< prev index next >

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

Print this page

 661         info->err = NULL;
 662         if (info->is_decompressor) {
 663             j_decompress_ptr dinfo = (j_decompress_ptr) info;
 664             free(dinfo->src);
 665             dinfo->src = NULL;
 666         } else {
 667             j_compress_ptr cinfo = (j_compress_ptr) info;
 668             free(cinfo->dest);
 669             cinfo->dest = NULL;
 670         }
 671         jpeg_destroy(info);
 672         free(info);
 673     }
 674 }
 675 
 676 static void imageio_abort(JNIEnv *env, jobject this,
 677         imageIODataPtr data) {
 678     data->abortFlag = JNI_TRUE;
 679 }
 680 





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

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

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


1333         ThrowByName(env, "java/io/IOException", buffer);
1334         return 0;
1335     }
1336 
1337     /* Perform library initialization */
1338     jpeg_create_decompress(cinfo);
1339 
1340     // Set up to keep any APP2 markers, as these might contain ICC profile
1341     // data
1342     jpeg_save_markers(cinfo, ICC_MARKER, 0xFFFF);
1343 
1344     /*
1345      * Now set up our source.
1346      */
1347     cinfo->src =
1348             (struct jpeg_source_mgr *) malloc(sizeof (struct jpeg_source_mgr));
1349     if (cinfo->src == NULL) {

1350         ThrowByName(env,
1351                 "java/lang/OutOfMemoryError",
1352                 "Initializing Reader");
1353         return 0;
1354     }
1355     cinfo->src->bytes_in_buffer = 0;
1356     cinfo->src->next_input_byte = NULL;
1357     cinfo->src->init_source = imageio_init_source;
1358     cinfo->src->fill_input_buffer = imageio_fill_input_buffer;
1359     cinfo->src->skip_input_data = imageio_skip_input_data;
1360     cinfo->src->resync_to_restart = jpeg_resync_to_restart; // use default
1361     cinfo->src->term_source = imageio_term_source;
1362 
1363     /* set up the association to persist for future calls */
1364     data = initImageioData(env, (j_common_ptr) cinfo, this);
1365     if (data == NULL) {

1366         ThrowByName(env,
1367                 "java/lang/OutOfMemoryError",
1368                 "Initializing Reader");
1369         return 0;
1370     }
1371 
1372     imageio_set_stream(env, (j_common_ptr) cinfo, data, stream);
1373 
1374     if ((*env)->ExceptionCheck(env)) return 0;



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

1392         return 0;
1393     }
1394 
1395     if (GET_ARRAYS(env, data, &src->next_input_byte) == NOT_OK) {
1396         ThrowByName(env,
1397                 "java/io/IOException",
1398                 "Array pin failed");

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

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

1495             return 0;
1496         }
1497 
1498         (*env)->CallVoidMethod(env, this,
1499                 JPEGImageLoader_setInputAttributesID,
1500                 cinfo->image_width,
1501                 cinfo->image_height,
1502                 cinfo->jpeg_color_space,
1503                 cinfo->out_color_space,
1504                 cinfo->num_components,
1505                 profileData);
1506         if ((*env)->ExceptionCheck(env)) {

1507             return 0;
1508         }
1509     }
1510 
1511     return ptr_to_jlong(data);
1512 }
1513 
1514 JNIEXPORT jint JNICALL Java_com_sun_javafx_iio_jpeg_JPEGImageLoader_startDecompression
1515 (JNIEnv *env, jobject this, jlong ptr, jint outCS, jint dest_width, jint dest_height) {
1516     imageIODataPtr data = (imageIODataPtr) jlong_to_ptr(ptr);
1517     j_decompress_ptr cinfo = (j_decompress_ptr) data->jpegObj;
1518     struct jpeg_source_mgr *src = cinfo->src;
1519     sun_jpeg_error_ptr jerr;
1520 
1521     jfloat x_scale;
1522     jfloat y_scale;
1523     jfloat max_scale;
1524 
1525     if (GET_ARRAYS(env, data, &cinfo->src->next_input_byte) == NOT_OK) {
1526         ThrowByName(env,

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

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








1649     while (cinfo->output_scanline < cinfo->output_height) {
1650         int num_scanlines;
1651         if (report_progress == JNI_TRUE) {
1652             RELEASE_ARRAYS(env, data, cinfo->src->next_input_byte);
1653             (*env)->CallVoidMethod(env, this,
1654                     JPEGImageLoader_updateImageProgressID,
1655                     cinfo->output_scanline);
1656             if ((*env)->ExceptionCheck(env)) return JNI_FALSE;



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

1659                           "java/io/IOException",
1660                           "Array pin failed");
1661               return JNI_FALSE;
1662             }
1663         }
1664 
1665         num_scanlines = jpeg_read_scanlines(cinfo, &scanline_ptr, 1);
1666         if (num_scanlines == 1) {
1667             jbyte *body = (*env)->GetPrimitiveArrayCritical(env, barray, NULL);
1668             if (body == NULL) {
1669                 fprintf(stderr, "decompressIndirect: GetPrimitiveArrayCritical returns NULL: out of memory\n");

1670                 return JNI_FALSE;
1671             }
1672             memcpy(body+offset,scanline_ptr, bytes_per_row);
1673             (*env)->ReleasePrimitiveArrayCritical(env, barray, body, JNI_ABORT);
1674             offset += bytes_per_row;
1675         }
1676     }

1677 
1678     if (report_progress == JNI_TRUE) {
1679         RELEASE_ARRAYS(env, data, cinfo->src->next_input_byte);
1680         (*env)->CallVoidMethod(env, this,
1681                 JPEGImageLoader_updateImageProgressID,
1682                 cinfo->output_height);
1683       if ((*env)->ExceptionCheck(env)) return JNI_FALSE;
1684       if (GET_ARRAYS(env, data, &cinfo->src->next_input_byte) == NOT_OK) {
1685           ThrowByName(env,


1686                 "java/io/IOException",
1687                 "Array pin failed");
1688           return JNI_FALSE;
1689       }
1690     }
1691 
1692     jpeg_finish_decompress(cinfo);
1693     free(scanline_ptr);
1694 
1695     RELEASE_ARRAYS(env, data, cinfo->src->next_input_byte);
1696     return JNI_TRUE;
1697 }

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

1255             cls,
1256             "updateImageProgress",
1257             "(I)V");
1258     if ((*env)->ExceptionCheck(env)) {
1259         return;
1260     }
1261 
1262     JPEGImageLoader_emitWarningID = (*env)->GetMethodID(env,
1263             cls,
1264             "emitWarning",
1265             "(Ljava/lang/String;)V");
1266     if ((*env)->ExceptionCheck(env)) {
1267         return;
1268     }
1269 
1270 }
1271 
1272 JNIEXPORT void JNICALL Java_com_sun_javafx_iio_jpeg_JPEGImageLoader_disposeNative
1273 (JNIEnv *env, jclass cls, jlong ptr) {
1274     imageIODataPtr data = (imageIODataPtr) jlong_to_ptr(ptr);
1275     disposeIIO(env, data);


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

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

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

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

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








1636     /* Establish the setjmp return context for sun_jpeg_error_exit to use. */
1637     jerr = (sun_jpeg_error_ptr) cinfo->err;
1638 
1639     if (setjmp(jerr->setjmp_buffer)) {
1640         /* If we get here, the JPEG code has signaled an error
1641            while reading. */
1642         if (!(*env)->ExceptionOccurred(env)) {
1643             char buffer[JMSG_LENGTH_MAX];
1644             (*cinfo->err->format_message) ((struct jpeg_common_struct *) cinfo,
1645                     buffer);
1646             ThrowByName(env, "java/io/IOException", buffer);
1647         }



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

1712 
1713     RELEASE_ARRAYS(env, data, cinfo->src->next_input_byte);
1714     return JNI_TRUE;
1715 }
< prev index next >