90 #define READ_NO_EOI 0
91
92 /* Writer warnings */
93
94 /* Return codes for various ops */
95 #define OK 1
96 #define NOT_OK 0
97
98 /*
99 * First we define two objects, one for the stream and buffer and one
100 * for pixels. Both contain references to Java objects and pointers to
101 * pinned arrays. These objects can be used for either input or
102 * output. Pixels can be accessed as either INT32s or bytes.
103 * Every I/O operation will have one of each these objects, one for
104 * the stream and the other to hold pixels, regardless of the I/O direction.
105 */
106
107 /******************** StreamBuffer definition ************************/
108
109 typedef struct streamBufferStruct {
110 jobject stream; // ImageInputStream or ImageOutputStream
111 jbyteArray hstreamBuffer; // Handle to a Java buffer for the stream
112 JOCTET *buf; // Pinned buffer pointer */
113 int bufferOffset; // holds offset between unpin and the next pin
114 int bufferLength; // Allocated, nut just used
115 int suspendable; // Set to true to suspend input
116 long remaining_skip; // Used only on input
117 } streamBuffer, *streamBufferPtr;
118
119 /*
120 * This buffer size was set to 64K in the old classes, 4K by default in the
121 * IJG library, with the comment "an efficiently freadable size", and 1K
122 * in AWT.
123 * Unlike in the other Java designs, these objects will persist, so 64K
124 * seems too big and 1K seems too small. If 4K was good enough for the
125 * IJG folks, it's good enough for me.
126 */
127 #define STREAMBUF_SIZE 4096
128
129 /*
130 * Used to signal that no data need be restored from an unpin to a pin.
131 * I.e. the buffer is empty.
132 */
133 #define NO_DATA -1
134
135 // Forward reference
136 static void resetStreamBuffer(JNIEnv *env, streamBufferPtr sb);
137
138 /*
139 * Initialize a freshly allocated StreamBuffer object. The stream is left
140 * null, as it will be set from Java by setSource, but the buffer object
141 * is created and a global reference kept. Returns OK on success, NOT_OK
142 * if allocating the buffer or getting a global reference for it failed.
143 */
144 static int initStreamBuffer(JNIEnv *env, streamBufferPtr sb) {
145 /* Initialize a new buffer */
146 jbyteArray hInputBuffer = (*env)->NewByteArray(env, STREAMBUF_SIZE);
147 if (hInputBuffer == NULL) {
148 JNU_ThrowByName( env,
149 "java/lang/OutOfMemoryError",
150 "Initializing Reader");
151 return NOT_OK;
152 }
153 sb->bufferLength = (*env)->GetArrayLength(env, hInputBuffer);
154 sb->hstreamBuffer = (*env)->NewGlobalRef(env, hInputBuffer);
155 if (sb->hstreamBuffer == NULL) {
156 JNU_ThrowByName( env,
157 "java/lang/OutOfMemoryError",
158 "Initializing Reader");
159 return NOT_OK;
160 }
161
162
163 sb->stream = NULL;
164
165 sb->buf = NULL;
166
167 resetStreamBuffer(env, sb);
168
169 return OK;
170 }
171
172 /*
173 * Free all resources associated with this streamBuffer. This must
174 * be called to dispose the object to avoid leaking global references, as
175 * resetStreamBuffer does not release the buffer reference.
176 */
177 static void destroyStreamBuffer(JNIEnv *env, streamBufferPtr sb) {
178 resetStreamBuffer(env, sb);
179 if (sb->hstreamBuffer != NULL) {
180 (*env)->DeleteGlobalRef(env, sb->hstreamBuffer);
181 }
182 }
183
184 // Forward reference
185 static void unpinStreamBuffer(JNIEnv *env,
186 streamBufferPtr sb,
187 const JOCTET *next_byte);
188 /*
189 * Resets the state of a streamBuffer object that has been in use.
190 * The global reference to the stream is released, but the reference
191 * to the buffer is retained. The buffer is unpinned if it was pinned.
192 * All other state is reset.
193 */
194 static void resetStreamBuffer(JNIEnv *env, streamBufferPtr sb) {
195 if (sb->stream != NULL) {
196 (*env)->DeleteGlobalRef(env, sb->stream);
197 sb->stream = NULL;
198 }
199 unpinStreamBuffer(env, sb, NULL);
200 sb->bufferOffset = NO_DATA;
201 sb->suspendable = FALSE;
202 sb->remaining_skip = 0;
203 }
204
205 /*
206 * Pins the data buffer associated with this stream. Returns OK on
207 * success, NOT_OK on failure, as GetPrimitiveArrayCritical may fail.
208 */
209 static int pinStreamBuffer(JNIEnv *env,
210 streamBufferPtr sb,
211 const JOCTET **next_byte) {
212 if (sb->hstreamBuffer != NULL) {
213 assert(sb->buf == NULL);
214 sb->buf =
215 (JOCTET *)(*env)->GetPrimitiveArrayCritical(env,
216 sb->hstreamBuffer,
217 NULL);
565 if (cinfo->is_decompressor) {
566 (*env)->CallVoidMethod(env, theObject,
567 JPEGImageReader_warningWithMessageID,
568 string);
569 } else {
570 (*env)->CallVoidMethod(env, theObject,
571 JPEGImageWriter_warningWithMessageID,
572 string);
573 }
574 }
575
576 /* End of verbatim copy from jpegdecoder.c */
577
578 /*************** end of error handling *********************/
579
580 /*************** Shared utility code ***********************/
581
582 static void imageio_set_stream(JNIEnv *env,
583 j_common_ptr cinfo,
584 imageIODataPtr data,
585 jobject stream){
586 streamBufferPtr sb;
587 sun_jpeg_error_ptr jerr;
588
589 sb = &data->streamBuf;
590
591 resetStreamBuffer(env, sb); // Removes any old stream
592
593 /* Now we need a new global reference for the stream */
594 if (stream != NULL) { // Fix for 4411955
595 sb->stream = (*env)->NewGlobalRef(env, stream);
596 if (sb->stream == NULL) {
597 JNU_ThrowByName(env,
598 "java/lang/OutOfMemoryError",
599 "Setting Stream");
600 return;
601 }
602 }
603
604 /* And finally reset state */
605 data->abortFlag = JNI_FALSE;
606
607 /* Establish the setjmp return context for sun_jpeg_error_exit to use. */
608 jerr = (sun_jpeg_error_ptr) cinfo->err;
609
610 if (setjmp(jerr->setjmp_buffer)) {
611 /* If we get here, the JPEG code has signaled an error
612 while aborting. */
613 if (!(*env)->ExceptionOccurred(env)) {
614 char buffer[JMSG_LENGTH_MAX];
615 (*cinfo->err->format_message) (cinfo,
616 buffer);
617 JNU_ThrowByName(env, "javax/imageio/IIOException", buffer);
618 }
619 return;
889 * if TRUE is returned. A FALSE return should only be used when I/O
890 * suspension is desired (this mode is discussed in the next section).
891 */
892 /*
893 * Note that with I/O suspension turned on, this procedure should not
894 * do any work since the JPEG library has a very simple backtracking
895 * mechanism which relies on the fact that the buffer will be filled
896 * only when it has backed out to the top application level. When
897 * suspendable is turned on, imageio_fill_suspended_buffer will
898 * do the actual work of filling the buffer.
899 */
900
901 GLOBAL(boolean)
902 imageio_fill_input_buffer(j_decompress_ptr cinfo)
903 {
904 struct jpeg_source_mgr *src = cinfo->src;
905 imageIODataPtr data = (imageIODataPtr) cinfo->client_data;
906 streamBufferPtr sb = &data->streamBuf;
907 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
908 int ret;
909
910 /* This is where input suspends */
911 if (sb->suspendable) {
912 return FALSE;
913 }
914
915 #ifdef DEBUG
916 printf("Filling input buffer, remaining skip is %ld, ",
917 sb->remaining_skip);
918 printf("Buffer length is %d\n", sb->bufferLength);
919 #endif
920
921 /*
922 * Definitively skips. Could be left over if we tried to skip
923 * more than a buffer's worth but suspended when getting the next
924 * buffer. Now we aren't suspended, so we can catch up.
925 */
926 if (sb->remaining_skip) {
927 src->skip_input_data(cinfo, 0);
928 }
929
930 /*
931 * Now fill a complete buffer, or as much of one as the stream
932 * will give us if we are near the end.
933 */
934 RELEASE_ARRAYS(env, data, src->next_input_byte);
935 ret = (*env)->CallIntMethod(env,
936 sb->stream,
937 JPEGImageReader_readInputDataID,
938 sb->hstreamBuffer, 0,
939 sb->bufferLength);
940 if ((*env)->ExceptionOccurred(env)
941 || !GET_ARRAYS(env, data, &(src->next_input_byte))) {
942 cinfo->err->error_exit((j_common_ptr) cinfo);
943 }
944
945 #ifdef DEBUG
946 printf("Buffer filled. ret = %d\n", ret);
947 #endif
948 /*
949 * If we have reached the end of the stream, then the EOI marker
950 * is missing. We accept such streams but generate a warning.
951 * The image is likely to be corrupted, though everything through
952 * the end of the last complete MCU should be usable.
953 */
954 if (ret <= 0) {
955 jobject reader = data->imageIOobj;
956 #ifdef DEBUG
976 return TRUE;
977 }
978
979 /*
980 * With I/O suspension turned on, the JPEG library requires that all
981 * buffer filling be done at the top application level, using this
982 * function. Due to the way that backtracking works, this procedure
983 * saves all of the data that was left in the buffer when suspension
984 * occured and read new data only at the end.
985 */
986
987 GLOBAL(void)
988 imageio_fill_suspended_buffer(j_decompress_ptr cinfo)
989 {
990 struct jpeg_source_mgr *src = cinfo->src;
991 imageIODataPtr data = (imageIODataPtr) cinfo->client_data;
992 streamBufferPtr sb = &data->streamBuf;
993 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
994 jint ret;
995 int offset, buflen;
996
997 /*
998 * The original (jpegdecoder.c) had code here that called
999 * InputStream.available and just returned if the number of bytes
1000 * available was less than any remaining skip. Presumably this was
1001 * to avoid blocking, although the benefit was unclear, as no more
1002 * decompression can take place until more data is available, so
1003 * the code would block on input a little further along anyway.
1004 * ImageInputStreams don't have an available method, so we'll just
1005 * block in the skip if we have to.
1006 */
1007
1008 if (sb->remaining_skip) {
1009 src->skip_input_data(cinfo, 0);
1010 }
1011
1012 /* Save the data currently in the buffer */
1013 offset = src->bytes_in_buffer;
1014 if (src->next_input_byte > sb->buf) {
1015 memcpy(sb->buf, src->next_input_byte, offset);
1016 }
1017 RELEASE_ARRAYS(env, data, src->next_input_byte);
1018 buflen = sb->bufferLength - offset;
1019 if (buflen <= 0) {
1020 if (!GET_ARRAYS(env, data, &(src->next_input_byte))) {
1021 cinfo->err->error_exit((j_common_ptr) cinfo);
1022 }
1023 return;
1024 }
1025
1026 ret = (*env)->CallIntMethod(env, sb->stream,
1027 JPEGImageReader_readInputDataID,
1028 sb->hstreamBuffer,
1029 offset, buflen);
1030 if ((*env)->ExceptionOccurred(env)
1031 || !GET_ARRAYS(env, data, &(src->next_input_byte))) {
1032 cinfo->err->error_exit((j_common_ptr) cinfo);
1033 }
1034 /*
1035 * If we have reached the end of the stream, then the EOI marker
1036 * is missing. We accept such streams but generate a warning.
1037 * The image is likely to be corrupted, though everything through
1038 * the end of the last complete MCU should be usable.
1039 */
1040 if (ret <= 0) {
1041 jobject reader = data->imageIOobj;
1042 RELEASE_ARRAYS(env, data, src->next_input_byte);
1043 (*env)->CallVoidMethod(env, reader,
1044 JPEGImageReader_warningOccurredID,
1045 READ_NO_EOI);
1046 if ((*env)->ExceptionOccurred(env)
1069 * buffer.
1070 *
1071 * A negative skip count is treated as a no-op. A zero skip count
1072 * skips any remaining skip from a previous skip while suspended.
1073 *
1074 * Note that with I/O suspension turned on, this procedure does not
1075 * call skipBytes since the JPEG library has a very simple backtracking
1076 * mechanism which relies on the fact that the application level has
1077 * exclusive control over actual I/O.
1078 */
1079
1080 GLOBAL(void)
1081 imageio_skip_input_data(j_decompress_ptr cinfo, long num_bytes)
1082 {
1083 struct jpeg_source_mgr *src = cinfo->src;
1084 imageIODataPtr data = (imageIODataPtr) cinfo->client_data;
1085 streamBufferPtr sb = &data->streamBuf;
1086 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
1087 jlong ret;
1088 jobject reader;
1089
1090 if (num_bytes < 0) {
1091 return;
1092 }
1093 num_bytes += sb->remaining_skip;
1094 sb->remaining_skip = 0;
1095
1096 /* First the easy case where we are skipping <= the current contents. */
1097 ret = src->bytes_in_buffer;
1098 if (ret >= num_bytes) {
1099 src->next_input_byte += num_bytes;
1100 src->bytes_in_buffer -= num_bytes;
1101 return;
1102 }
1103
1104 /*
1105 * We are skipping more than is in the buffer. We empty the buffer and,
1106 * if we aren't suspended, call the Java skipBytes method. We always
1107 * leave the buffer empty, to be filled by either fill method above.
1108 */
1109 src->bytes_in_buffer = 0;
1110 src->next_input_byte = sb->buf;
1111
1112 num_bytes -= (long)ret;
1113 if (sb->suspendable) {
1114 sb->remaining_skip = num_bytes;
1115 return;
1116 }
1117
1118 RELEASE_ARRAYS(env, data, src->next_input_byte);
1119 ret = (*env)->CallLongMethod(env,
1120 sb->stream,
1121 JPEGImageReader_skipInputBytesID,
1122 (jlong) num_bytes);
1123 if ((*env)->ExceptionOccurred(env)
1124 || !GET_ARRAYS(env, data, &(src->next_input_byte))) {
1125 cinfo->err->error_exit((j_common_ptr) cinfo);
1126 }
1127
1128 /*
1129 * If we have reached the end of the stream, then the EOI marker
1130 * is missing. We accept such streams but generate a warning.
1131 * The image is likely to be corrupted, though everything through
1132 * the end of the last complete MCU should be usable.
1133 */
1134 if (ret <= 0) {
1135 reader = data->imageIOobj;
1136 RELEASE_ARRAYS(env, data, src->next_input_byte);
1137 (*env)->CallVoidMethod(env,
1138 reader,
1139 JPEGImageReader_warningOccurredID,
1140 READ_NO_EOI);
2276 dest->next_output_byte = sb->buf;
2277 dest->free_in_buffer = sb->bufferLength;
2278 }
2279
2280 /*
2281 * Empty the output buffer --- called whenever buffer fills up.
2282 *
2283 * This routine writes the entire output buffer
2284 * (ignoring the current state of next_output_byte & free_in_buffer),
2285 * resets the pointer & count to the start of the buffer, and returns TRUE
2286 * indicating that the buffer has been dumped.
2287 */
2288
2289 METHODDEF(boolean)
2290 imageio_empty_output_buffer (j_compress_ptr cinfo)
2291 {
2292 struct jpeg_destination_mgr *dest = cinfo->dest;
2293 imageIODataPtr data = (imageIODataPtr) cinfo->client_data;
2294 streamBufferPtr sb = &data->streamBuf;
2295 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
2296
2297 RELEASE_ARRAYS(env, data, (const JOCTET *)(dest->next_output_byte));
2298
2299 (*env)->CallVoidMethod(env,
2300 sb->stream,
2301 JPEGImageWriter_writeOutputDataID,
2302 sb->hstreamBuffer,
2303 0,
2304 sb->bufferLength);
2305 if ((*env)->ExceptionOccurred(env)
2306 || !GET_ARRAYS(env, data,
2307 (const JOCTET **)(&dest->next_output_byte))) {
2308 cinfo->err->error_exit((j_common_ptr) cinfo);
2309 }
2310
2311 dest->next_output_byte = sb->buf;
2312 dest->free_in_buffer = sb->bufferLength;
2313
2314 return TRUE;
2315 }
2316
2317 /*
2318 * After all of the data has been encoded there may still be some
2319 * more left over in some of the working buffers. Now is the
2320 * time to clear them out.
2321 */
2322 METHODDEF(void)
2323 imageio_term_destination (j_compress_ptr cinfo)
2324 {
2325 struct jpeg_destination_mgr *dest = cinfo->dest;
2326 imageIODataPtr data = (imageIODataPtr) cinfo->client_data;
2327 streamBufferPtr sb = &data->streamBuf;
2328 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
2329
2330 /* find out how much needs to be written */
2331 jint datacount = sb->bufferLength - dest->free_in_buffer;
2332
2333 if (datacount != 0) {
2334 RELEASE_ARRAYS(env, data, (const JOCTET *)(dest->next_output_byte));
2335
2336 (*env)->CallVoidMethod(env,
2337 sb->stream,
2338 JPEGImageWriter_writeOutputDataID,
2339 sb->hstreamBuffer,
2340 0,
2341 datacount);
2342
2343 if ((*env)->ExceptionOccurred(env)
2344 || !GET_ARRAYS(env, data,
2345 (const JOCTET **)(&dest->next_output_byte))) {
2346 cinfo->err->error_exit((j_common_ptr) cinfo);
2347 }
2348 }
2349
2350 dest->next_output_byte = NULL;
2351 dest->free_in_buffer = 0;
2352
2353 }
2354
2355 /*
2356 * Flush the destination buffer. This is not called by the library,
2357 * but by our code below. This is the simplest implementation, though
|
90 #define READ_NO_EOI 0
91
92 /* Writer warnings */
93
94 /* Return codes for various ops */
95 #define OK 1
96 #define NOT_OK 0
97
98 /*
99 * First we define two objects, one for the stream and buffer and one
100 * for pixels. Both contain references to Java objects and pointers to
101 * pinned arrays. These objects can be used for either input or
102 * output. Pixels can be accessed as either INT32s or bytes.
103 * Every I/O operation will have one of each these objects, one for
104 * the stream and the other to hold pixels, regardless of the I/O direction.
105 */
106
107 /******************** StreamBuffer definition ************************/
108
109 typedef struct streamBufferStruct {
110 jweak ioRef; // weak reference to a provider of I/O routines
111 jbyteArray hstreamBuffer; // Handle to a Java buffer for the stream
112 JOCTET *buf; // Pinned buffer pointer */
113 int bufferOffset; // holds offset between unpin and the next pin
114 int bufferLength; // Allocated, nut just used
115 int suspendable; // Set to true to suspend input
116 long remaining_skip; // Used only on input
117 } streamBuffer, *streamBufferPtr;
118
119 /*
120 * This buffer size was set to 64K in the old classes, 4K by default in the
121 * IJG library, with the comment "an efficiently freadable size", and 1K
122 * in AWT.
123 * Unlike in the other Java designs, these objects will persist, so 64K
124 * seems too big and 1K seems too small. If 4K was good enough for the
125 * IJG folks, it's good enough for me.
126 */
127 #define STREAMBUF_SIZE 4096
128
129 #define GET_IO_REF(io_name) \
130 do { \
131 if ((*env)->IsSameObject(env, sb->ioRef, NULL) || \
132 ((io_name) = (*env)->NewLocalRef(env, sb->ioRef)) == NULL) \
133 { \
134 cinfo->err->error_exit((j_common_ptr) cinfo); \
135 } \
136 } while (0) \
137
138 /*
139 * Used to signal that no data need be restored from an unpin to a pin.
140 * I.e. the buffer is empty.
141 */
142 #define NO_DATA -1
143
144 // Forward reference
145 static void resetStreamBuffer(JNIEnv *env, streamBufferPtr sb);
146
147 /*
148 * Initialize a freshly allocated StreamBuffer object. The stream is left
149 * null, as it will be set from Java by setSource, but the buffer object
150 * is created and a global reference kept. Returns OK on success, NOT_OK
151 * if allocating the buffer or getting a global reference for it failed.
152 */
153 static int initStreamBuffer(JNIEnv *env, streamBufferPtr sb) {
154 /* Initialize a new buffer */
155 jbyteArray hInputBuffer = (*env)->NewByteArray(env, STREAMBUF_SIZE);
156 if (hInputBuffer == NULL) {
157 JNU_ThrowByName( env,
158 "java/lang/OutOfMemoryError",
159 "Initializing Reader");
160 return NOT_OK;
161 }
162 sb->bufferLength = (*env)->GetArrayLength(env, hInputBuffer);
163 sb->hstreamBuffer = (*env)->NewGlobalRef(env, hInputBuffer);
164 if (sb->hstreamBuffer == NULL) {
165 JNU_ThrowByName( env,
166 "java/lang/OutOfMemoryError",
167 "Initializing Reader");
168 return NOT_OK;
169 }
170
171
172 sb->ioRef = NULL;
173
174 sb->buf = NULL;
175
176 resetStreamBuffer(env, sb);
177
178 return OK;
179 }
180
181 /*
182 * Free all resources associated with this streamBuffer. This must
183 * be called to dispose the object to avoid leaking global references, as
184 * resetStreamBuffer does not release the buffer reference.
185 */
186 static void destroyStreamBuffer(JNIEnv *env, streamBufferPtr sb) {
187 resetStreamBuffer(env, sb);
188 if (sb->hstreamBuffer != NULL) {
189 (*env)->DeleteGlobalRef(env, sb->hstreamBuffer);
190 }
191 }
192
193 // Forward reference
194 static void unpinStreamBuffer(JNIEnv *env,
195 streamBufferPtr sb,
196 const JOCTET *next_byte);
197 /*
198 * Resets the state of a streamBuffer object that has been in use.
199 * The global reference to the stream is released, but the reference
200 * to the buffer is retained. The buffer is unpinned if it was pinned.
201 * All other state is reset.
202 */
203 static void resetStreamBuffer(JNIEnv *env, streamBufferPtr sb) {
204 if (sb->ioRef != NULL) {
205 (*env)->DeleteWeakGlobalRef(env, sb->ioRef);
206 sb->ioRef = NULL;
207 }
208 unpinStreamBuffer(env, sb, NULL);
209 sb->bufferOffset = NO_DATA;
210 sb->suspendable = FALSE;
211 sb->remaining_skip = 0;
212 }
213
214 /*
215 * Pins the data buffer associated with this stream. Returns OK on
216 * success, NOT_OK on failure, as GetPrimitiveArrayCritical may fail.
217 */
218 static int pinStreamBuffer(JNIEnv *env,
219 streamBufferPtr sb,
220 const JOCTET **next_byte) {
221 if (sb->hstreamBuffer != NULL) {
222 assert(sb->buf == NULL);
223 sb->buf =
224 (JOCTET *)(*env)->GetPrimitiveArrayCritical(env,
225 sb->hstreamBuffer,
226 NULL);
574 if (cinfo->is_decompressor) {
575 (*env)->CallVoidMethod(env, theObject,
576 JPEGImageReader_warningWithMessageID,
577 string);
578 } else {
579 (*env)->CallVoidMethod(env, theObject,
580 JPEGImageWriter_warningWithMessageID,
581 string);
582 }
583 }
584
585 /* End of verbatim copy from jpegdecoder.c */
586
587 /*************** end of error handling *********************/
588
589 /*************** Shared utility code ***********************/
590
591 static void imageio_set_stream(JNIEnv *env,
592 j_common_ptr cinfo,
593 imageIODataPtr data,
594 jobject io) {
595 streamBufferPtr sb;
596 sun_jpeg_error_ptr jerr;
597
598 sb = &data->streamBuf;
599
600 resetStreamBuffer(env, sb); // Removes any old stream
601
602 /* Now we need a new weak global reference for the I/O provider */
603 if (io != NULL) { // Fix for 4411955
604 sb->ioRef = (*env)->NewWeakGlobalRef(env, io);
605 if (sb->ioRef == NULL) {
606 JNU_ThrowByName(env,
607 "java/lang/OutOfMemoryError",
608 "Setting I/O provider");
609 return;
610 }
611 }
612
613 /* And finally reset state */
614 data->abortFlag = JNI_FALSE;
615
616 /* Establish the setjmp return context for sun_jpeg_error_exit to use. */
617 jerr = (sun_jpeg_error_ptr) cinfo->err;
618
619 if (setjmp(jerr->setjmp_buffer)) {
620 /* If we get here, the JPEG code has signaled an error
621 while aborting. */
622 if (!(*env)->ExceptionOccurred(env)) {
623 char buffer[JMSG_LENGTH_MAX];
624 (*cinfo->err->format_message) (cinfo,
625 buffer);
626 JNU_ThrowByName(env, "javax/imageio/IIOException", buffer);
627 }
628 return;
898 * if TRUE is returned. A FALSE return should only be used when I/O
899 * suspension is desired (this mode is discussed in the next section).
900 */
901 /*
902 * Note that with I/O suspension turned on, this procedure should not
903 * do any work since the JPEG library has a very simple backtracking
904 * mechanism which relies on the fact that the buffer will be filled
905 * only when it has backed out to the top application level. When
906 * suspendable is turned on, imageio_fill_suspended_buffer will
907 * do the actual work of filling the buffer.
908 */
909
910 GLOBAL(boolean)
911 imageio_fill_input_buffer(j_decompress_ptr cinfo)
912 {
913 struct jpeg_source_mgr *src = cinfo->src;
914 imageIODataPtr data = (imageIODataPtr) cinfo->client_data;
915 streamBufferPtr sb = &data->streamBuf;
916 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
917 int ret;
918 jobject input = NULL;
919
920 /* This is where input suspends */
921 if (sb->suspendable) {
922 return FALSE;
923 }
924
925 #ifdef DEBUG
926 printf("Filling input buffer, remaining skip is %ld, ",
927 sb->remaining_skip);
928 printf("Buffer length is %d\n", sb->bufferLength);
929 #endif
930
931 /*
932 * Definitively skips. Could be left over if we tried to skip
933 * more than a buffer's worth but suspended when getting the next
934 * buffer. Now we aren't suspended, so we can catch up.
935 */
936 if (sb->remaining_skip) {
937 src->skip_input_data(cinfo, 0);
938 }
939
940 /*
941 * Now fill a complete buffer, or as much of one as the stream
942 * will give us if we are near the end.
943 */
944 GET_IO_REF(input);
945
946 RELEASE_ARRAYS(env, data, src->next_input_byte);
947 ret = (*env)->CallIntMethod(env,
948 input,
949 JPEGImageReader_readInputDataID,
950 sb->hstreamBuffer, 0,
951 sb->bufferLength);
952 if ((*env)->ExceptionOccurred(env)
953 || !GET_ARRAYS(env, data, &(src->next_input_byte))) {
954 cinfo->err->error_exit((j_common_ptr) cinfo);
955 }
956
957 #ifdef DEBUG
958 printf("Buffer filled. ret = %d\n", ret);
959 #endif
960 /*
961 * If we have reached the end of the stream, then the EOI marker
962 * is missing. We accept such streams but generate a warning.
963 * The image is likely to be corrupted, though everything through
964 * the end of the last complete MCU should be usable.
965 */
966 if (ret <= 0) {
967 jobject reader = data->imageIOobj;
968 #ifdef DEBUG
988 return TRUE;
989 }
990
991 /*
992 * With I/O suspension turned on, the JPEG library requires that all
993 * buffer filling be done at the top application level, using this
994 * function. Due to the way that backtracking works, this procedure
995 * saves all of the data that was left in the buffer when suspension
996 * occured and read new data only at the end.
997 */
998
999 GLOBAL(void)
1000 imageio_fill_suspended_buffer(j_decompress_ptr cinfo)
1001 {
1002 struct jpeg_source_mgr *src = cinfo->src;
1003 imageIODataPtr data = (imageIODataPtr) cinfo->client_data;
1004 streamBufferPtr sb = &data->streamBuf;
1005 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
1006 jint ret;
1007 int offset, buflen;
1008 jobject input = NULL;
1009
1010 /*
1011 * The original (jpegdecoder.c) had code here that called
1012 * InputStream.available and just returned if the number of bytes
1013 * available was less than any remaining skip. Presumably this was
1014 * to avoid blocking, although the benefit was unclear, as no more
1015 * decompression can take place until more data is available, so
1016 * the code would block on input a little further along anyway.
1017 * ImageInputStreams don't have an available method, so we'll just
1018 * block in the skip if we have to.
1019 */
1020
1021 if (sb->remaining_skip) {
1022 src->skip_input_data(cinfo, 0);
1023 }
1024
1025 /* Save the data currently in the buffer */
1026 offset = src->bytes_in_buffer;
1027 if (src->next_input_byte > sb->buf) {
1028 memcpy(sb->buf, src->next_input_byte, offset);
1029 }
1030
1031 GET_IO_REF(input);
1032
1033 RELEASE_ARRAYS(env, data, src->next_input_byte);
1034 buflen = sb->bufferLength - offset;
1035 if (buflen <= 0) {
1036 if (!GET_ARRAYS(env, data, &(src->next_input_byte))) {
1037 cinfo->err->error_exit((j_common_ptr) cinfo);
1038 }
1039 return;
1040 }
1041
1042 ret = (*env)->CallIntMethod(env, input,
1043 JPEGImageReader_readInputDataID,
1044 sb->hstreamBuffer,
1045 offset, buflen);
1046 if ((*env)->ExceptionOccurred(env)
1047 || !GET_ARRAYS(env, data, &(src->next_input_byte))) {
1048 cinfo->err->error_exit((j_common_ptr) cinfo);
1049 }
1050 /*
1051 * If we have reached the end of the stream, then the EOI marker
1052 * is missing. We accept such streams but generate a warning.
1053 * The image is likely to be corrupted, though everything through
1054 * the end of the last complete MCU should be usable.
1055 */
1056 if (ret <= 0) {
1057 jobject reader = data->imageIOobj;
1058 RELEASE_ARRAYS(env, data, src->next_input_byte);
1059 (*env)->CallVoidMethod(env, reader,
1060 JPEGImageReader_warningOccurredID,
1061 READ_NO_EOI);
1062 if ((*env)->ExceptionOccurred(env)
1085 * buffer.
1086 *
1087 * A negative skip count is treated as a no-op. A zero skip count
1088 * skips any remaining skip from a previous skip while suspended.
1089 *
1090 * Note that with I/O suspension turned on, this procedure does not
1091 * call skipBytes since the JPEG library has a very simple backtracking
1092 * mechanism which relies on the fact that the application level has
1093 * exclusive control over actual I/O.
1094 */
1095
1096 GLOBAL(void)
1097 imageio_skip_input_data(j_decompress_ptr cinfo, long num_bytes)
1098 {
1099 struct jpeg_source_mgr *src = cinfo->src;
1100 imageIODataPtr data = (imageIODataPtr) cinfo->client_data;
1101 streamBufferPtr sb = &data->streamBuf;
1102 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
1103 jlong ret;
1104 jobject reader;
1105 jobject input = NULL;
1106
1107 if (num_bytes < 0) {
1108 return;
1109 }
1110 num_bytes += sb->remaining_skip;
1111 sb->remaining_skip = 0;
1112
1113 /* First the easy case where we are skipping <= the current contents. */
1114 ret = src->bytes_in_buffer;
1115 if (ret >= num_bytes) {
1116 src->next_input_byte += num_bytes;
1117 src->bytes_in_buffer -= num_bytes;
1118 return;
1119 }
1120
1121 /*
1122 * We are skipping more than is in the buffer. We empty the buffer and,
1123 * if we aren't suspended, call the Java skipBytes method. We always
1124 * leave the buffer empty, to be filled by either fill method above.
1125 */
1126 src->bytes_in_buffer = 0;
1127 src->next_input_byte = sb->buf;
1128
1129 num_bytes -= (long)ret;
1130 if (sb->suspendable) {
1131 sb->remaining_skip = num_bytes;
1132 return;
1133 }
1134
1135 GET_IO_REF(input);
1136
1137 RELEASE_ARRAYS(env, data, src->next_input_byte);
1138 ret = (*env)->CallLongMethod(env,
1139 input,
1140 JPEGImageReader_skipInputBytesID,
1141 (jlong) num_bytes);
1142 if ((*env)->ExceptionOccurred(env)
1143 || !GET_ARRAYS(env, data, &(src->next_input_byte))) {
1144 cinfo->err->error_exit((j_common_ptr) cinfo);
1145 }
1146
1147 /*
1148 * If we have reached the end of the stream, then the EOI marker
1149 * is missing. We accept such streams but generate a warning.
1150 * The image is likely to be corrupted, though everything through
1151 * the end of the last complete MCU should be usable.
1152 */
1153 if (ret <= 0) {
1154 reader = data->imageIOobj;
1155 RELEASE_ARRAYS(env, data, src->next_input_byte);
1156 (*env)->CallVoidMethod(env,
1157 reader,
1158 JPEGImageReader_warningOccurredID,
1159 READ_NO_EOI);
2295 dest->next_output_byte = sb->buf;
2296 dest->free_in_buffer = sb->bufferLength;
2297 }
2298
2299 /*
2300 * Empty the output buffer --- called whenever buffer fills up.
2301 *
2302 * This routine writes the entire output buffer
2303 * (ignoring the current state of next_output_byte & free_in_buffer),
2304 * resets the pointer & count to the start of the buffer, and returns TRUE
2305 * indicating that the buffer has been dumped.
2306 */
2307
2308 METHODDEF(boolean)
2309 imageio_empty_output_buffer (j_compress_ptr cinfo)
2310 {
2311 struct jpeg_destination_mgr *dest = cinfo->dest;
2312 imageIODataPtr data = (imageIODataPtr) cinfo->client_data;
2313 streamBufferPtr sb = &data->streamBuf;
2314 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
2315 jobject output = NULL;
2316
2317 GET_IO_REF(output);
2318
2319 RELEASE_ARRAYS(env, data, (const JOCTET *)(dest->next_output_byte));
2320
2321 (*env)->CallVoidMethod(env,
2322 output,
2323 JPEGImageWriter_writeOutputDataID,
2324 sb->hstreamBuffer,
2325 0,
2326 sb->bufferLength);
2327 if ((*env)->ExceptionOccurred(env)
2328 || !GET_ARRAYS(env, data,
2329 (const JOCTET **)(&dest->next_output_byte))) {
2330 cinfo->err->error_exit((j_common_ptr) cinfo);
2331 }
2332
2333 dest->next_output_byte = sb->buf;
2334 dest->free_in_buffer = sb->bufferLength;
2335
2336 return TRUE;
2337 }
2338
2339 /*
2340 * After all of the data has been encoded there may still be some
2341 * more left over in some of the working buffers. Now is the
2342 * time to clear them out.
2343 */
2344 METHODDEF(void)
2345 imageio_term_destination (j_compress_ptr cinfo)
2346 {
2347 struct jpeg_destination_mgr *dest = cinfo->dest;
2348 imageIODataPtr data = (imageIODataPtr) cinfo->client_data;
2349 streamBufferPtr sb = &data->streamBuf;
2350 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
2351
2352 /* find out how much needs to be written */
2353 jint datacount = sb->bufferLength - dest->free_in_buffer;
2354
2355 if (datacount != 0) {
2356 jobject output = NULL;
2357
2358 GET_IO_REF(output);
2359
2360 RELEASE_ARRAYS(env, data, (const JOCTET *)(dest->next_output_byte));
2361
2362 (*env)->CallVoidMethod(env,
2363 output,
2364 JPEGImageWriter_writeOutputDataID,
2365 sb->hstreamBuffer,
2366 0,
2367 datacount);
2368
2369 if ((*env)->ExceptionOccurred(env)
2370 || !GET_ARRAYS(env, data,
2371 (const JOCTET **)(&dest->next_output_byte))) {
2372 cinfo->err->error_exit((j_common_ptr) cinfo);
2373 }
2374 }
2375
2376 dest->next_output_byte = NULL;
2377 dest->free_in_buffer = 0;
2378
2379 }
2380
2381 /*
2382 * Flush the destination buffer. This is not called by the library,
2383 * but by our code below. This is the simplest implementation, though
|