< prev index next >

modules/javafx.graphics/src/main/native-iio/jpegloader.c

Print this page

   1 /*
   2  * Copyright (c) 2009, 2018, 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

 669         info->err = NULL;
 670         if (info->is_decompressor) {
 671             j_decompress_ptr dinfo = (j_decompress_ptr) info;
 672             free(dinfo->src);
 673             dinfo->src = NULL;
 674         } else {
 675             j_compress_ptr cinfo = (j_compress_ptr) info;
 676             free(cinfo->dest);
 677             cinfo->dest = NULL;
 678         }
 679         jpeg_destroy(info);
 680         free(info);
 681     }
 682 }
 683 
 684 static void imageio_abort(JNIEnv *env, jobject this,
 685         imageIODataPtr data) {
 686     data->abortFlag = JNI_TRUE;
 687 }
 688 





 689 /*************** end of shared utility code ****************/
 690 
 691 /********************** Loader Support **************************/
 692 
 693 /********************** Source Management ***********************/
 694 
 695 /*
 696  * INPUT HANDLING:
 697  *
 698  * The JPEG library's input management is defined by the jpeg_source_mgr
 699  * structure which contains two fields to convey the information in the
 700  * buffer and 5 methods which perform all buffer management.  The library
 701  * defines a standard input manager that uses stdio for obtaining compressed
 702  * jpeg data, but here we need to use Java to get our data.
 703  *
 704  * We use the library jpeg_source_mgr but our own routines that access
 705  * imageio-specific information in the imageIOData structure.
 706  */
 707 
 708 /*

1258             cls,
1259             "updateImageProgress",
1260             "(I)V");
1261     if ((*env)->ExceptionCheck(env)) {
1262         return;
1263     }
1264 
1265     JPEGImageLoader_emitWarningID = (*env)->GetMethodID(env,
1266             cls,
1267             "emitWarning",
1268             "(Ljava/lang/String;)V");
1269     if ((*env)->ExceptionCheck(env)) {
1270         return;
1271     }
1272 
1273 }
1274 
1275 JNIEXPORT void JNICALL Java_com_sun_javafx_iio_jpeg_JPEGImageLoader_disposeNative
1276 (JNIEnv *env, jclass cls, jlong ptr) {
1277     imageIODataPtr data = (imageIODataPtr) jlong_to_ptr(ptr);
1278     j_common_ptr info = destroyImageioData(env, data);
1279 
1280     imageio_dispose(info);
1281 }
1282 
1283 #define JPEG_APP1  (JPEG_APP0 + 1)  /* EXIF APP1 marker code  */
1284 
1285 /*
1286  * For EXIF images, the APP1 will appear immediately after the SOI,
1287  * so it's safe to only look at the first marker in the list.
1288  * (see http://www.exif.org/Exif2-2.PDF, section 4.7, page 58)
1289  */
1290 #define IS_EXIF(c) \
1291     (((c)->marker_list != NULL) && ((c)->marker_list->marker == JPEG_APP1))
1292 
1293 JNIEXPORT jlong JNICALL Java_com_sun_javafx_iio_jpeg_JPEGImageLoader_initDecompressor
1294 (JNIEnv *env, jobject this, jobject stream) {
1295     imageIODataPtr data;
1296     struct sun_jpeg_error_mgr *jerr_mgr;
1297 
1298     /* This struct contains the JPEG decompression parameters and pointers to
1299      * working space (which is allocated as needed by the JPEG library).
1300      */

1321         free(cinfo);
1322         ThrowByName(env,
1323                 "java/lang/OutOfMemoryError",
1324                 "Initializing Reader");
1325         return 0;
1326     }
1327 
1328     /* We set up the normal JPEG error routines, then override error_exit. */
1329     cinfo->err = jpeg_std_error(&(jerr_mgr->pub));
1330     jerr_mgr->pub.error_exit = sun_jpeg_error_exit;
1331     /* We need to setup our own print routines */
1332     jerr_mgr->pub.output_message = sun_jpeg_output_message;
1333     /* Now we can setjmp before every call to the library */
1334 
1335     /* Establish the setjmp return context for sun_jpeg_error_exit to use. */
1336     if (setjmp(jerr_mgr->setjmp_buffer)) {
1337         /* If we get here, the JPEG code has signaled an error. */
1338         char buffer[JMSG_LENGTH_MAX];
1339         (*cinfo->err->format_message) ((struct jpeg_common_struct *) cinfo,
1340                 buffer);


1341         ThrowByName(env, "java/io/IOException", buffer);
1342         return 0;
1343     }
1344 
1345     /* Perform library initialization */
1346     jpeg_create_decompress(cinfo);
1347 
1348     // Set up to keep any APP2 markers, as these might contain ICC profile
1349     // data
1350     jpeg_save_markers(cinfo, ICC_MARKER, 0xFFFF);
1351 
1352     /*
1353      * Now set up our source.
1354      */
1355     cinfo->src =
1356             (struct jpeg_source_mgr *) malloc(sizeof (struct jpeg_source_mgr));
1357     if (cinfo->src == NULL) {

1358         ThrowByName(env,
1359                 "java/lang/OutOfMemoryError",
1360                 "Initializing Reader");
1361         return 0;
1362     }
1363     cinfo->src->bytes_in_buffer = 0;
1364     cinfo->src->next_input_byte = NULL;
1365     cinfo->src->init_source = imageio_init_source;
1366     cinfo->src->fill_input_buffer = imageio_fill_input_buffer;
1367     cinfo->src->skip_input_data = imageio_skip_input_data;
1368     cinfo->src->resync_to_restart = jpeg_resync_to_restart; // use default
1369     cinfo->src->term_source = imageio_term_source;
1370 
1371     /* set up the association to persist for future calls */
1372     data = initImageioData(env, (j_common_ptr) cinfo, this);
1373     if (data == NULL) {

1374         ThrowByName(env,
1375                 "java/lang/OutOfMemoryError",
1376                 "Initializing Reader");
1377         return 0;
1378     }
1379 
1380     imageio_set_stream(env, (j_common_ptr) cinfo, data, stream);
1381 
1382     if ((*env)->ExceptionCheck(env)) return 0;



1383 
1384     imageio_init_source((j_decompress_ptr) cinfo);
1385 
1386     src = cinfo->src;
1387     jerr = (sun_jpeg_error_ptr) cinfo->err;
1388 
1389     /* Establish the setjmp return context for sun_jpeg_error_exit to use. */
1390     if (setjmp(jerr->setjmp_buffer)) {
1391         /* If we get here, the JPEG code has signaled an error
1392            while reading the header. */
1393         RELEASE_ARRAYS(env, data, src->next_input_byte);
1394         if (!(*env)->ExceptionOccurred(env)) {
1395             char buffer[JMSG_LENGTH_MAX];
1396             (*cinfo->err->format_message) ((struct jpeg_common_struct *) cinfo,
1397                     buffer);
1398             ThrowByName(env, "java/io/IOException", buffer);
1399         }

1400         return 0;
1401     }
1402 
1403     if (GET_ARRAYS(env, data, &src->next_input_byte) == NOT_OK) {
1404         ThrowByName(env,
1405                 "java/io/IOException",
1406                 "Array pin failed");

1407         return 0;
1408     }
1409 
1410     jret = jpeg_read_header(cinfo, FALSE);
1411 
1412     if (jret == JPEG_HEADER_TABLES_ONLY) {
1413         imageio_term_source(cinfo); // Pushback remaining buffer contents
1414 #ifdef DEBUG_IIO_JPEG
1415         printf("just read tables-only image; q table 0 at %p\n",
1416                 cinfo->quant_tbl_ptrs[0]);
1417 #endif
1418         RELEASE_ARRAYS(env, data, src->next_input_byte);
1419     } else {
1420         /*
1421          * Now adjust the jpeg_color_space variable, which was set in
1422          * default_decompress_parms, to reflect our differences from IJG
1423          */
1424 
1425         switch (cinfo->jpeg_color_space) {
1426             default:

1483 
1484                 v_samp0 = cinfo->comp_info[0].v_samp_factor;
1485                 v_samp1 = cinfo->comp_info[1].v_samp_factor;
1486                 v_samp2 = cinfo->comp_info[2].v_samp_factor;
1487 
1488                 if ((h_samp1 > h_samp0) && (h_samp2 > h_samp0) ||
1489                         (v_samp1 > v_samp0) && (v_samp2 > v_samp0)) {
1490                     cinfo->jpeg_color_space = JCS_YCCK;
1491                     /* Leave the output space as CMYK */
1492                 }
1493 
1494                 /* There is no support for CMYK on jfx side, so request RGB output */
1495                 cinfo->out_color_space = JCS_RGB;
1496         }
1497         RELEASE_ARRAYS(env, data, src->next_input_byte);
1498 
1499         /* read icc profile data */
1500         profileData = read_icc_profile(env, cinfo);
1501 
1502         if ((*env)->ExceptionCheck(env)) {

1503             return 0;
1504         }
1505 
1506         (*env)->CallVoidMethod(env, this,
1507                 JPEGImageLoader_setInputAttributesID,
1508                 cinfo->image_width,
1509                 cinfo->image_height,
1510                 cinfo->jpeg_color_space,
1511                 cinfo->out_color_space,
1512                 cinfo->num_components,
1513                 profileData);
1514         if ((*env)->ExceptionCheck(env)) {

1515             return 0;
1516         }
1517     }
1518 
1519     return ptr_to_jlong(data);
1520 }
1521 
1522 JNIEXPORT jint JNICALL Java_com_sun_javafx_iio_jpeg_JPEGImageLoader_startDecompression
1523 (JNIEnv *env, jobject this, jlong ptr, jint outCS, jint dest_width, jint dest_height) {
1524     imageIODataPtr data = (imageIODataPtr) jlong_to_ptr(ptr);
1525     j_decompress_ptr cinfo = (j_decompress_ptr) data->jpegObj;
1526     struct jpeg_source_mgr *src = cinfo->src;
1527     sun_jpeg_error_ptr jerr;
1528 
1529     jfloat x_scale;
1530     jfloat y_scale;
1531     jfloat max_scale;
1532 
1533     if (GET_ARRAYS(env, data, &cinfo->src->next_input_byte) == NOT_OK) {
1534         ThrowByName(env,

1589     jpeg_start_decompress(cinfo);
1590 
1591     RELEASE_ARRAYS(env, data, cinfo->src->next_input_byte);
1592     (*env)->CallVoidMethod(env, this,
1593             JPEGImageLoader_setOutputAttributesID,
1594             cinfo->output_width,
1595             cinfo->output_height);
1596 
1597     return cinfo->output_components;
1598 }
1599 
1600 #define SAFE_TO_MULT(a, b) (((a) > 0) && ((b) >= 0) && ((0x7fffffff / (a)) > (b)))
1601 
1602 JNIEXPORT jboolean JNICALL Java_com_sun_javafx_iio_jpeg_JPEGImageLoader_decompressIndirect
1603 (JNIEnv *env, jobject this, jlong ptr, jboolean report_progress, jbyteArray barray) {
1604     imageIODataPtr data = (imageIODataPtr) jlong_to_ptr(ptr);
1605     j_decompress_ptr cinfo = (j_decompress_ptr) data->jpegObj;
1606     struct jpeg_source_mgr *src = cinfo->src;
1607     sun_jpeg_error_ptr jerr;
1608     int bytes_per_row = cinfo->output_width * cinfo->output_components;
1609     JSAMPROW scanline_ptr = (JSAMPROW) malloc(bytes_per_row * sizeof (JSAMPLE));
1610     int offset = 0;

1611 
1612     if (!SAFE_TO_MULT(cinfo->output_width, cinfo->output_components) ||
1613         !SAFE_TO_MULT(bytes_per_row, cinfo->output_height) ||
1614         ((*env)->GetArrayLength(env, barray) <
1615          (bytes_per_row * cinfo->output_height)))
1616      {
1617         ThrowByName(env,
1618                 "java/lang/OutOfMemoryError",
1619                 "Reading JPEG Stream");
1620         return JNI_FALSE;
1621     }
1622 
1623     if (GET_ARRAYS(env, data, &cinfo->src->next_input_byte) == NOT_OK) {
1624         ThrowByName(env,
1625                 "java/io/IOException",
1626                 "Array pin failed");
1627         return JNI_FALSE;
1628     }
1629 
1630     if (scanline_ptr == NULL) {
1631         ThrowByName(env,
1632                 "java/lang/OutOfMemoryError",
1633                 "Reading JPEG Stream");
1634         RELEASE_ARRAYS(env, data, cinfo->src->next_input_byte);
1635         return JNI_FALSE;
1636     }
1637 
1638     /* Establish the setjmp return context for sun_jpeg_error_exit to use. */
1639     jerr = (sun_jpeg_error_ptr) cinfo->err;
1640 
1641     if (setjmp(jerr->setjmp_buffer)) {
1642         /* If we get here, the JPEG code has signaled an error
1643            while reading. */
1644         if (!(*env)->ExceptionOccurred(env)) {
1645             char buffer[JMSG_LENGTH_MAX];
1646             (*cinfo->err->format_message) ((struct jpeg_common_struct *) cinfo,
1647                     buffer);
1648             ThrowByName(env, "java/io/IOException", buffer);
1649         }
1650         if (scanline_ptr != NULL) {
1651             free(scanline_ptr);
1652         }
1653         RELEASE_ARRAYS(env, data, cinfo->src->next_input_byte);
1654         return JNI_FALSE;
1655     }
1656 








1657     while (cinfo->output_scanline < cinfo->output_height) {
1658         int num_scanlines;
1659         if (report_progress == JNI_TRUE) {
1660             RELEASE_ARRAYS(env, data, cinfo->src->next_input_byte);
1661             (*env)->CallVoidMethod(env, this,
1662                     JPEGImageLoader_updateImageProgressID,
1663                     cinfo->output_scanline);
1664             if ((*env)->ExceptionCheck(env)) return JNI_FALSE;



1665             if (GET_ARRAYS(env, data, &cinfo->src->next_input_byte) == NOT_OK) {
1666               ThrowByName(env,

1667                           "java/io/IOException",
1668                           "Array pin failed");
1669               return JNI_FALSE;
1670             }
1671         }
1672 
1673         num_scanlines = jpeg_read_scanlines(cinfo, &scanline_ptr, 1);
1674         if (num_scanlines == 1) {
1675             jboolean iscopy = FALSE;
1676             jbyte *body = (*env)->GetPrimitiveArrayCritical(env, barray, &iscopy);
1677             if (body == NULL) {
1678                 fprintf(stderr, "decompressIndirect: GetPrimitiveArrayCritical returns NULL: out of memory\n");

1679                 return JNI_FALSE;
1680             }
1681             memcpy(body+offset,scanline_ptr, bytes_per_row);
1682             (*env)->ReleasePrimitiveArrayCritical(env, barray, body, JNI_ABORT);
1683             offset += bytes_per_row;
1684         }
1685     }

1686 
1687     if (report_progress == JNI_TRUE) {
1688         RELEASE_ARRAYS(env, data, cinfo->src->next_input_byte);
1689         (*env)->CallVoidMethod(env, this,
1690                 JPEGImageLoader_updateImageProgressID,
1691                 cinfo->output_height);
1692       if ((*env)->ExceptionCheck(env)) return JNI_FALSE;
1693       if (GET_ARRAYS(env, data, &cinfo->src->next_input_byte) == NOT_OK) {
1694           ThrowByName(env,


1695                 "java/io/IOException",
1696                 "Array pin failed");
1697           return JNI_FALSE;
1698       }
1699     }
1700 
1701     jpeg_finish_decompress(cinfo);
1702     free(scanline_ptr);
1703 
1704     RELEASE_ARRAYS(env, data, cinfo->src->next_input_byte);
1705     return JNI_TRUE;
1706 }

   1 /*
   2  * Copyright (c) 2009, 2019, 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

 669         info->err = NULL;
 670         if (info->is_decompressor) {
 671             j_decompress_ptr dinfo = (j_decompress_ptr) info;
 672             free(dinfo->src);
 673             dinfo->src = NULL;
 674         } else {
 675             j_compress_ptr cinfo = (j_compress_ptr) info;
 676             free(cinfo->dest);
 677             cinfo->dest = NULL;
 678         }
 679         jpeg_destroy(info);
 680         free(info);
 681     }
 682 }
 683 
 684 static void imageio_abort(JNIEnv *env, jobject this,
 685         imageIODataPtr data) {
 686     data->abortFlag = JNI_TRUE;
 687 }
 688 
 689 static void disposeIIO(JNIEnv *env, imageIODataPtr data) {
 690     j_common_ptr info = destroyImageioData(env, data);
 691     imageio_dispose(info);
 692 }
 693 
 694 /*************** end of shared utility code ****************/
 695 
 696 /********************** Loader Support **************************/
 697 
 698 /********************** Source Management ***********************/
 699 
 700 /*
 701  * INPUT HANDLING:
 702  *
 703  * The JPEG library's input management is defined by the jpeg_source_mgr
 704  * structure which contains two fields to convey the information in the
 705  * buffer and 5 methods which perform all buffer management.  The library
 706  * defines a standard input manager that uses stdio for obtaining compressed
 707  * jpeg data, but here we need to use Java to get our data.
 708  *
 709  * We use the library jpeg_source_mgr but our own routines that access
 710  * imageio-specific information in the imageIOData structure.
 711  */
 712 
 713 /*

1263             cls,
1264             "updateImageProgress",
1265             "(I)V");
1266     if ((*env)->ExceptionCheck(env)) {
1267         return;
1268     }
1269 
1270     JPEGImageLoader_emitWarningID = (*env)->GetMethodID(env,
1271             cls,
1272             "emitWarning",
1273             "(Ljava/lang/String;)V");
1274     if ((*env)->ExceptionCheck(env)) {
1275         return;
1276     }
1277 
1278 }
1279 
1280 JNIEXPORT void JNICALL Java_com_sun_javafx_iio_jpeg_JPEGImageLoader_disposeNative
1281 (JNIEnv *env, jclass cls, jlong ptr) {
1282     imageIODataPtr data = (imageIODataPtr) jlong_to_ptr(ptr);
1283     disposeIIO(env, data);


1284 }
1285 
1286 #define JPEG_APP1  (JPEG_APP0 + 1)  /* EXIF APP1 marker code  */
1287 
1288 /*
1289  * For EXIF images, the APP1 will appear immediately after the SOI,
1290  * so it's safe to only look at the first marker in the list.
1291  * (see http://www.exif.org/Exif2-2.PDF, section 4.7, page 58)
1292  */
1293 #define IS_EXIF(c) \
1294     (((c)->marker_list != NULL) && ((c)->marker_list->marker == JPEG_APP1))
1295 
1296 JNIEXPORT jlong JNICALL Java_com_sun_javafx_iio_jpeg_JPEGImageLoader_initDecompressor
1297 (JNIEnv *env, jobject this, jobject stream) {
1298     imageIODataPtr data;
1299     struct sun_jpeg_error_mgr *jerr_mgr;
1300 
1301     /* This struct contains the JPEG decompression parameters and pointers to
1302      * working space (which is allocated as needed by the JPEG library).
1303      */

1324         free(cinfo);
1325         ThrowByName(env,
1326                 "java/lang/OutOfMemoryError",
1327                 "Initializing Reader");
1328         return 0;
1329     }
1330 
1331     /* We set up the normal JPEG error routines, then override error_exit. */
1332     cinfo->err = jpeg_std_error(&(jerr_mgr->pub));
1333     jerr_mgr->pub.error_exit = sun_jpeg_error_exit;
1334     /* We need to setup our own print routines */
1335     jerr_mgr->pub.output_message = sun_jpeg_output_message;
1336     /* Now we can setjmp before every call to the library */
1337 
1338     /* Establish the setjmp return context for sun_jpeg_error_exit to use. */
1339     if (setjmp(jerr_mgr->setjmp_buffer)) {
1340         /* If we get here, the JPEG code has signaled an error. */
1341         char buffer[JMSG_LENGTH_MAX];
1342         (*cinfo->err->format_message) ((struct jpeg_common_struct *) cinfo,
1343                 buffer);
1344         free(cinfo->err);
1345         free(cinfo);
1346         ThrowByName(env, "java/io/IOException", buffer);
1347         return 0;
1348     }
1349 
1350     /* Perform library initialization */
1351     jpeg_create_decompress(cinfo);
1352 
1353     // Set up to keep any APP2 markers, as these might contain ICC profile
1354     // data
1355     jpeg_save_markers(cinfo, ICC_MARKER, 0xFFFF);
1356 
1357     /*
1358      * Now set up our source.
1359      */
1360     cinfo->src =
1361             (struct jpeg_source_mgr *) malloc(sizeof (struct jpeg_source_mgr));
1362     if (cinfo->src == NULL) {
1363         imageio_dispose((j_common_ptr) cinfo);
1364         ThrowByName(env,
1365                 "java/lang/OutOfMemoryError",
1366                 "Initializing Reader");
1367         return 0;
1368     }
1369     cinfo->src->bytes_in_buffer = 0;
1370     cinfo->src->next_input_byte = NULL;
1371     cinfo->src->init_source = imageio_init_source;
1372     cinfo->src->fill_input_buffer = imageio_fill_input_buffer;
1373     cinfo->src->skip_input_data = imageio_skip_input_data;
1374     cinfo->src->resync_to_restart = jpeg_resync_to_restart; // use default
1375     cinfo->src->term_source = imageio_term_source;
1376 
1377     /* set up the association to persist for future calls */
1378     data = initImageioData(env, (j_common_ptr) cinfo, this);
1379     if (data == NULL) {
1380         imageio_dispose((j_common_ptr) cinfo);
1381         ThrowByName(env,
1382                 "java/lang/OutOfMemoryError",
1383                 "Initializing Reader");
1384         return 0;
1385     }
1386 
1387     imageio_set_stream(env, (j_common_ptr) cinfo, data, stream);
1388 
1389     if ((*env)->ExceptionCheck(env)) {
1390         disposeIIO(env, data);
1391         return 0;
1392     }
1393 
1394     imageio_init_source((j_decompress_ptr) cinfo);
1395 
1396     src = cinfo->src;
1397     jerr = (sun_jpeg_error_ptr) cinfo->err;
1398 
1399     /* Establish the setjmp return context for sun_jpeg_error_exit to use. */
1400     if (setjmp(jerr->setjmp_buffer)) {
1401         /* If we get here, the JPEG code has signaled an error
1402            while reading the header. */
1403         disposeIIO(env, data);
1404         if (!(*env)->ExceptionOccurred(env)) {
1405             char buffer[JMSG_LENGTH_MAX];
1406             (*cinfo->err->format_message) ((struct jpeg_common_struct *) cinfo,
1407                     buffer);
1408             ThrowByName(env, "java/io/IOException", buffer);
1409         }
1410 
1411         return 0;
1412     }
1413 
1414     if (GET_ARRAYS(env, data, &src->next_input_byte) == NOT_OK) {
1415         ThrowByName(env,
1416                 "java/io/IOException",
1417                 "Array pin failed");
1418         disposeIIO(env, data);
1419         return 0;
1420     }
1421 
1422     jret = jpeg_read_header(cinfo, FALSE);
1423 
1424     if (jret == JPEG_HEADER_TABLES_ONLY) {
1425         imageio_term_source(cinfo); // Pushback remaining buffer contents
1426 #ifdef DEBUG_IIO_JPEG
1427         printf("just read tables-only image; q table 0 at %p\n",
1428                 cinfo->quant_tbl_ptrs[0]);
1429 #endif
1430         RELEASE_ARRAYS(env, data, src->next_input_byte);
1431     } else {
1432         /*
1433          * Now adjust the jpeg_color_space variable, which was set in
1434          * default_decompress_parms, to reflect our differences from IJG
1435          */
1436 
1437         switch (cinfo->jpeg_color_space) {
1438             default:

1495 
1496                 v_samp0 = cinfo->comp_info[0].v_samp_factor;
1497                 v_samp1 = cinfo->comp_info[1].v_samp_factor;
1498                 v_samp2 = cinfo->comp_info[2].v_samp_factor;
1499 
1500                 if ((h_samp1 > h_samp0) && (h_samp2 > h_samp0) ||
1501                         (v_samp1 > v_samp0) && (v_samp2 > v_samp0)) {
1502                     cinfo->jpeg_color_space = JCS_YCCK;
1503                     /* Leave the output space as CMYK */
1504                 }
1505 
1506                 /* There is no support for CMYK on jfx side, so request RGB output */
1507                 cinfo->out_color_space = JCS_RGB;
1508         }
1509         RELEASE_ARRAYS(env, data, src->next_input_byte);
1510 
1511         /* read icc profile data */
1512         profileData = read_icc_profile(env, cinfo);
1513 
1514         if ((*env)->ExceptionCheck(env)) {
1515             disposeIIO(env, data);
1516             return 0;
1517         }
1518 
1519         (*env)->CallVoidMethod(env, this,
1520                 JPEGImageLoader_setInputAttributesID,
1521                 cinfo->image_width,
1522                 cinfo->image_height,
1523                 cinfo->jpeg_color_space,
1524                 cinfo->out_color_space,
1525                 cinfo->num_components,
1526                 profileData);
1527         if ((*env)->ExceptionCheck(env)) {
1528             disposeIIO(env, data);
1529             return 0;
1530         }
1531     }
1532 
1533     return ptr_to_jlong(data);
1534 }
1535 
1536 JNIEXPORT jint JNICALL Java_com_sun_javafx_iio_jpeg_JPEGImageLoader_startDecompression
1537 (JNIEnv *env, jobject this, jlong ptr, jint outCS, jint dest_width, jint dest_height) {
1538     imageIODataPtr data = (imageIODataPtr) jlong_to_ptr(ptr);
1539     j_decompress_ptr cinfo = (j_decompress_ptr) data->jpegObj;
1540     struct jpeg_source_mgr *src = cinfo->src;
1541     sun_jpeg_error_ptr jerr;
1542 
1543     jfloat x_scale;
1544     jfloat y_scale;
1545     jfloat max_scale;
1546 
1547     if (GET_ARRAYS(env, data, &cinfo->src->next_input_byte) == NOT_OK) {
1548         ThrowByName(env,

1603     jpeg_start_decompress(cinfo);
1604 
1605     RELEASE_ARRAYS(env, data, cinfo->src->next_input_byte);
1606     (*env)->CallVoidMethod(env, this,
1607             JPEGImageLoader_setOutputAttributesID,
1608             cinfo->output_width,
1609             cinfo->output_height);
1610 
1611     return cinfo->output_components;
1612 }
1613 
1614 #define SAFE_TO_MULT(a, b) (((a) > 0) && ((b) >= 0) && ((0x7fffffff / (a)) > (b)))
1615 
1616 JNIEXPORT jboolean JNICALL Java_com_sun_javafx_iio_jpeg_JPEGImageLoader_decompressIndirect
1617 (JNIEnv *env, jobject this, jlong ptr, jboolean report_progress, jbyteArray barray) {
1618     imageIODataPtr data = (imageIODataPtr) jlong_to_ptr(ptr);
1619     j_decompress_ptr cinfo = (j_decompress_ptr) data->jpegObj;
1620     struct jpeg_source_mgr *src = cinfo->src;
1621     sun_jpeg_error_ptr jerr;
1622     int bytes_per_row = cinfo->output_width * cinfo->output_components;

1623     int offset = 0;
1624     JSAMPROW scanline_ptr = NULL;
1625 
1626     if (!SAFE_TO_MULT(cinfo->output_width, cinfo->output_components) ||
1627         !SAFE_TO_MULT(bytes_per_row, cinfo->output_height) ||
1628         ((*env)->GetArrayLength(env, barray) <
1629          (bytes_per_row * cinfo->output_height)))
1630      {
1631         ThrowByName(env,
1632                 "java/lang/OutOfMemoryError",
1633                 "Reading JPEG Stream");
1634         return JNI_FALSE;
1635     }
1636 
1637     if (GET_ARRAYS(env, data, &cinfo->src->next_input_byte) == NOT_OK) {
1638         ThrowByName(env,
1639                 "java/io/IOException",
1640                 "Array pin failed");
1641         return JNI_FALSE;
1642     }
1643 








1644     /* Establish the setjmp return context for sun_jpeg_error_exit to use. */
1645     jerr = (sun_jpeg_error_ptr) cinfo->err;
1646 
1647     if (setjmp(jerr->setjmp_buffer)) {
1648         /* If we get here, the JPEG code has signaled an error
1649            while reading. */
1650         if (!(*env)->ExceptionOccurred(env)) {
1651             char buffer[JMSG_LENGTH_MAX];
1652             (*cinfo->err->format_message) ((struct jpeg_common_struct *) cinfo,
1653                     buffer);
1654             ThrowByName(env, "java/io/IOException", buffer);
1655         }



1656         RELEASE_ARRAYS(env, data, cinfo->src->next_input_byte);
1657         return JNI_FALSE;
1658     }
1659 
1660     scanline_ptr = (JSAMPROW) malloc(bytes_per_row * sizeof(JSAMPLE));
1661     if (scanline_ptr == NULL) {
1662         ThrowByName(env,
1663                 "java/lang/OutOfMemoryError",
1664                 "Reading JPEG Stream");
1665         return JNI_FALSE;
1666     }
1667 
1668     while (cinfo->output_scanline < cinfo->output_height) {
1669         int num_scanlines;
1670         if (report_progress == JNI_TRUE) {
1671             RELEASE_ARRAYS(env, data, cinfo->src->next_input_byte);
1672             (*env)->CallVoidMethod(env, this,
1673                     JPEGImageLoader_updateImageProgressID,
1674                     cinfo->output_scanline);
1675             if ((*env)->ExceptionCheck(env)) {
1676                 free(scanline_ptr);
1677                 return JNI_FALSE;
1678             }
1679             if (GET_ARRAYS(env, data, &cinfo->src->next_input_byte) == NOT_OK) {
1680                 free(scanline_ptr);
1681                 ThrowByName(env,
1682                           "java/io/IOException",
1683                           "Array pin failed");
1684                 return JNI_FALSE;
1685             }
1686         }
1687 
1688         num_scanlines = jpeg_read_scanlines(cinfo, &scanline_ptr, 1);
1689         if (num_scanlines == 1) {
1690             jboolean iscopy = FALSE;
1691             jbyte *body = (*env)->GetPrimitiveArrayCritical(env, barray, &iscopy);
1692             if (body == NULL) {
1693                 fprintf(stderr, "decompressIndirect: GetPrimitiveArrayCritical returns NULL: out of memory\n");
1694                 free(scanline_ptr);
1695                 return JNI_FALSE;
1696             }
1697             memcpy(body+offset,scanline_ptr, bytes_per_row);
1698             (*env)->ReleasePrimitiveArrayCritical(env, barray, body, JNI_ABORT);
1699             offset += bytes_per_row;
1700         }
1701     }
1702     free(scanline_ptr);
1703 
1704     if (report_progress == JNI_TRUE) {
1705         RELEASE_ARRAYS(env, data, cinfo->src->next_input_byte);
1706         (*env)->CallVoidMethod(env, this,
1707                 JPEGImageLoader_updateImageProgressID,
1708                 cinfo->output_height);
1709         if ((*env)->ExceptionCheck(env)) {
1710             return JNI_FALSE;
1711         }
1712         if (GET_ARRAYS(env, data, &cinfo->src->next_input_byte) == NOT_OK) {
1713             ThrowByName(env,
1714                 "java/io/IOException",
1715                 "Array pin failed");
1716             return JNI_FALSE;
1717         }
1718     }
1719 
1720     jpeg_finish_decompress(cinfo);

1721 
1722     RELEASE_ARRAYS(env, data, cinfo->src->next_input_byte);
1723     return JNI_TRUE;
1724 }
< prev index next >