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 | } |
Copyright © 2010 Geeknet, Inc. All rights reserved. Terms of Use