There are no available options for this view.

Parent Directory Parent Directory | Revision <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Log">Log</a> Revision <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Log">Log</a>

Revision 1.12 - (show annotations) (download) (as text)
Mon Aug 1 20:29:24 2005 UTC (12 years, 5 months ago) by jgdavidson
Branch: MAIN
CVS Tags: aolserver_v45_r0, aolserver_v45_r2_rc0, HEAD
Branch point for: aolserver_v45_r1, aolserver_v45_r2, aolserver_v45_bp
Changes since 1.11: +14 -15 lines
File MIME type: text/x-chdr
Minor edits to silence the compiler.
1 /*
2 * The contents of this file are subject to the AOLserver Public License
3 * Version 1.1 (the "License"); you may not use this file except in
4 * compliance with the License. You may obtain a copy of the License at
5 * http://aolserver.com/.
6 *
7 * Software distributed under the License is distributed on an "AS IS"
8 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
9 * the License for the specific language governing rights and limitations
10 * under the License.
11 *
12 * The Original Code is AOLserver Code and related documentation
13 * distributed by AOL.
14 *
15 * The Initial Developer of the Original Code is America Online,
16 * Inc. Portions created by AOL are Copyright (C) 1999 America Online,
17 * Inc. All Rights Reserved.
18 *
19 * Alternatively, the contents of this file may be used under the terms
20 * of the GNU General Public License (the "GPL"), in which case the
21 * provisions of GPL are applicable instead of those above. If you wish
22 * to allow use of your version of this file only under the terms of the
23 * GPL and not to allow others to use your version of this file under the
24 * License, indicate your decision by deleting the provisions above and
25 * replace them with the notice and other provisions required by the GPL.
26 * If you do not delete the provisions above, a recipient may use your
27 * version of this file under either the License or the GPL.
28 */
29
30 /*
31 * tclimg.c --
32 *
33 * Commands for image files.
34 */
35
36 static const char *RCSID = "@(#) $Header: /cvsroot-fuse/aolserver/aolserver/nsd/tclimg.c,v 1.12 2005/08/01 20:29:24 jgdavidson Exp $, compiled: " __DATE__ " " __TIME__;
37
38 #include "nsd.h"
39
40 /*
41 * Local functions defined in this file
42 */
43
44 static int <a href="/cvs/aolserver/aolserver/nsd/tclimg.c#A_ChanGetc">ChanGetc</a>(Tcl_Channel chan);
45 static int <a href="/cvs/aolserver/aolserver/nsd/tclimg.c#A_JpegNextMarker">JpegNextMarker</a>(Tcl_Channel chan);
46 static int <a href="/cvs/aolserver/aolserver/nsd/tclimg.c#A_JpegSize">JpegSize</a>(Tcl_Channel chan, int *wPtr, int *hPtr);
47 static int <a href="/cvs/aolserver/aolserver/nsd/tclimg.c#A_JpegRead2Bytes">JpegRead2Bytes</a>(Tcl_Channel chan);
48 static int <a href="/cvs/aolserver/aolserver/nsd/tclimg.c#A_AppendObjDims">AppendObjDims</a>(Tcl_Interp *interp, int w, int h);
49
50
51 /*
52 *----------------------------------------------------------------------
53 *
54 * <a href="/cvs/aolserver/aolserver/nsd/tclimg.c#A_NsTclGifSizeObjCmd">NsTclGifSizeObjCmd</a> --
55 *
56 * Implements ns_gifsize, returning a list of width and height.
57 *
58 * Results:
59 * Tcl result.
60 *
61 * Side effects:
62 * See docs.
63 *
64 *----------------------------------------------------------------------
65 */
66
67 int
68 <a href="/cvs/aolserver/aolserver/nsd/tclimg.c#A_NsTclGifSizeObjCmd">NsTclGifSizeObjCmd</a>(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
69 {
70 int fd;
71 unsigned char buf[0x300];
72 int depth, colormap, dx, dy, status;
73 char *file;
74
75 if (objc != 2) {
76 Tcl_WrongNumArgs(interp, 1, objv, "gif");
77 return TCL_ERROR;
78 }
79 file = Tcl_GetString(objv[1]);
80 fd = open(file, O_RDONLY|O_BINARY);
81 if (fd == -1) {
82 Tcl_AppendResult(interp, "could not open \"", file, "\": ",
83 Tcl_PosixError(interp), NULL);
84 return TCL_ERROR;
85 }
86 status = TCL_ERROR;
87
88 /*
89 * Read the GIF version number
90 */
91
92 if (read(fd, buf, 6) != 6) {
93 readfail:
94 Tcl_AppendResult(interp, "could not read \"", file, "\": ",
95 Tcl_PosixError(interp), NULL);
96 goto done;
97 }
98
99 if (strncmp((char *) buf, "GIF87a", 6) &&
100 strncmp((char *) buf, "GIF89a", 6)) {
101 badfile:
102 Tcl_AppendResult(interp, "invalid gif file: ", file, NULL);
103 goto done;
104 }
105
106 if (read(fd, buf, 7) != 7) {
107 goto readfail;
108 }
109
110 depth = 1 << ((buf[4] & 0x7) + 1);
111 colormap = (buf[4] & 0x80 ? 1 : 0);
112
113 if (colormap) {
114 if (read(fd, buf, (size_t)(3*depth)) != (3*depth)) {
115 goto readfail;
116 }
117 }
118
119 outerloop:
120 if (read(fd, buf, 1) != 1) {
121 goto readfail;
122 }
123
124 if (buf[0] == '!') {
125 unsigned char count;
126
127 if (read(fd, buf, 1) != 1) {
128 goto readfail;
129 }
130 innerloop:
131 if (read(fd, (char *) &count, 1) != 1) {
132 goto readfail;
133 }
134 if (count == 0) {
135 goto outerloop;
136 }
137 if (read(fd, buf, count) != count) {
138 goto readfail;
139 }
140 goto innerloop;
141 } else if (buf[0] != ',') {
142 goto badfile;
143 }
144
145 if (read(fd,buf,9) != 9) {
146 goto readfail;
147 }
148
149 dx = 0x100 * buf[5] + buf[4];
150 dy = 0x100 * buf[7] + buf[6];
151 if(<a href="/cvs/aolserver/aolserver/nsd/tclimg.c#A_AppendObjDims">AppendObjDims</a>(interp, dx, dy) != TCL_OK) {
152 return TCL_ERROR;
153 };
154 status = TCL_OK;
155
156 done:
157 close(fd);
158 return status;
159 }
160
161
162 /*
163 *----------------------------------------------------------------------
164 *
165 * <a href="/cvs/aolserver/aolserver/nsd/tclimg.c#A_NsTclJpegSizeObjCmd">NsTclJpegSizeObjCmd</a> --
166 *
167 * Implements ns_jpegsize as obj command.
168 *
169 * Results:
170 * Tcl result.
171 *
172 * Side effects:
173 * See docs.
174 *
175 *----------------------------------------------------------------------
176 */
177
178 int
179 <a href="/cvs/aolserver/aolserver/nsd/tclimg.c#A_NsTclJpegSizeObjCmd">NsTclJpegSizeObjCmd</a>(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
180 {
181 int code, w = 0, h = 0;
182 Tcl_Channel chan;
183 char *file;
184
185 if (objc != 2) {
186 Tcl_WrongNumArgs(interp, 1, objv, "file");
187 return TCL_ERROR;
188 }
189 file = Tcl_GetString(objv[1]);
190 chan = Tcl_OpenFileChannel(interp, file, "r", 0);
191 if (chan == NULL) {
192 /* Tcl function will leave error message in interp's result */
193 return TCL_ERROR;
194 }
195 if (Tcl_SetChannelOption(interp, chan, "-translation", "binary") != TCL_OK) {
196 /* Tcl function will leave error message in interp's result */
197 return TCL_ERROR;
198 }
199 code = <a href="/cvs/aolserver/aolserver/nsd/tclimg.c#A_JpegSize">JpegSize</a>(chan, &w, &h);
200 Tcl_Close(interp, chan);
201 if (code != TCL_OK) {
202 Tcl_AppendResult(interp, "invalid jpeg file: ", file, NULL);
203 return TCL_ERROR;
204 }
205 if(<a href="/cvs/aolserver/aolserver/nsd/tclimg.c#A_AppendObjDims">AppendObjDims</a>(interp, w, h) != TCL_OK) {
206 return TCL_ERROR;
207 };
208 return TCL_OK;
209 }
210
211 #define M_SOI 0xD8 /* Start Of Image (beginning of datastream) */
212 #define M_EOI 0xD9 /* End Of Image (end of datastream) */
213 #define M_SOS 0xDA /* Start Of Scan (begins compressed data) */
214
215 static int
216 <a href="/cvs/aolserver/aolserver/nsd/tclimg.c#A_JpegSize">JpegSize</a>(Tcl_Channel chan, int *wPtr, int *hPtr)
217 {
218 unsigned int i, w, h;
219 Tcl_WideInt numbytes;
220
221 if (<a href="/cvs/aolserver/aolserver/nsd/tclimg.c#A_ChanGetc">ChanGetc</a>(chan) == 0xFF && <a href="/cvs/aolserver/aolserver/nsd/tclimg.c#A_ChanGetc">ChanGetc</a>(chan) == M_SOI) {
222 while (1) {
223 i = <a href="/cvs/aolserver/aolserver/nsd/tclimg.c#A_JpegNextMarker">JpegNextMarker</a>(chan);
224 if (i == EOF || i == M_SOS || i == M_EOI) {
225 break;
226 }
227 if (0xC0 <= i && i <= 0xC3) {
228 if (<a href="/cvs/aolserver/aolserver/nsd/tclimg.c#A_JpegRead2Bytes">JpegRead2Bytes</a>(chan) != EOF && <a href="/cvs/aolserver/aolserver/nsd/tclimg.c#A_ChanGetc">ChanGetc</a>(chan) != EOF
229 && (h = <a href="/cvs/aolserver/aolserver/nsd/tclimg.c#A_JpegRead2Bytes">JpegRead2Bytes</a>(chan)) != EOF
230 && (w = <a href="/cvs/aolserver/aolserver/nsd/tclimg.c#A_JpegRead2Bytes">JpegRead2Bytes</a>(chan)) != EOF) {
231 *wPtr = w;
232 *hPtr = h;
233 return TCL_OK;
234 }
235 break;
236 }
237 numbytes = <a href="/cvs/aolserver/aolserver/nsd/tclimg.c#A_JpegRead2Bytes">JpegRead2Bytes</a>(chan);
238 if (numbytes < 2 || Tcl_Seek(chan, numbytes - 2, SEEK_CUR) == -1) {
239 break;
240 }
241 }
242 }
243 return TCL_ERROR;
244 }
245
246
247 /*
248 *----------------------------------------------------------------------
249 *
250 * <a href="/cvs/aolserver/aolserver/nsd/tclimg.c#A_JpegRead2Bytes">JpegRead2Bytes</a> --
251 *
252 * Read 2 bytes, convert to unsigned int. All 2-byte quantities
253 * in JPEG markers are MSB first.
254 *
255 * Results:
256 * The two byte value, or -1 on error.
257 *
258 * Side effects:
259 * Advances file pointer.
260 *
261 *----------------------------------------------------------------------
262 */
263
264 static int
265 <a href="/cvs/aolserver/aolserver/nsd/tclimg.c#A_JpegRead2Bytes">JpegRead2Bytes</a>(Tcl_Channel chan)
266 {
267 int c1, c2;
268
269 c1 = <a href="/cvs/aolserver/aolserver/nsd/tclimg.c#A_ChanGetc">ChanGetc</a>(chan);
270 c2 = <a href="/cvs/aolserver/aolserver/nsd/tclimg.c#A_ChanGetc">ChanGetc</a>(chan);
271 if (c1 == EOF || c2 == EOF) {
272 return -1;
273 }
274 return (int)(((unsigned int) c1) << 8) + ((unsigned int) c2);
275 }
276
277
278 /*
279 *----------------------------------------------------------------------
280 *
281 * <a href="/cvs/aolserver/aolserver/nsd/tclimg.c#A_JpegNextMarker">JpegNextMarker</a> --
282 *
283 * Find the next JPEG marker and return its marker code. We
284 * expect at least one FF byte, possibly more if the compressor
285 * used FFs to pad the file. There could also be non-FF garbage
286 * between markers. The treatment of such garbage is
287 * unspecified; we choose to skip over it but emit a warning
288 * msg. This routine must not be used after seeing SOS marker,
289 * since it will not deal correctly with FF/00 sequences in the
290 * compressed image data...
291 *
292 * Results:
293 * The next marker code.
294 *
295 * Side effects:
296 * Will eat up any duplicate FF bytes.
297 *
298 *----------------------------------------------------------------------
299 */
300
301 static int
302 <a href="/cvs/aolserver/aolserver/nsd/tclimg.c#A_JpegNextMarker">JpegNextMarker</a>(Tcl_Channel chan)
303 {
304 int c;
305
306 /*
307 * Find 0xFF byte; count and skip any non-FFs.
308 */
309
310 c = <a href="/cvs/aolserver/aolserver/nsd/tclimg.c#A_ChanGetc">ChanGetc</a>(chan);
311 while (c != EOF && c != 0xFF) {
312 c = <a href="/cvs/aolserver/aolserver/nsd/tclimg.c#A_ChanGetc">ChanGetc</a>(chan);
313 }
314 if (c != EOF) {
315 /*
316 * Get marker code byte, swallowing any duplicate FF bytes.
317 */
318
319 do {
320 c = <a href="/cvs/aolserver/aolserver/nsd/tclimg.c#A_ChanGetc">ChanGetc</a>(chan);
321 } while (c == 0xFF);
322 }
323
324 return c;
325 }
326
327
328 /*
329 *----------------------------------------------------------------------
330 *
331 * <a href="/cvs/aolserver/aolserver/nsd/tclimg.c#A_ChanGetc">ChanGetc</a> --
332 *
333 * Read a single unsigned char from a channel.
334 *
335 * Results:
336 * Character or EOF.
337 *
338 * Side effects:
339 * None.
340 *
341 *----------------------------------------------------------------------
342 */
343
344 static int
345 <a href="/cvs/aolserver/aolserver/nsd/tclimg.c#A_ChanGetc">ChanGetc</a>(Tcl_Channel chan)
346 {
347 unsigned char buf[1];
348
349 if (Tcl_Read(chan, (char *) buf, 1) != 1) {
350 return EOF;
351 }
352 return (int) buf[0];
353 }
354
355
356 /*
357 *----------------------------------------------------------------------
358 *
359 * <a href="/cvs/aolserver/aolserver/nsd/tclimg.c#A_AppendObjDims">AppendObjDims</a> --
360 *
361 * Format and append width and height dimensions.
362 *
363 * Results:
364 * None.
365 *
366 * Side effects:
367 * List elements appended to interp result.
368 *
369 *----------------------------------------------------------------------
370 */
371
372 static int
373 <a href="/cvs/aolserver/aolserver/nsd/tclimg.c#A_AppendObjDims">AppendObjDims</a>(Tcl_Interp *interp, int w, int h)
374 {
375 char buf[20];
376 Tcl_Obj *result = Tcl_NewObj();
377
378 sprintf(buf, "%d", w);
379 if (Tcl_ListObjAppendElement(interp, result, Tcl_NewStringObj(buf, -1))) {
380 return TCL_ERROR;
381 }
382 sprintf(buf, "%d", h);
383 if (Tcl_ListObjAppendElement(interp, result, Tcl_NewStringObj(buf, -1))) {
384 return TCL_ERROR;
385 }
386
387 Tcl_SetObjResult(interp, result);
388
389 return TCL_OK;
390 }