< prev index next >

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

Print this page


   1 /*
   2  * Copyright (c) 2000, 2014, Oracle and/or its affiliates. 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.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


 552 
 553 METHODDEF(void)
 554 sun_jpeg_output_message (j_common_ptr cinfo)
 555 {
 556   char buffer[JMSG_LENGTH_MAX];
 557   jstring string;
 558   imageIODataPtr data = (imageIODataPtr) cinfo->client_data;
 559   JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 560   jobject theObject;
 561 
 562   /* Create the message */
 563   (*cinfo->err->format_message) (cinfo, buffer);
 564 
 565   // Create a new java string from the message
 566   string = (*env)->NewStringUTF(env, buffer);
 567   CHECK_NULL(string);
 568 
 569   theObject = data->imageIOobj;
 570 
 571   if (cinfo->is_decompressor) {


 572       (*env)->CallVoidMethod(env, theObject,
 573                              JPEGImageReader_warningWithMessageID,
 574                              string);




 575   } else {


 576       (*env)->CallVoidMethod(env, theObject,
 577                              JPEGImageWriter_warningWithMessageID,
 578                              string);





 579   }
 580 }
 581 
 582 /* End of verbatim copy from jpegdecoder.c */
 583 
 584 /*************** end of error handling *********************/
 585 
 586 /*************** Shared utility code ***********************/
 587 
 588 static void imageio_set_stream(JNIEnv *env,
 589                                j_common_ptr cinfo,
 590                                imageIODataPtr data,
 591                                jobject io){
 592     streamBufferPtr sb;
 593     sun_jpeg_error_ptr jerr;
 594 
 595     sb = &data->streamBuf;
 596 
 597     resetStreamBuffer(env, sb);  // Removes any old stream
 598 


1026     if (sb->remaining_skip) {
1027         src->skip_input_data(cinfo, 0);
1028     }
1029 
1030     /* Save the data currently in the buffer */
1031     offset = src->bytes_in_buffer;
1032     if (src->next_input_byte > sb->buf) {
1033         memcpy(sb->buf, src->next_input_byte, offset);
1034     }
1035 
1036 
1037     RELEASE_ARRAYS(env, data, src->next_input_byte);
1038 
1039     GET_IO_REF(input);
1040 
1041     buflen = sb->bufferLength - offset;
1042     if (buflen <= 0) {
1043         if (!GET_ARRAYS(env, data, &(src->next_input_byte))) {
1044             cinfo->err->error_exit((j_common_ptr) cinfo);
1045         }

1046         return;
1047     }
1048 
1049     ret = (*env)->CallIntMethod(env, input,
1050                                 JPEGImageReader_readInputDataID,
1051                                 sb->hstreamBuffer,
1052                                 offset, buflen);
1053     if ((ret > 0) && ((unsigned int)ret > buflen)) ret = buflen;
1054     if ((*env)->ExceptionOccurred(env)
1055         || !GET_ARRAYS(env, data, &(src->next_input_byte))) {
1056         cinfo->err->error_exit((j_common_ptr) cinfo);
1057     }
1058     /*
1059      * If we have reached the end of the stream, then the EOI marker
1060      * is missing.  We accept such streams but generate a warning.
1061      * The image is likely to be corrupted, though everything through
1062      * the end of the last complete MCU should be usable.
1063      */
1064     if (ret <= 0) {
1065         jobject reader = data->imageIOobj;


1781                 /* Leave the output space as CMYK */
1782             }
1783         }
1784         RELEASE_ARRAYS(env, data, src->next_input_byte);
1785 
1786         /* read icc profile data */
1787         profileData = read_icc_profile(env, cinfo);
1788 
1789         if ((*env)->ExceptionCheck(env)) {
1790             return retval;
1791         }
1792 
1793         (*env)->CallVoidMethod(env, this,
1794                                JPEGImageReader_setImageDataID,
1795                                cinfo->image_width,
1796                                cinfo->image_height,
1797                                cinfo->jpeg_color_space,
1798                                cinfo->out_color_space,
1799                                cinfo->num_components,
1800                                profileData);




1801         if (reset) {
1802             jpeg_abort_decompress(cinfo);
1803         }

1804     }
1805 
1806     return retval;
1807 }
1808 
1809 
1810 JNIEXPORT void JNICALL
1811 Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_setOutColorSpace
1812     (JNIEnv *env,
1813      jobject this,
1814      jlong ptr,
1815      jint code) {
1816 
1817     imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr);
1818     j_decompress_ptr cinfo;
1819 
1820     if (data == NULL) {
1821         JNU_ThrowByName(env,
1822                         "java/lang/IllegalStateException",
1823                         "Attempting to use reader after dispose()");


1994                    DCHuffmanTables,
1995                    ACHuffmanTables,
1996                    TRUE);
1997     }
1998 
1999     progressive = jpeg_has_multiple_scans(cinfo);
2000     if (progressive) {
2001         cinfo->buffered_image = TRUE;
2002         cinfo->input_scan_number = minProgressivePass+1; // Java count from 0
2003 #define MAX_JAVA_INT 2147483647 // XXX Is this defined in JNI somewhere?
2004         if (maxProgressivePass < MAX_JAVA_INT) {
2005             maxProgressivePass++; // For testing
2006         }
2007     }
2008 
2009     data->streamBuf.suspendable = FALSE;
2010 
2011     jpeg_start_decompress(cinfo);
2012 
2013     if (numBands !=  cinfo->output_components) {

2014         JNU_ThrowByName(env, "javax/imageio/IIOException",
2015                         "Invalid argument to native readImage");
2016         return data->abortFlag;
2017     }
2018 
2019     if (cinfo->output_components <= 0 ||
2020         cinfo->image_width > (0xffffffffu / (unsigned int)cinfo->output_components))
2021     {

2022         JNU_ThrowByName(env, "javax/imageio/IIOException",
2023                         "Invalid number of output components");
2024         return data->abortFlag;
2025     }
2026 
2027     // Allocate a 1-scanline buffer
2028     scanLinePtr = (JSAMPROW)malloc(cinfo->image_width*cinfo->output_components);
2029     if (scanLinePtr == NULL) {
2030         RELEASE_ARRAYS(env, data, src->next_input_byte);
2031         JNU_ThrowByName( env,
2032                          "java/lang/OutOfMemoryError",
2033                          "Reading JPEG Stream");
2034         return data->abortFlag;
2035     }
2036 
2037     // loop over progressive passes
2038     done = FALSE;
2039     while (!done) {
2040         if (progressive) {
2041             // initialize the next pass.  Note that this skips up to
2042             // the first interesting pass.
2043             jpeg_start_output(cinfo, cinfo->input_scan_number);
2044             if (wantUpdates) {

2045                 (*env)->CallVoidMethod(env, this,
2046                                        JPEGImageReader_passStartedID,
2047                                        cinfo->input_scan_number-1);




2048             }
2049         } else if (wantUpdates) {

2050             (*env)->CallVoidMethod(env, this,
2051                                    JPEGImageReader_passStartedID,
2052                                    0);
2053 



2054         }
2055 
2056         // Skip until the first interesting line
2057         while ((data->abortFlag == JNI_FALSE)
2058                && ((jint)cinfo->output_scanline < sourceYStart)) {
2059             jpeg_read_scanlines(cinfo, &scanLinePtr, 1);
2060         }
2061 
2062         scanlineLimit = sourceYStart+sourceHeight;
2063         pixelLimit = scanLinePtr
2064             +(sourceXStart+sourceWidth)*cinfo->output_components;
2065 
2066         pixelStride = stepX*cinfo->output_components;
2067         targetLine = 0;
2068 
2069         while ((data->abortFlag == JNI_FALSE)
2070                && ((jint)cinfo->output_scanline < scanlineLimit)) {
2071 
2072             jpeg_read_scanlines(cinfo, &scanLinePtr, 1);
2073 


2121             linesLeft =  scanlineLimit - cinfo->output_scanline;
2122             // Take the minimum
2123             if (skipLines > linesLeft) {
2124                 skipLines = linesLeft;
2125             }
2126             for(i = 0; i < skipLines; i++) {
2127                 jpeg_read_scanlines(cinfo, &scanLinePtr, 1);
2128             }
2129         }
2130         if (progressive) {
2131             jpeg_finish_output(cinfo); // Increments pass counter
2132             // Call Java to notify pass complete
2133             if (jpeg_input_complete(cinfo)
2134                 || (cinfo->input_scan_number > maxProgressivePass)) {
2135                 done = TRUE;
2136             }
2137         } else {
2138             done = TRUE;
2139         }
2140         if (wantUpdates) {

2141             (*env)->CallVoidMethod(env, this,
2142                                    JPEGImageReader_passCompleteID);




2143         }
2144 
2145     }
2146     /*
2147      * We are done, but we might not have read all the lines, or all
2148      * the passes, so use jpeg_abort instead of jpeg_finish_decompress.
2149      */
2150     if (cinfo->output_scanline == cinfo->output_height) {
2151         //    if ((cinfo->output_scanline == cinfo->output_height) &&
2152         //(jpeg_input_complete(cinfo))) {  // We read the whole file
2153         jpeg_finish_decompress(cinfo);
2154     } else {
2155         jpeg_abort_decompress(cinfo);
2156     }
2157 
2158     free(scanLinePtr);
2159 
2160     RELEASE_ARRAYS(env, data, src->next_input_byte);
2161 
2162     return data->abortFlag;


   1 /*
   2  * Copyright (c) 2000, 2016, Oracle and/or its affiliates. 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.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


 552 
 553 METHODDEF(void)
 554 sun_jpeg_output_message (j_common_ptr cinfo)
 555 {
 556     char buffer[JMSG_LENGTH_MAX];
 557     jstring string;
 558     imageIODataPtr data = (imageIODataPtr) cinfo->client_data;
 559     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
 560     jobject theObject;
 561 
 562     /* Create the message */
 563     (*cinfo->err->format_message) (cinfo, buffer);
 564 
 565     // Create a new java string from the message
 566     string = (*env)->NewStringUTF(env, buffer);
 567     CHECK_NULL(string);
 568 
 569     theObject = data->imageIOobj;
 570 
 571     if (cinfo->is_decompressor) {
 572         struct jpeg_source_mgr *src = ((j_decompress_ptr)cinfo)->src;
 573         RELEASE_ARRAYS(env, data, src->next_input_byte);
 574         (*env)->CallVoidMethod(env, theObject,
 575             JPEGImageReader_warningWithMessageID,
 576             string);
 577         if ((*env)->ExceptionOccurred(env)
 578             || !GET_ARRAYS(env, data, &(src->next_input_byte))) {
 579             cinfo->err->error_exit(cinfo);
 580         }
 581     } else {
 582         struct jpeg_destination_mgr *dest = ((j_compress_ptr)cinfo)->dest;
 583         RELEASE_ARRAYS(env, data, (const JOCTET *)(dest->next_output_byte));
 584         (*env)->CallVoidMethod(env, theObject,
 585             JPEGImageWriter_warningWithMessageID,
 586             string);
 587         if ((*env)->ExceptionOccurred(env)
 588             || !GET_ARRAYS(env, data,
 589             (const JOCTET **)(&dest->next_output_byte))) {
 590             cinfo->err->error_exit(cinfo);
 591         }
 592     }
 593 }
 594 
 595 /* End of verbatim copy from jpegdecoder.c */
 596 
 597 /*************** end of error handling *********************/
 598 
 599 /*************** Shared utility code ***********************/
 600 
 601 static void imageio_set_stream(JNIEnv *env,
 602                                j_common_ptr cinfo,
 603                                imageIODataPtr data,
 604                                jobject io){
 605     streamBufferPtr sb;
 606     sun_jpeg_error_ptr jerr;
 607 
 608     sb = &data->streamBuf;
 609 
 610     resetStreamBuffer(env, sb);  // Removes any old stream
 611 


1039     if (sb->remaining_skip) {
1040         src->skip_input_data(cinfo, 0);
1041     }
1042 
1043     /* Save the data currently in the buffer */
1044     offset = src->bytes_in_buffer;
1045     if (src->next_input_byte > sb->buf) {
1046         memcpy(sb->buf, src->next_input_byte, offset);
1047     }
1048 
1049 
1050     RELEASE_ARRAYS(env, data, src->next_input_byte);
1051 
1052     GET_IO_REF(input);
1053 
1054     buflen = sb->bufferLength - offset;
1055     if (buflen <= 0) {
1056         if (!GET_ARRAYS(env, data, &(src->next_input_byte))) {
1057             cinfo->err->error_exit((j_common_ptr) cinfo);
1058         }
1059         RELEASE_ARRAYS(env, data, src->next_input_byte);
1060         return;
1061     }
1062 
1063     ret = (*env)->CallIntMethod(env, input,
1064                                 JPEGImageReader_readInputDataID,
1065                                 sb->hstreamBuffer,
1066                                 offset, buflen);
1067     if ((ret > 0) && ((unsigned int)ret > buflen)) ret = buflen;
1068     if ((*env)->ExceptionOccurred(env)
1069         || !GET_ARRAYS(env, data, &(src->next_input_byte))) {
1070         cinfo->err->error_exit((j_common_ptr) cinfo);
1071     }
1072     /*
1073      * If we have reached the end of the stream, then the EOI marker
1074      * is missing.  We accept such streams but generate a warning.
1075      * The image is likely to be corrupted, though everything through
1076      * the end of the last complete MCU should be usable.
1077      */
1078     if (ret <= 0) {
1079         jobject reader = data->imageIOobj;


1795                 /* Leave the output space as CMYK */
1796             }
1797         }
1798         RELEASE_ARRAYS(env, data, src->next_input_byte);
1799 
1800         /* read icc profile data */
1801         profileData = read_icc_profile(env, cinfo);
1802 
1803         if ((*env)->ExceptionCheck(env)) {
1804             return retval;
1805         }
1806 
1807         (*env)->CallVoidMethod(env, this,
1808                                JPEGImageReader_setImageDataID,
1809                                cinfo->image_width,
1810                                cinfo->image_height,
1811                                cinfo->jpeg_color_space,
1812                                cinfo->out_color_space,
1813                                cinfo->num_components,
1814                                profileData);
1815         if ((*env)->ExceptionOccurred(env)
1816             || !GET_ARRAYS(env, data, &(src->next_input_byte))) {
1817             cinfo->err->error_exit((j_common_ptr) cinfo);
1818         }
1819         if (reset) {
1820             jpeg_abort_decompress(cinfo);
1821         }
1822         RELEASE_ARRAYS(env, data, src->next_input_byte);
1823     }
1824 
1825     return retval;
1826 }
1827 
1828 
1829 JNIEXPORT void JNICALL
1830 Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_setOutColorSpace
1831     (JNIEnv *env,
1832      jobject this,
1833      jlong ptr,
1834      jint code) {
1835 
1836     imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr);
1837     j_decompress_ptr cinfo;
1838 
1839     if (data == NULL) {
1840         JNU_ThrowByName(env,
1841                         "java/lang/IllegalStateException",
1842                         "Attempting to use reader after dispose()");


2013                    DCHuffmanTables,
2014                    ACHuffmanTables,
2015                    TRUE);
2016     }
2017 
2018     progressive = jpeg_has_multiple_scans(cinfo);
2019     if (progressive) {
2020         cinfo->buffered_image = TRUE;
2021         cinfo->input_scan_number = minProgressivePass+1; // Java count from 0
2022 #define MAX_JAVA_INT 2147483647 // XXX Is this defined in JNI somewhere?
2023         if (maxProgressivePass < MAX_JAVA_INT) {
2024             maxProgressivePass++; // For testing
2025         }
2026     }
2027 
2028     data->streamBuf.suspendable = FALSE;
2029 
2030     jpeg_start_decompress(cinfo);
2031 
2032     if (numBands !=  cinfo->output_components) {
2033         RELEASE_ARRAYS(env, data, src->next_input_byte);
2034         JNU_ThrowByName(env, "javax/imageio/IIOException",
2035                         "Invalid argument to native readImage");
2036         return data->abortFlag;
2037     }
2038 
2039     if (cinfo->output_components <= 0 ||
2040         cinfo->image_width > (0xffffffffu / (unsigned int)cinfo->output_components))
2041     {
2042         RELEASE_ARRAYS(env, data, src->next_input_byte);
2043         JNU_ThrowByName(env, "javax/imageio/IIOException",
2044                         "Invalid number of output components");
2045         return data->abortFlag;
2046     }
2047 
2048     // Allocate a 1-scanline buffer
2049     scanLinePtr = (JSAMPROW)malloc(cinfo->image_width*cinfo->output_components);
2050     if (scanLinePtr == NULL) {
2051         RELEASE_ARRAYS(env, data, src->next_input_byte);
2052         JNU_ThrowByName( env,
2053                          "java/lang/OutOfMemoryError",
2054                          "Reading JPEG Stream");
2055         return data->abortFlag;
2056     }
2057 
2058     // loop over progressive passes
2059     done = FALSE;
2060     while (!done) {
2061         if (progressive) {
2062             // initialize the next pass.  Note that this skips up to
2063             // the first interesting pass.
2064             jpeg_start_output(cinfo, cinfo->input_scan_number);
2065             if (wantUpdates) {
2066                 RELEASE_ARRAYS(env, data, src->next_input_byte);
2067                 (*env)->CallVoidMethod(env, this,
2068                                        JPEGImageReader_passStartedID,
2069                                        cinfo->input_scan_number-1);
2070                 if ((*env)->ExceptionOccurred(env)
2071                     || !GET_ARRAYS(env, data, &(src->next_input_byte))) {
2072                     cinfo->err->error_exit((j_common_ptr) cinfo);
2073                 }
2074             }
2075         } else if (wantUpdates) {
2076             RELEASE_ARRAYS(env, data, src->next_input_byte);
2077             (*env)->CallVoidMethod(env, this,
2078                                    JPEGImageReader_passStartedID,
2079                                    0);
2080             if ((*env)->ExceptionOccurred(env)
2081                 || !GET_ARRAYS(env, data, &(src->next_input_byte))) {
2082                 cinfo->err->error_exit((j_common_ptr) cinfo);
2083             }
2084         }
2085 
2086         // Skip until the first interesting line
2087         while ((data->abortFlag == JNI_FALSE)
2088                && ((jint)cinfo->output_scanline < sourceYStart)) {
2089             jpeg_read_scanlines(cinfo, &scanLinePtr, 1);
2090         }
2091 
2092         scanlineLimit = sourceYStart+sourceHeight;
2093         pixelLimit = scanLinePtr
2094             +(sourceXStart+sourceWidth)*cinfo->output_components;
2095 
2096         pixelStride = stepX*cinfo->output_components;
2097         targetLine = 0;
2098 
2099         while ((data->abortFlag == JNI_FALSE)
2100                && ((jint)cinfo->output_scanline < scanlineLimit)) {
2101 
2102             jpeg_read_scanlines(cinfo, &scanLinePtr, 1);
2103 


2151             linesLeft =  scanlineLimit - cinfo->output_scanline;
2152             // Take the minimum
2153             if (skipLines > linesLeft) {
2154                 skipLines = linesLeft;
2155             }
2156             for(i = 0; i < skipLines; i++) {
2157                 jpeg_read_scanlines(cinfo, &scanLinePtr, 1);
2158             }
2159         }
2160         if (progressive) {
2161             jpeg_finish_output(cinfo); // Increments pass counter
2162             // Call Java to notify pass complete
2163             if (jpeg_input_complete(cinfo)
2164                 || (cinfo->input_scan_number > maxProgressivePass)) {
2165                 done = TRUE;
2166             }
2167         } else {
2168             done = TRUE;
2169         }
2170         if (wantUpdates) {
2171             RELEASE_ARRAYS(env, data, src->next_input_byte);
2172             (*env)->CallVoidMethod(env, this,
2173                                    JPEGImageReader_passCompleteID);
2174             if ((*env)->ExceptionOccurred(env)
2175                 || !GET_ARRAYS(env, data, &(src->next_input_byte))) {
2176                 cinfo->err->error_exit((j_common_ptr) cinfo);
2177             }
2178         }
2179 
2180     }
2181     /*
2182      * We are done, but we might not have read all the lines, or all
2183      * the passes, so use jpeg_abort instead of jpeg_finish_decompress.
2184      */
2185     if (cinfo->output_scanline == cinfo->output_height) {
2186         //    if ((cinfo->output_scanline == cinfo->output_height) &&
2187         //(jpeg_input_complete(cinfo))) {  // We read the whole file
2188         jpeg_finish_decompress(cinfo);
2189     } else {
2190         jpeg_abort_decompress(cinfo);
2191     }
2192 
2193     free(scanLinePtr);
2194 
2195     RELEASE_ARRAYS(env, data, src->next_input_byte);
2196 
2197     return data->abortFlag;


< prev index next >