blob: 1429931f8c6dba78ce9967a8be296126a22d011c [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1995-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26#include <stdio.h>
27#include "jni.h"
28#include "jni_util.h"
29
30#define OUTCODELENGTH 4097
31
32/* We use Get/ReleasePrimitiveArrayCritical functions to avoid
33 * the need to copy buffer elements.
34 *
35 * MAKE SURE TO:
36 *
37 * - carefully insert pairs of RELEASE_ARRAYS and GET_ARRAYS around
38 * callbacks to Java.
39 * - call RELEASE_ARRAYS before returning to Java.
40 *
41 * Otherwise things will go horribly wrong. There may be memory leaks,
42 * excessive pinning, or even VM crashes!
43 *
44 * Note that GetPrimitiveArrayCritical may fail!
45 */
46
47#define GET_ARRAYS() \
48 prefix = (short *) \
49 (*env)->GetPrimitiveArrayCritical(env, prefixh, 0); \
50 if (prefix == 0) \
51 goto out_of_memory; \
52 suffix = (unsigned char *) \
53 (*env)->GetPrimitiveArrayCritical(env, suffixh, 0); \
54 if (suffix == 0) \
55 goto out_of_memory; \
56 outCode = (unsigned char *) \
57 (*env)->GetPrimitiveArrayCritical(env, outCodeh, 0); \
58 if (outCode == 0) \
59 goto out_of_memory; \
60 rasline = (unsigned char *) \
61 (*env)->GetPrimitiveArrayCritical(env, raslineh, 0); \
62 if (rasline == 0) \
63 goto out_of_memory; \
64 block = (unsigned char *) \
65 (*env)->GetPrimitiveArrayCritical(env, blockh, 0); \
66 if (block == 0) \
67 goto out_of_memory
68
69/*
70 * Note that it is important to check whether the arrays are NULL,
71 * because GetPrimitiveArrayCritical might have failed.
72 */
73#define RELEASE_ARRAYS() \
74if (prefix) \
75 (*env)->ReleasePrimitiveArrayCritical(env, prefixh, prefix, 0); \
76if (suffix) \
77 (*env)->ReleasePrimitiveArrayCritical(env, suffixh, suffix, 0); \
78if (outCode) \
79 (*env)->ReleasePrimitiveArrayCritical(env, outCodeh, outCode, 0); \
80if (rasline) \
81 (*env)->ReleasePrimitiveArrayCritical(env, raslineh, rasline, 0); \
82if (block) \
83 (*env)->ReleasePrimitiveArrayCritical(env, blockh, block, 0)
84
85/* Place holders for the old native interface. */
86
87long
88sun_awt_image_GifImageDecoder_parseImage()
89{
90 return 0;
91}
92
93void
94sun_awt_image_GifImageDecoder_initIDs()
95{
96}
97
98static jmethodID readID;
99static jmethodID sendID;
100static jfieldID prefixID;
101static jfieldID suffixID;
102static jfieldID outCodeID;
103
104JNIEXPORT void JNICALL
105Java_sun_awt_image_GifImageDecoder_initIDs(JNIEnv *env, jclass this)
106{
107 readID = (*env)->GetMethodID(env, this, "readBytes", "([BII)I");
108 sendID = (*env)->GetMethodID(env, this, "sendPixels",
109 "(IIII[BLjava/awt/image/ColorModel;)I");
110 prefixID = (*env)->GetFieldID(env, this, "prefix", "[S");
111 suffixID = (*env)->GetFieldID(env, this, "suffix", "[B");
112 outCodeID = (*env)->GetFieldID(env, this, "outCode", "[B");
113}
114
115JNIEXPORT jboolean JNICALL
116Java_sun_awt_image_GifImageDecoder_parseImage(JNIEnv *env,
117 jobject this,
118 jint relx, jint rely,
119 jint width, jint height,
120 jint interlace,
121 jint initCodeSize,
122 jbyteArray blockh,
123 jbyteArray raslineh,
124 jobject cmh)
125{
126 /* Patrick Naughton:
127 * Note that I ignore the possible existence of a local color map.
128 * I'm told there aren't many files around that use them, and the
129 * spec says it's defined for future use. This could lead to an
130 * error reading some files.
131 *
132 * Start reading the image data. First we get the intial code size
133 * and compute decompressor constant values, based on this code
134 * size.
135 *
136 * The GIF spec has it that the code size is the code size used to
137 * compute the above values is the code size given in the file,
138 * but the code size used in compression/decompression is the code
139 * size given in the file plus one. (thus the ++).
140 *
141 * Arthur van Hoff:
142 * The following narly code reads LZW compressed data blocks and
143 * dumps it into the image data. The input stream is broken up into
144 * blocks of 1-255 characters, each preceded by a length byte.
145 * 3-12 bit codes are read from these blocks. The codes correspond to
146 * entry is the hashtable (the prefix, suffix stuff), and the appropriate
147 * pixels are written to the image.
148 */
149 static int verbose = 0;
150
151 int clearCode = (1 << initCodeSize);
152 int eofCode = clearCode + 1;
153 int bitMask;
154 int curCode;
155 int outCount;
156
157 /* Variables used to form reading data */
158 int blockEnd = 0;
159 int remain = 0;
160 int byteoff = 0;
161 int accumbits = 0;
162 int accumdata = 0;
163
164 /* Variables used to decompress the data */
165 int codeSize = initCodeSize + 1;
166 int maxCode = 1 << codeSize;
167 int codeMask = maxCode - 1;
168 int freeCode = clearCode + 2;
169 int code = 0;
170 int oldCode = 0;
171 unsigned char prevChar = 0;
172
173 /* Temproray storage for decompression */
174 short *prefix;
175 unsigned char *suffix = NULL;
176 unsigned char *outCode = NULL;
177 unsigned char *rasline = NULL;
178 unsigned char *block = NULL;
179
180 jshortArray prefixh = (*env)->GetObjectField(env, this, prefixID);
181 jbyteArray suffixh = (*env)->GetObjectField(env, this, suffixID);
182 jbyteArray outCodeh = (*env)->GetObjectField(env, this, outCodeID);
183
184 int blockLength = 0;
185
186 /* Variables used for writing pixels */
187 int x = width;
188 int y = 0;
189 int off = 0;
190 int passinc = interlace ? 8 : 1;
191 int passht = passinc;
192 int len;
193
194 if (blockh == 0 || raslineh == 0
195 || prefixh == 0 || suffixh == 0
196 || outCodeh == 0)
197 {
198 JNU_ThrowNullPointerException(env, 0);
199 return 0;
200 }
201 if (((*env)->GetArrayLength(env, prefixh) != 4096) ||
202 ((*env)->GetArrayLength(env, suffixh) != 4096) ||
203 ((*env)->GetArrayLength(env, outCodeh) != OUTCODELENGTH))
204 {
205 JNU_ThrowArrayIndexOutOfBoundsException(env, 0);
206 return 0;
207 }
208
209 if (verbose) {
210 fprintf(stdout, "Decompressing...");
211 }
212
213 /* Fix for bugid 4216605 Some animated GIFs display corrupted. */
214 bitMask = clearCode - 1;
215
216 GET_ARRAYS();
217
218 /* Read codes until the eofCode is encountered */
219 for (;;) {
220 if (accumbits < codeSize) {
221 /* fill the buffer if needed */
222 while (remain < 2) {
223 if (blockEnd) {
224 /* Sometimes we have one last byte to process... */
225 if (remain == 1 && accumbits + 8 >= codeSize) {
226 remain--;
227 goto last_byte;
228 }
229 RELEASE_ARRAYS();
230 if (off > 0) {
231 (*env)->CallIntMethod(env, this, sendID,
232 relx, rely + y,
233 width, passht,
234 raslineh, cmh);
235 }
236 /* quietly accept truncated GIF images */
237 return 1;
238 }
239 /* move remaining bytes to the beginning of the buffer */
240 block[0] = block[byteoff];
241 byteoff = 0;
242
243 RELEASE_ARRAYS();
244 /* fill the block */
245 len = (*env)->CallIntMethod(env, this, readID,
246 blockh, remain, blockLength + 1);
247 if ((*env)->ExceptionOccurred(env)) {
248 return 0;
249 }
250 GET_ARRAYS();
251
252 remain += blockLength;
253 if (len > 0) {
254 remain -= (len - 1);
255 blockLength = 0;
256 } else {
257 blockLength = block[remain];
258 }
259 if (blockLength == 0) {
260 blockEnd = 1;
261 }
262 }
263 remain -= 2;
264
265 /* 2 bytes at a time saves checking for accumbits < codeSize.
266 * We know we'll get enough and also that we can't overflow
267 * since codeSize <= 12.
268 */
269 accumdata += (block[byteoff++] & 0xff) << accumbits;
270 accumbits += 8;
271 last_byte:
272 accumdata += (block[byteoff++] & 0xff) << accumbits;
273 accumbits += 8;
274 }
275
276 /* Compute the code */
277 code = accumdata & codeMask;
278 accumdata >>= codeSize;
279 accumbits -= codeSize;
280
281 /*
282 * Interpret the code
283 */
284 if (code == clearCode) {
285 /* Clear code sets everything back to its initial value, then
286 * reads the immediately subsequent code as uncompressed data.
287 */
288 if (verbose) {
289 fprintf(stdout, ".");
290 fflush(stdout);
291 }
292
293 /* Note that freeCode is one less than it is supposed to be,
294 * this is because it will be incremented next time round the loop
295 */
296 freeCode = clearCode + 1;
297 codeSize = initCodeSize + 1;
298 maxCode = 1 << codeSize;
299 codeMask = maxCode - 1;
300
301 /* Continue if we've NOT reached the end, some Gif images
302 * contain bogus codes after the last clear code.
303 */
304 if (y < height) {
305 continue;
306 }
307
308 /* pretend we've reached the end of the data */
309 code = eofCode;
310 }
311
312 if (code == eofCode) {
313 /* make sure we read the whole block of pixels. */
314 flushit:
315 while (!blockEnd) {
316 if (verbose) {
317 fprintf(stdout, "flushing %d bytes\n", blockLength);
318 }
319 RELEASE_ARRAYS();
320 if ((*env)->CallIntMethod(env, this, readID,
321 blockh, 0, blockLength + 1) != 0
322 || (*env)->ExceptionOccurred(env))
323 {
324 /* quietly accept truncated GIF images */
325 return (!(*env)->ExceptionOccurred(env));
326 }
327 GET_ARRAYS();
328 blockLength = block[blockLength];
329 blockEnd = (blockLength == 0);
330 }
331 RELEASE_ARRAYS();
332 return 1;
333 }
334
335 /* It must be data: save code in CurCode */
336 curCode = code;
337 outCount = OUTCODELENGTH;
338
339 /* If greater or equal to freeCode, not in the hash table
340 * yet; repeat the last character decoded
341 */
342 if (curCode >= freeCode) {
343 if (curCode > freeCode) {
344 /*
345 * if we get a code too far outside our range, it
346 * could case the parser to start traversing parts
347 * of our data structure that are out of range...
348 */
349 goto flushit;
350 }
351 curCode = oldCode;
352 outCode[--outCount] = prevChar;
353 }
354
355 /* Unless this code is raw data, pursue the chain pointed
356 * to by curCode through the hash table to its end; each
357 * code in the chain puts its associated output code on
358 * the output queue.
359 */
360 while (curCode > bitMask) {
361 outCode[--outCount] = suffix[curCode];
362 if (outCount == 0) {
363 /*
364 * In theory this should never happen since our
365 * prefix and suffix arrays are monotonically
366 * decreasing and so outCode will only be filled
367 * as much as those arrays, but I don't want to
368 * take that chance and the test is probably
369 * cheap compared to the read and write operations.
370 * If we ever do overflow the array, we will just
371 * flush the rest of the data and quietly accept
372 * the GIF as truncated here.
373 */
374 goto flushit;
375 }
376 curCode = prefix[curCode];
377 }
378
379 /* The last code in the chain is treated as raw data. */
380 prevChar = (unsigned char)curCode;
381 outCode[--outCount] = prevChar;
382
383 /* Now we put the data out to the Output routine. It's
384 * been stacked LIFO, so deal with it that way...
385 *
386 * Note that for some malformed images we have to skip
387 * current frame and continue with rest of data
388 * because we may have not enough info to interpret
389 * corrupted frame correctly.
390 * However, we can not skip frame without decoding it
391 * and therefore we have to continue looping through data
392 * but skip internal output loop.
393 *
394 * In particular this is is possible when
395 * width of the frame is set to zero. If
396 * global width (i.e. width of the logical screen)
397 * is zero too then zero-length scanline buffer
398 * is allocated in java code and we have no buffer to
399 * store decoded data in.
400 */
401 len = OUTCODELENGTH - outCount;
402 while ((width > 0) && (--len >= 0)) {
403 rasline[off++] = outCode[outCount++];
404
405 /* Update the X-coordinate, and if it overflows, update the
406 * Y-coordinate
407 */
408 if (--x == 0) {
409 /* If a non-interlaced picture, just increment y to the next
410 * scan line. If it's interlaced, deal with the interlace as
411 * described in the GIF spec. Put the decoded scan line out
412 * to the screen if we haven't gone past the bottom of it
413 */
414 int count;
415 RELEASE_ARRAYS();
416 count = (*env)->CallIntMethod(env, this, sendID,
417 relx, rely + y,
418 width, passht,
419 raslineh, cmh);
420 if (count <= 0 || (*env)->ExceptionOccurred(env)) {
421 /* Nobody is listening any more. */
422 if (verbose) {
423 fprintf(stdout, "Orphan gif decoder quitting\n");
424 }
425 return 0;
426 }
427 GET_ARRAYS();
428 x = width;
429 off = 0;
430 /* pass inc ht ystart */
431 /* 0 8 8 0 */
432 /* 1 8 4 4 */
433 /* 2 4 2 2 */
434 /* 3 2 1 1 */
435 y += passinc;
436 while (y >= height) {
437 passinc = passht;
438 passht >>= 1;
439 y = passht;
440 if (passht == 0) {
441 goto flushit;
442 }
443 }
444 }
445 }
446
447 /* Build the hash table on-the-fly. No table is stored in the file. */
448 prefix[freeCode] = (short)oldCode;
449 suffix[freeCode] = prevChar;
450 oldCode = code;
451
452 /* Point to the next slot in the table. If we exceed the
453 * maxCode, increment the code size unless
454 * it's already 12. If it is, do nothing: the next code
455 * decompressed better be CLEAR
456 */
457 if (++freeCode >= maxCode) {
458 if (codeSize < 12) {
459 codeSize++;
460 maxCode <<= 1;
461 codeMask = maxCode - 1;
462 } else {
463 /* Just in case */
464 freeCode = maxCode - 1;
465 }
466 }
467 }
468out_of_memory:
469 RELEASE_ARRAYS();
470 return 0;
471}