src/share/native/sun/awt/image/jpeg/imageioJPEG.c

Print this page




  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