/java-1.7.0-openjdk/openjdk/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c

# · C · 3024 lines · 1971 code · 425 blank · 628 comment · 406 complexity · 7b7e4027d0060cc39313d97c919e9592 MD5 · raw file

Large files are truncated click here to view the full file

  1. /*
  2. * Copyright (c) 2000, 2011, 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
  23. * questions.
  24. */
  25. /*
  26. * This file contains the code to link the Java Image I/O JPEG plug-in
  27. * to the IJG library used to read and write JPEG files. Much of it has
  28. * been copied, updated, and annotated from the jpegdecoder.c AWT JPEG
  29. * decoder. Where that code was unclear, the present author has either
  30. * rewritten the relevant section or commented it for the sake of future
  31. * maintainers.
  32. *
  33. * In particular, the way the AWT code handled progressive JPEGs seems
  34. * to me to be only accidentally correct and somewhat inefficient. The
  35. * scheme used here represents the way I think it should work. (REV 11/00)
  36. */
  37. #include <stdlib.h>
  38. #include <setjmp.h>
  39. #include <assert.h>
  40. #include <string.h>
  41. #include <limits.h>
  42. /* java native interface headers */
  43. #include "jni.h"
  44. #include "jni_util.h"
  45. #include "com_sun_imageio_plugins_jpeg_JPEGImageReader.h"
  46. #include "com_sun_imageio_plugins_jpeg_JPEGImageWriter.h"
  47. /* headers from the JPEG library */
  48. #include <jpeglib.h>
  49. #include <jerror.h>
  50. #undef MAX
  51. #define MAX(a,b) ((a) > (b) ? (a) : (b))
  52. /* Cached Java method ids */
  53. static jmethodID ImageInputStream_readID;
  54. static jmethodID ImageInputStream_skipBytesID;
  55. static jmethodID JPEGImageReader_warningOccurredID;
  56. static jmethodID JPEGImageReader_warningWithMessageID;
  57. static jmethodID JPEGImageReader_setImageDataID;
  58. static jmethodID JPEGImageReader_acceptPixelsID;
  59. static jmethodID JPEGImageReader_pushBackID;
  60. static jmethodID JPEGImageReader_passStartedID;
  61. static jmethodID JPEGImageReader_passCompleteID;
  62. static jmethodID ImageOutputStream_writeID;
  63. static jmethodID JPEGImageWriter_warningOccurredID;
  64. static jmethodID JPEGImageWriter_warningWithMessageID;
  65. static jmethodID JPEGImageWriter_writeMetadataID;
  66. static jmethodID JPEGImageWriter_grabPixelsID;
  67. static jfieldID JPEGQTable_tableID;
  68. static jfieldID JPEGHuffmanTable_lengthsID;
  69. static jfieldID JPEGHuffmanTable_valuesID;
  70. /*
  71. * Defined in jpegdecoder.c. Copy code from there if and
  72. * when that disappears. */
  73. extern JavaVM *jvm;
  74. /*
  75. * The following sets of defines must match the warning messages in the
  76. * Java code.
  77. */
  78. /* Reader warnings */
  79. #define READ_NO_EOI 0
  80. /* Writer warnings */
  81. /* Return codes for various ops */
  82. #define OK 1
  83. #define NOT_OK 0
  84. /*
  85. * First we define two objects, one for the stream and buffer and one
  86. * for pixels. Both contain references to Java objects and pointers to
  87. * pinned arrays. These objects can be used for either input or
  88. * output. Pixels can be accessed as either INT32s or bytes.
  89. * Every I/O operation will have one of each these objects, one for
  90. * the stream and the other to hold pixels, regardless of the I/O direction.
  91. */
  92. /******************** StreamBuffer definition ************************/
  93. typedef struct streamBufferStruct {
  94. jobject stream; // ImageInputStream or ImageOutputStream
  95. jbyteArray hstreamBuffer; // Handle to a Java buffer for the stream
  96. JOCTET *buf; // Pinned buffer pointer */
  97. size_t bufferOffset; // holds offset between unpin and the next pin
  98. size_t bufferLength; // Allocated, nut just used
  99. int suspendable; // Set to true to suspend input
  100. long remaining_skip; // Used only on input
  101. } streamBuffer, *streamBufferPtr;
  102. /*
  103. * This buffer size was set to 64K in the old classes, 4K by default in the
  104. * IJG library, with the comment "an efficiently freadable size", and 1K
  105. * in AWT.
  106. * Unlike in the other Java designs, these objects will persist, so 64K
  107. * seems too big and 1K seems too small. If 4K was good enough for the
  108. * IJG folks, it's good enough for me.
  109. */
  110. #define STREAMBUF_SIZE 4096
  111. /*
  112. * Used to signal that no data need be restored from an unpin to a pin.
  113. * I.e. the buffer is empty.
  114. */
  115. #define NO_DATA ((size_t)-1)
  116. // Forward reference
  117. static void resetStreamBuffer(JNIEnv *env, streamBufferPtr sb);
  118. /*
  119. * Initialize a freshly allocated StreamBuffer object. The stream is left
  120. * null, as it will be set from Java by setSource, but the buffer object
  121. * is created and a global reference kept. Returns OK on success, NOT_OK
  122. * if allocating the buffer or getting a global reference for it failed.
  123. */
  124. static int initStreamBuffer(JNIEnv *env, streamBufferPtr sb) {
  125. /* Initialize a new buffer */
  126. jbyteArray hInputBuffer = (*env)->NewByteArray(env, STREAMBUF_SIZE);
  127. if (hInputBuffer == NULL) {
  128. JNU_ThrowByName( env,
  129. "java/lang/OutOfMemoryError",
  130. "Initializing Reader");
  131. return NOT_OK;
  132. }
  133. sb->bufferLength = (*env)->GetArrayLength(env, hInputBuffer);
  134. sb->hstreamBuffer = (*env)->NewGlobalRef(env, hInputBuffer);
  135. if (sb->hstreamBuffer == NULL) {
  136. JNU_ThrowByName( env,
  137. "java/lang/OutOfMemoryError",
  138. "Initializing Reader");
  139. return NOT_OK;
  140. }
  141. sb->stream = NULL;
  142. sb->buf = NULL;
  143. resetStreamBuffer(env, sb);
  144. return OK;
  145. }
  146. /*
  147. * Free all resources associated with this streamBuffer. This must
  148. * be called to dispose the object to avoid leaking global references, as
  149. * resetStreamBuffer does not release the buffer reference.
  150. */
  151. static void destroyStreamBuffer(JNIEnv *env, streamBufferPtr sb) {
  152. resetStreamBuffer(env, sb);
  153. if (sb->hstreamBuffer != NULL) {
  154. (*env)->DeleteGlobalRef(env, sb->hstreamBuffer);
  155. }
  156. }
  157. // Forward reference
  158. static void unpinStreamBuffer(JNIEnv *env,
  159. streamBufferPtr sb,
  160. const JOCTET *next_byte);
  161. /*
  162. * Resets the state of a streamBuffer object that has been in use.
  163. * The global reference to the stream is released, but the reference
  164. * to the buffer is retained. The buffer is unpinned if it was pinned.
  165. * All other state is reset.
  166. */
  167. static void resetStreamBuffer(JNIEnv *env, streamBufferPtr sb) {
  168. if (sb->stream != NULL) {
  169. (*env)->DeleteGlobalRef(env, sb->stream);
  170. sb->stream = NULL;
  171. }
  172. unpinStreamBuffer(env, sb, NULL);
  173. sb->bufferOffset = NO_DATA;
  174. sb->suspendable = FALSE;
  175. sb->remaining_skip = 0;
  176. }
  177. /*
  178. * Pins the data buffer associated with this stream. Returns OK on
  179. * success, NOT_OK on failure, as GetPrimitiveArrayCritical may fail.
  180. */
  181. static int pinStreamBuffer(JNIEnv *env,
  182. streamBufferPtr sb,
  183. const JOCTET **next_byte) {
  184. if (sb->hstreamBuffer != NULL) {
  185. assert(sb->buf == NULL);
  186. sb->buf =
  187. (JOCTET *)(*env)->GetPrimitiveArrayCritical(env,
  188. sb->hstreamBuffer,
  189. NULL);
  190. if (sb->buf == NULL) {
  191. return NOT_OK;
  192. }
  193. if (sb->bufferOffset != NO_DATA) {
  194. *next_byte = sb->buf + sb->bufferOffset;
  195. }
  196. }
  197. return OK;
  198. }
  199. /*
  200. * Unpins the data buffer associated with this stream.
  201. */
  202. static void unpinStreamBuffer(JNIEnv *env,
  203. streamBufferPtr sb,
  204. const JOCTET *next_byte) {
  205. if (sb->buf != NULL) {
  206. assert(sb->hstreamBuffer != NULL);
  207. if (next_byte == NULL) {
  208. sb->bufferOffset = NO_DATA;
  209. } else {
  210. sb->bufferOffset = next_byte - sb->buf;
  211. }
  212. (*env)->ReleasePrimitiveArrayCritical(env,
  213. sb->hstreamBuffer,
  214. sb->buf,
  215. 0);
  216. sb->buf = NULL;
  217. }
  218. }
  219. /*
  220. * Clear out the streamBuffer. This just invalidates the data in the buffer.
  221. */
  222. static void clearStreamBuffer(streamBufferPtr sb) {
  223. sb->bufferOffset = NO_DATA;
  224. }
  225. /*************************** end StreamBuffer definition *************/
  226. /*************************** Pixel Buffer definition ******************/
  227. typedef struct pixelBufferStruct {
  228. jobject hpixelObject; // Usually a DataBuffer bank as a byte array
  229. unsigned int byteBufferLength;
  230. union pixptr {
  231. INT32 *ip; // Pinned buffer pointer, as 32-bit ints
  232. unsigned char *bp; // Pinned buffer pointer, as bytes
  233. } buf;
  234. } pixelBuffer, *pixelBufferPtr;
  235. /*
  236. * Initialize a freshly allocated PixelBuffer. All fields are simply
  237. * set to NULL, as we have no idea what size buffer we will need.
  238. */
  239. static void initPixelBuffer(pixelBufferPtr pb) {
  240. pb->hpixelObject = NULL;
  241. pb->byteBufferLength = 0;
  242. pb->buf.ip = NULL;
  243. }
  244. /*
  245. * Set the pixelBuffer to use the given buffer, acquiring a new global
  246. * reference for it. Returns OK on success, NOT_OK on failure.
  247. */
  248. static int setPixelBuffer(JNIEnv *env, pixelBufferPtr pb, jobject obj) {
  249. pb->hpixelObject = (*env)->NewGlobalRef(env, obj);
  250. if (pb->hpixelObject == NULL) {
  251. JNU_ThrowByName( env,
  252. "java/lang/OutOfMemoryError",
  253. "Setting Pixel Buffer");
  254. return NOT_OK;
  255. }
  256. pb->byteBufferLength = (*env)->GetArrayLength(env, pb->hpixelObject);
  257. return OK;
  258. }
  259. // Forward reference
  260. static void unpinPixelBuffer(JNIEnv *env, pixelBufferPtr pb);
  261. /*
  262. * Resets a pixel buffer to its initial state. Unpins any pixel buffer,
  263. * releases the global reference, and resets fields to NULL. Use this
  264. * method to dispose the object as well (there is no destroyPixelBuffer).
  265. */
  266. static void resetPixelBuffer(JNIEnv *env, pixelBufferPtr pb) {
  267. if (pb->hpixelObject != NULL) {
  268. unpinPixelBuffer(env, pb);
  269. (*env)->DeleteGlobalRef(env, pb->hpixelObject);
  270. pb->hpixelObject = NULL;
  271. pb->byteBufferLength = 0;
  272. }
  273. }
  274. /*
  275. * Pins the data buffer. Returns OK on success, NOT_OK on failure.
  276. */
  277. static int pinPixelBuffer(JNIEnv *env, pixelBufferPtr pb) {
  278. if (pb->hpixelObject != NULL) {
  279. assert(pb->buf.ip == NULL);
  280. pb->buf.bp = (unsigned char *)(*env)->GetPrimitiveArrayCritical
  281. (env, pb->hpixelObject, NULL);
  282. if (pb->buf.bp == NULL) {
  283. return NOT_OK;
  284. }
  285. }
  286. return OK;
  287. }
  288. /*
  289. * Unpins the data buffer.
  290. */
  291. static void unpinPixelBuffer(JNIEnv *env, pixelBufferPtr pb) {
  292. if (pb->buf.ip != NULL) {
  293. assert(pb->hpixelObject != NULL);
  294. (*env)->ReleasePrimitiveArrayCritical(env,
  295. pb->hpixelObject,
  296. pb->buf.ip,
  297. 0);
  298. pb->buf.ip = NULL;
  299. }
  300. }
  301. /********************* end PixelBuffer definition *******************/
  302. /********************* ImageIOData definition ***********************/
  303. #define MAX_BANDS 4
  304. #define JPEG_BAND_SIZE 8
  305. #define NUM_BAND_VALUES (1<<JPEG_BAND_SIZE)
  306. #define MAX_JPEG_BAND_VALUE (NUM_BAND_VALUES-1)
  307. #define HALF_MAX_JPEG_BAND_VALUE (MAX_JPEG_BAND_VALUE>>1)
  308. /* The number of possible incoming values to be scaled. */
  309. #define NUM_INPUT_VALUES (1 << 16)
  310. /*
  311. * The principal imageioData object, opaque to I/O direction.
  312. * Each JPEGImageReader will have associated with it a
  313. * jpeg_decompress_struct, and similarly each JPEGImageWriter will
  314. * have associated with it a jpeg_compress_struct. In order to
  315. * ensure that these associations persist from one native call to
  316. * the next, and to provide a central locus of imageio-specific
  317. * data, we define an imageioData struct containing references
  318. * to the Java object and the IJG structs. The functions
  319. * that manipulate these objects know whether input or output is being
  320. * performed and therefore know how to manipulate the contents correctly.
  321. * If for some reason they don't, the direction can be determined by
  322. * checking the is_decompressor field of the jpegObj.
  323. * In order for lower level code to determine a
  324. * Java object given an IJG struct, such as for dispatching warnings,
  325. * we use the client_data field of the jpeg object to store a pointer
  326. * to the imageIOData object. Maintenance of this pointer is performed
  327. * exclusively within the following access functions. If you
  328. * change that, you run the risk of dangling pointers.
  329. */
  330. typedef struct imageIODataStruct {
  331. j_common_ptr jpegObj; // Either struct is fine
  332. jobject imageIOobj; // A JPEGImageReader or a JPEGImageWriter
  333. streamBuffer streamBuf; // Buffer for the stream
  334. pixelBuffer pixelBuf; // Buffer for pixels
  335. jboolean abortFlag; // Passed down from Java abort method
  336. } imageIOData, *imageIODataPtr;
  337. /*
  338. * Allocate and initialize a new imageIOData object to associate the
  339. * jpeg object and the Java object. Returns a pointer to the new object
  340. * on success, NULL on failure.
  341. */
  342. static imageIODataPtr initImageioData (JNIEnv *env,
  343. j_common_ptr cinfo,
  344. jobject obj) {
  345. imageIODataPtr data = (imageIODataPtr) malloc (sizeof(imageIOData));
  346. if (data == NULL) {
  347. return NULL;
  348. }
  349. data->jpegObj = cinfo;
  350. cinfo->client_data = data;
  351. #ifdef DEBUG_IIO_JPEG
  352. printf("new structures: data is %p, cinfo is %p\n", data, cinfo);
  353. #endif
  354. data->imageIOobj = (*env)->NewWeakGlobalRef(env, obj);
  355. if (data->imageIOobj == NULL) {
  356. free (data);
  357. return NULL;
  358. }
  359. if (initStreamBuffer(env, &data->streamBuf) == NOT_OK) {
  360. (*env)->DeleteWeakGlobalRef(env, data->imageIOobj);
  361. free (data);
  362. return NULL;
  363. }
  364. initPixelBuffer(&data->pixelBuf);
  365. data->abortFlag = JNI_FALSE;
  366. return data;
  367. }
  368. /*
  369. * Resets the imageIOData object to its initial state, as though
  370. * it had just been allocated and initialized.
  371. */
  372. static void resetImageIOData(JNIEnv *env, imageIODataPtr data) {
  373. resetStreamBuffer(env, &data->streamBuf);
  374. resetPixelBuffer(env, &data->pixelBuf);
  375. data->abortFlag = JNI_FALSE;
  376. }
  377. /*
  378. * Releases all resources held by this object and its subobjects,
  379. * frees the object, and returns the jpeg object. This method must
  380. * be called to avoid leaking global references.
  381. * Note that the jpeg object is not freed or destroyed, as that is
  382. * the client's responsibility, although the client_data field is
  383. * cleared.
  384. */
  385. static j_common_ptr destroyImageioData(JNIEnv *env, imageIODataPtr data) {
  386. j_common_ptr ret = data->jpegObj;
  387. (*env)->DeleteWeakGlobalRef(env, data->imageIOobj);
  388. destroyStreamBuffer(env, &data->streamBuf);
  389. resetPixelBuffer(env, &data->pixelBuf);
  390. ret->client_data = NULL;
  391. free(data);
  392. return ret;
  393. }
  394. /******************** end ImageIOData definition ***********************/
  395. /******************** Java array pinning and unpinning *****************/
  396. /* We use Get/ReleasePrimitiveArrayCritical functions to avoid
  397. * the need to copy array elements for the above two objects.
  398. *
  399. * MAKE SURE TO:
  400. *
  401. * - carefully insert pairs of RELEASE_ARRAYS and GET_ARRAYS around
  402. * callbacks to Java.
  403. * - call RELEASE_ARRAYS before returning to Java.
  404. *
  405. * Otherwise things will go horribly wrong. There may be memory leaks,
  406. * excessive pinning, or even VM crashes!
  407. *
  408. * Note that GetPrimitiveArrayCritical may fail!
  409. */
  410. /*
  411. * Release (unpin) all the arrays in use during a read.
  412. */
  413. static void RELEASE_ARRAYS(JNIEnv *env, imageIODataPtr data, const JOCTET *next_byte)
  414. {
  415. unpinStreamBuffer(env, &data->streamBuf, next_byte);
  416. unpinPixelBuffer(env, &data->pixelBuf);
  417. }
  418. /*
  419. * Get (pin) all the arrays in use during a read.
  420. */
  421. static int GET_ARRAYS(JNIEnv *env, imageIODataPtr data, const JOCTET **next_byte) {
  422. if (pinStreamBuffer(env, &data->streamBuf, next_byte) == NOT_OK) {
  423. return NOT_OK;
  424. }
  425. if (pinPixelBuffer(env, &data->pixelBuf) == NOT_OK) {
  426. RELEASE_ARRAYS(env, data, *next_byte);
  427. return NOT_OK;
  428. }
  429. return OK;
  430. }
  431. /****** end of Java array pinning and unpinning ***********/
  432. /****** Error Handling *******/
  433. /*
  434. * Set up error handling to use setjmp/longjmp. This is the third such
  435. * setup, as both the AWT jpeg decoder and the com.sun... JPEG classes
  436. * setup thier own. Ultimately these should be integrated, as they all
  437. * do pretty much the same thing.
  438. */
  439. struct sun_jpeg_error_mgr {
  440. struct jpeg_error_mgr pub; /* "public" fields */
  441. jmp_buf setjmp_buffer; /* for return to caller */
  442. };
  443. typedef struct sun_jpeg_error_mgr * sun_jpeg_error_ptr;
  444. /*
  445. * Here's the routine that will replace the standard error_exit method:
  446. */
  447. METHODDEF(void)
  448. sun_jpeg_error_exit (j_common_ptr cinfo)
  449. {
  450. /* cinfo->err really points to a sun_jpeg_error_mgr struct */
  451. sun_jpeg_error_ptr myerr = (sun_jpeg_error_ptr) cinfo->err;
  452. /* For Java, we will format the message and put it in the error we throw. */
  453. /* Return control to the setjmp point */
  454. longjmp(myerr->setjmp_buffer, 1);
  455. }
  456. /*
  457. * Error Message handling
  458. *
  459. * This overrides the output_message method to send JPEG messages
  460. *
  461. */
  462. METHODDEF(void)
  463. sun_jpeg_output_message (j_common_ptr cinfo)
  464. {
  465. char buffer[JMSG_LENGTH_MAX];
  466. jstring string;
  467. imageIODataPtr data = (imageIODataPtr) cinfo->client_data;
  468. JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
  469. jobject theObject;
  470. /* Create the message */
  471. (*cinfo->err->format_message) (cinfo, buffer);
  472. // Create a new java string from the message
  473. string = (*env)->NewStringUTF(env, buffer);
  474. theObject = data->imageIOobj;
  475. if (cinfo->is_decompressor) {
  476. (*env)->CallVoidMethod(env, theObject,
  477. JPEGImageReader_warningWithMessageID,
  478. string);
  479. } else {
  480. (*env)->CallVoidMethod(env, theObject,
  481. JPEGImageWriter_warningWithMessageID,
  482. string);
  483. }
  484. }
  485. /* End of verbatim copy from jpegdecoder.c */
  486. /*************** end of error handling *********************/
  487. /*************** Shared utility code ***********************/
  488. static void imageio_set_stream(JNIEnv *env,
  489. j_common_ptr cinfo,
  490. imageIODataPtr data,
  491. jobject stream){
  492. streamBufferPtr sb;
  493. sun_jpeg_error_ptr jerr;
  494. sb = &data->streamBuf;
  495. resetStreamBuffer(env, sb); // Removes any old stream
  496. /* Now we need a new global reference for the stream */
  497. if (stream != NULL) { // Fix for 4411955
  498. sb->stream = (*env)->NewGlobalRef(env, stream);
  499. if (sb->stream == NULL) {
  500. JNU_ThrowByName(env,
  501. "java/lang/OutOfMemoryError",
  502. "Setting Stream");
  503. return;
  504. }
  505. }
  506. /* And finally reset state */
  507. data->abortFlag = JNI_FALSE;
  508. /* Establish the setjmp return context for sun_jpeg_error_exit to use. */
  509. jerr = (sun_jpeg_error_ptr) cinfo->err;
  510. if (setjmp(jerr->setjmp_buffer)) {
  511. /* If we get here, the JPEG code has signaled an error
  512. while aborting. */
  513. if (!(*env)->ExceptionOccurred(env)) {
  514. char buffer[JMSG_LENGTH_MAX];
  515. (*cinfo->err->format_message) (cinfo,
  516. buffer);
  517. JNU_ThrowByName(env, "javax/imageio/IIOException", buffer);
  518. }
  519. return;
  520. }
  521. jpeg_abort(cinfo); // Frees any markers, but not tables
  522. }
  523. static void imageio_reset(JNIEnv *env,
  524. j_common_ptr cinfo,
  525. imageIODataPtr data) {
  526. sun_jpeg_error_ptr jerr;
  527. resetImageIOData(env, data); // Mapping to jpeg object is retained.
  528. /* Establish the setjmp return context for sun_jpeg_error_exit to use. */
  529. jerr = (sun_jpeg_error_ptr) cinfo->err;
  530. if (setjmp(jerr->setjmp_buffer)) {
  531. /* If we get here, the JPEG code has signaled an error
  532. while aborting. */
  533. if (!(*env)->ExceptionOccurred(env)) {
  534. char buffer[JMSG_LENGTH_MAX];
  535. (*cinfo->err->format_message) (cinfo, buffer);
  536. JNU_ThrowByName(env, "javax/imageio/IIOException", buffer);
  537. }
  538. return;
  539. }
  540. jpeg_abort(cinfo); // Does not reset tables
  541. }
  542. static void imageio_dispose(j_common_ptr info) {
  543. if (info != NULL) {
  544. free(info->err);
  545. info->err = NULL;
  546. if (info->is_decompressor) {
  547. j_decompress_ptr dinfo = (j_decompress_ptr) info;
  548. free(dinfo->src);
  549. dinfo->src = NULL;
  550. } else {
  551. j_compress_ptr cinfo = (j_compress_ptr) info;
  552. free(cinfo->dest);
  553. cinfo->dest = NULL;
  554. }
  555. jpeg_destroy(info);
  556. free(info);
  557. }
  558. }
  559. static void imageio_abort(JNIEnv *env, jobject this,
  560. imageIODataPtr data) {
  561. data->abortFlag = JNI_TRUE;
  562. }
  563. static int setQTables(JNIEnv *env,
  564. j_common_ptr cinfo,
  565. jobjectArray qtables,
  566. boolean write) {
  567. jsize qlen;
  568. jobject table;
  569. jintArray qdata;
  570. jint *qdataBody;
  571. JQUANT_TBL *quant_ptr;
  572. int i, j;
  573. j_compress_ptr comp;
  574. j_decompress_ptr decomp;
  575. qlen = (*env)->GetArrayLength(env, qtables);
  576. #ifdef DEBUG_IIO_JPEG
  577. printf("in setQTables, qlen = %d, write is %d\n", qlen, write);
  578. #endif
  579. if (qlen > NUM_QUANT_TBLS) {
  580. /* Ignore extra qunterization tables. */
  581. qlen = NUM_QUANT_TBLS;
  582. }
  583. for (i = 0; i < qlen; i++) {
  584. table = (*env)->GetObjectArrayElement(env, qtables, i);
  585. qdata = (*env)->GetObjectField(env, table, JPEGQTable_tableID);
  586. qdataBody = (*env)->GetPrimitiveArrayCritical(env, qdata, NULL);
  587. if (cinfo->is_decompressor) {
  588. decomp = (j_decompress_ptr) cinfo;
  589. if (decomp->quant_tbl_ptrs[i] == NULL) {
  590. decomp->quant_tbl_ptrs[i] =
  591. jpeg_alloc_quant_table(cinfo);
  592. }
  593. quant_ptr = decomp->quant_tbl_ptrs[i];
  594. } else {
  595. comp = (j_compress_ptr) cinfo;
  596. if (comp->quant_tbl_ptrs[i] == NULL) {
  597. comp->quant_tbl_ptrs[i] =
  598. jpeg_alloc_quant_table(cinfo);
  599. }
  600. quant_ptr = comp->quant_tbl_ptrs[i];
  601. }
  602. for (j = 0; j < 64; j++) {
  603. quant_ptr->quantval[j] = (UINT16)qdataBody[j];
  604. }
  605. quant_ptr->sent_table = !write;
  606. (*env)->ReleasePrimitiveArrayCritical(env,
  607. qdata,
  608. qdataBody,
  609. 0);
  610. }
  611. return qlen;
  612. }
  613. static void setHuffTable(JNIEnv *env,
  614. JHUFF_TBL *huff_ptr,
  615. jobject table) {
  616. jshortArray huffLens;
  617. jshortArray huffValues;
  618. jshort *hlensBody, *hvalsBody;
  619. jsize hlensLen, hvalsLen;
  620. int i;
  621. // lengths
  622. huffLens = (*env)->GetObjectField(env,
  623. table,
  624. JPEGHuffmanTable_lengthsID);
  625. hlensLen = (*env)->GetArrayLength(env, huffLens);
  626. hlensBody = (*env)->GetShortArrayElements(env,
  627. huffLens,
  628. NULL);
  629. if (hlensLen > 16) {
  630. /* Ignore extra elements of bits array. Only 16 elements can be
  631. stored. 0-th element is not used. (see jpeglib.h, line 107) */
  632. hlensLen = 16;
  633. }
  634. for (i = 1; i <= hlensLen; i++) {
  635. huff_ptr->bits[i] = (UINT8)hlensBody[i-1];
  636. }
  637. (*env)->ReleaseShortArrayElements(env,
  638. huffLens,
  639. hlensBody,
  640. JNI_ABORT);
  641. // values
  642. huffValues = (*env)->GetObjectField(env,
  643. table,
  644. JPEGHuffmanTable_valuesID);
  645. hvalsLen = (*env)->GetArrayLength(env, huffValues);
  646. hvalsBody = (*env)->GetShortArrayElements(env,
  647. huffValues,
  648. NULL);
  649. if (hvalsLen > 256) {
  650. /* Ignore extra elements of hufval array. Only 256 elements
  651. can be stored. (see jpeglib.h, line 109) */
  652. hlensLen = 256;
  653. }
  654. for (i = 0; i < hvalsLen; i++) {
  655. huff_ptr->huffval[i] = (UINT8)hvalsBody[i];
  656. }
  657. (*env)->ReleaseShortArrayElements(env,
  658. huffValues,
  659. hvalsBody,
  660. JNI_ABORT);
  661. }
  662. static int setHTables(JNIEnv *env,
  663. j_common_ptr cinfo,
  664. jobjectArray DCHuffmanTables,
  665. jobjectArray ACHuffmanTables,
  666. boolean write) {
  667. int i;
  668. jobject table;
  669. JHUFF_TBL *huff_ptr;
  670. j_compress_ptr comp;
  671. j_decompress_ptr decomp;
  672. jsize hlen = (*env)->GetArrayLength(env, DCHuffmanTables);
  673. if (hlen > NUM_HUFF_TBLS) {
  674. /* Ignore extra DC huffman tables. */
  675. hlen = NUM_HUFF_TBLS;
  676. }
  677. for (i = 0; i < hlen; i++) {
  678. if (cinfo->is_decompressor) {
  679. decomp = (j_decompress_ptr) cinfo;
  680. if (decomp->dc_huff_tbl_ptrs[i] == NULL) {
  681. decomp->dc_huff_tbl_ptrs[i] =
  682. jpeg_alloc_huff_table(cinfo);
  683. }
  684. huff_ptr = decomp->dc_huff_tbl_ptrs[i];
  685. } else {
  686. comp = (j_compress_ptr) cinfo;
  687. if (comp->dc_huff_tbl_ptrs[i] == NULL) {
  688. comp->dc_huff_tbl_ptrs[i] =
  689. jpeg_alloc_huff_table(cinfo);
  690. }
  691. huff_ptr = comp->dc_huff_tbl_ptrs[i];
  692. }
  693. table = (*env)->GetObjectArrayElement(env, DCHuffmanTables, i);
  694. setHuffTable(env, huff_ptr, table);
  695. huff_ptr->sent_table = !write;
  696. }
  697. hlen = (*env)->GetArrayLength(env, ACHuffmanTables);
  698. if (hlen > NUM_HUFF_TBLS) {
  699. /* Ignore extra AC huffman tables. */
  700. hlen = NUM_HUFF_TBLS;
  701. }
  702. for (i = 0; i < hlen; i++) {
  703. if (cinfo->is_decompressor) {
  704. decomp = (j_decompress_ptr) cinfo;
  705. if (decomp->ac_huff_tbl_ptrs[i] == NULL) {
  706. decomp->ac_huff_tbl_ptrs[i] =
  707. jpeg_alloc_huff_table(cinfo);
  708. }
  709. huff_ptr = decomp->ac_huff_tbl_ptrs[i];
  710. } else {
  711. comp = (j_compress_ptr) cinfo;
  712. if (comp->ac_huff_tbl_ptrs[i] == NULL) {
  713. comp->ac_huff_tbl_ptrs[i] =
  714. jpeg_alloc_huff_table(cinfo);
  715. }
  716. huff_ptr = comp->ac_huff_tbl_ptrs[i];
  717. }
  718. table = (*env)->GetObjectArrayElement(env, ACHuffmanTables, i);
  719. setHuffTable(env, huff_ptr, table);
  720. huff_ptr->sent_table = !write;
  721. }
  722. return hlen;
  723. }
  724. /*************** end of shared utility code ****************/
  725. /********************** Reader Support **************************/
  726. /********************** Source Management ***********************/
  727. /*
  728. * INPUT HANDLING:
  729. *
  730. * The JPEG library's input management is defined by the jpeg_source_mgr
  731. * structure which contains two fields to convey the information in the
  732. * buffer and 5 methods which perform all buffer management. The library
  733. * defines a standard input manager that uses stdio for obtaining compressed
  734. * jpeg data, but here we need to use Java to get our data.
  735. *
  736. * We use the library jpeg_source_mgr but our own routines that access
  737. * imageio-specific information in the imageIOData structure.
  738. */
  739. /*
  740. * Initialize source. This is called by jpeg_read_header() before any
  741. * data is actually read. Unlike init_destination(), it may leave
  742. * bytes_in_buffer set to 0 (in which case a fill_input_buffer() call
  743. * will occur immediately).
  744. */
  745. GLOBAL(void)
  746. imageio_init_source(j_decompress_ptr cinfo)
  747. {
  748. struct jpeg_source_mgr *src = cinfo->src;
  749. src->next_input_byte = NULL;
  750. src->bytes_in_buffer = 0;
  751. }
  752. /*
  753. * This is called whenever bytes_in_buffer has reached zero and more
  754. * data is wanted. In typical applications, it should read fresh data
  755. * into the buffer (ignoring the current state of next_input_byte and
  756. * bytes_in_buffer), reset the pointer & count to the start of the
  757. * buffer, and return TRUE indicating that the buffer has been reloaded.
  758. * It is not necessary to fill the buffer entirely, only to obtain at
  759. * least one more byte. bytes_in_buffer MUST be set to a positive value
  760. * if TRUE is returned. A FALSE return should only be used when I/O
  761. * suspension is desired (this mode is discussed in the next section).
  762. */
  763. /*
  764. * Note that with I/O suspension turned on, this procedure should not
  765. * do any work since the JPEG library has a very simple backtracking
  766. * mechanism which relies on the fact that the buffer will be filled
  767. * only when it has backed out to the top application level. When
  768. * suspendable is turned on, imageio_fill_suspended_buffer will
  769. * do the actual work of filling the buffer.
  770. */
  771. GLOBAL(boolean)
  772. imageio_fill_input_buffer(j_decompress_ptr cinfo)
  773. {
  774. struct jpeg_source_mgr *src = cinfo->src;
  775. imageIODataPtr data = (imageIODataPtr) cinfo->client_data;
  776. streamBufferPtr sb = &data->streamBuf;
  777. JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
  778. int ret;
  779. /* This is where input suspends */
  780. if (sb->suspendable) {
  781. return FALSE;
  782. }
  783. #ifdef DEBUG_IIO_JPEG
  784. printf("Filling input buffer, remaining skip is %ld, ",
  785. sb->remaining_skip);
  786. printf("Buffer length is %d\n", sb->bufferLength);
  787. #endif
  788. /*
  789. * Definitively skips. Could be left over if we tried to skip
  790. * more than a buffer's worth but suspended when getting the next
  791. * buffer. Now we aren't suspended, so we can catch up.
  792. */
  793. if (sb->remaining_skip) {
  794. src->skip_input_data(cinfo, 0);
  795. }
  796. /*
  797. * Now fill a complete buffer, or as much of one as the stream
  798. * will give us if we are near the end.
  799. */
  800. RELEASE_ARRAYS(env, data, src->next_input_byte);
  801. ret = (*env)->CallIntMethod(env,
  802. sb->stream,
  803. ImageInputStream_readID,
  804. sb->hstreamBuffer, 0,
  805. sb->bufferLength);
  806. if ((*env)->ExceptionOccurred(env)
  807. || !GET_ARRAYS(env, data, &(src->next_input_byte))) {
  808. cinfo->err->error_exit((j_common_ptr) cinfo);
  809. }
  810. #ifdef DEBUG_IIO_JPEG
  811. printf("Buffer filled. ret = %d\n", ret);
  812. #endif
  813. /*
  814. * If we have reached the end of the stream, then the EOI marker
  815. * is missing. We accept such streams but generate a warning.
  816. * The image is likely to be corrupted, though everything through
  817. * the end of the last complete MCU should be usable.
  818. */
  819. if (ret <= 0) {
  820. jobject reader = data->imageIOobj;
  821. #ifdef DEBUG_IIO_JPEG
  822. printf("YO! Early EOI! ret = %d\n", ret);
  823. #endif
  824. RELEASE_ARRAYS(env, data, src->next_input_byte);
  825. (*env)->CallVoidMethod(env, reader,
  826. JPEGImageReader_warningOccurredID,
  827. READ_NO_EOI);
  828. if ((*env)->ExceptionOccurred(env)
  829. || !GET_ARRAYS(env, data, &(src->next_input_byte))) {
  830. cinfo->err->error_exit((j_common_ptr) cinfo);
  831. }
  832. sb->buf[0] = (JOCTET) 0xFF;
  833. sb->buf[1] = (JOCTET) JPEG_EOI;
  834. ret = 2;
  835. }
  836. src->next_input_byte = sb->buf;
  837. src->bytes_in_buffer = ret;
  838. return TRUE;
  839. }
  840. /*
  841. * With I/O suspension turned on, the JPEG library requires that all
  842. * buffer filling be done at the top application level, using this
  843. * function. Due to the way that backtracking works, this procedure
  844. * saves all of the data that was left in the buffer when suspension
  845. * occured and read new data only at the end.
  846. */
  847. GLOBAL(void)
  848. imageio_fill_suspended_buffer(j_decompress_ptr cinfo)
  849. {
  850. struct jpeg_source_mgr *src = cinfo->src;
  851. imageIODataPtr data = (imageIODataPtr) cinfo->client_data;
  852. streamBufferPtr sb = &data->streamBuf;
  853. JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
  854. jint ret;
  855. size_t offset, buflen;
  856. /*
  857. * The original (jpegdecoder.c) had code here that called
  858. * InputStream.available and just returned if the number of bytes
  859. * available was less than any remaining skip. Presumably this was
  860. * to avoid blocking, although the benefit was unclear, as no more
  861. * decompression can take place until more data is available, so
  862. * the code would block on input a little further along anyway.
  863. * ImageInputStreams don't have an available method, so we'll just
  864. * block in the skip if we have to.
  865. */
  866. if (sb->remaining_skip) {
  867. src->skip_input_data(cinfo, 0);
  868. }
  869. /* Save the data currently in the buffer */
  870. offset = src->bytes_in_buffer;
  871. if (src->next_input_byte > sb->buf) {
  872. memcpy(sb->buf, src->next_input_byte, offset);
  873. }
  874. RELEASE_ARRAYS(env, data, src->next_input_byte);
  875. buflen = sb->bufferLength - offset;
  876. if (buflen <= 0) {
  877. if (!GET_ARRAYS(env, data, &(src->next_input_byte))) {
  878. cinfo->err->error_exit((j_common_ptr) cinfo);
  879. }
  880. return;
  881. }
  882. ret = (*env)->CallIntMethod(env, sb->stream,
  883. ImageInputStream_readID,
  884. sb->hstreamBuffer,
  885. offset, buflen);
  886. if ((*env)->ExceptionOccurred(env)
  887. || !GET_ARRAYS(env, data, &(src->next_input_byte))) {
  888. cinfo->err->error_exit((j_common_ptr) cinfo);
  889. }
  890. /*
  891. * If we have reached the end of the stream, then the EOI marker
  892. * is missing. We accept such streams but generate a warning.
  893. * The image is likely to be corrupted, though everything through
  894. * the end of the last complete MCU should be usable.
  895. */
  896. if (ret <= 0) {
  897. jobject reader = data->imageIOobj;
  898. RELEASE_ARRAYS(env, data, src->next_input_byte);
  899. (*env)->CallVoidMethod(env, reader,
  900. JPEGImageReader_warningOccurredID,
  901. READ_NO_EOI);
  902. if ((*env)->ExceptionOccurred(env)
  903. || !GET_ARRAYS(env, data, &(src->next_input_byte))) {
  904. cinfo->err->error_exit((j_common_ptr) cinfo);
  905. }
  906. sb->buf[offset] = (JOCTET) 0xFF;
  907. sb->buf[offset + 1] = (JOCTET) JPEG_EOI;
  908. ret = 2;
  909. }
  910. src->next_input_byte = sb->buf;
  911. src->bytes_in_buffer = ret + offset;
  912. return;
  913. }
  914. /*
  915. * Skip num_bytes worth of data. The buffer pointer and count are
  916. * advanced over num_bytes input bytes, using the input stream
  917. * skipBytes method if the skip is greater than the number of bytes
  918. * in the buffer. This is used to skip over a potentially large amount of
  919. * uninteresting data (such as an APPn marker). bytes_in_buffer will be
  920. * zero on return if the skip is larger than the current contents of the
  921. * buffer.
  922. *
  923. * A negative skip count is treated as a no-op. A zero skip count
  924. * skips any remaining skip from a previous skip while suspended.
  925. *
  926. * Note that with I/O suspension turned on, this procedure does not
  927. * call skipBytes since the JPEG library has a very simple backtracking
  928. * mechanism which relies on the fact that the application level has
  929. * exclusive control over actual I/O.
  930. */
  931. GLOBAL(void)
  932. imageio_skip_input_data(j_decompress_ptr cinfo, long num_bytes)
  933. {
  934. struct jpeg_source_mgr *src = cinfo->src;
  935. imageIODataPtr data = (imageIODataPtr) cinfo->client_data;
  936. streamBufferPtr sb = &data->streamBuf;
  937. JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
  938. jlong ret;
  939. jobject reader;
  940. if (num_bytes < 0) {
  941. return;
  942. }
  943. num_bytes += sb->remaining_skip;
  944. sb->remaining_skip = 0;
  945. /* First the easy case where we are skipping <= the current contents. */
  946. ret = src->bytes_in_buffer;
  947. if (ret >= num_bytes) {
  948. src->next_input_byte += num_bytes;
  949. src->bytes_in_buffer -= num_bytes;
  950. return;
  951. }
  952. /*
  953. * We are skipping more than is in the buffer. We empty the buffer and,
  954. * if we aren't suspended, call the Java skipBytes method. We always
  955. * leave the buffer empty, to be filled by either fill method above.
  956. */
  957. src->bytes_in_buffer = 0;
  958. src->next_input_byte = sb->buf;
  959. num_bytes -= (long)ret;
  960. if (sb->suspendable) {
  961. sb->remaining_skip = num_bytes;
  962. return;
  963. }
  964. RELEASE_ARRAYS(env, data, src->next_input_byte);
  965. ret = (*env)->CallLongMethod(env,
  966. sb->stream,
  967. ImageInputStream_skipBytesID,
  968. (jlong) num_bytes);
  969. if ((*env)->ExceptionOccurred(env)
  970. || !GET_ARRAYS(env, data, &(src->next_input_byte))) {
  971. cinfo->err->error_exit((j_common_ptr) cinfo);
  972. }
  973. /*
  974. * If we have reached the end of the stream, then the EOI marker
  975. * is missing. We accept such streams but generate a warning.
  976. * The image is likely to be corrupted, though everything through
  977. * the end of the last complete MCU should be usable.
  978. */
  979. if (ret <= 0) {
  980. reader = data->imageIOobj;
  981. RELEASE_ARRAYS(env, data, src->next_input_byte);
  982. (*env)->CallVoidMethod(env,
  983. reader,
  984. JPEGImageReader_warningOccurredID,
  985. READ_NO_EOI);
  986. if ((*env)->ExceptionOccurred(env)
  987. || !GET_ARRAYS(env, data, &(src->next_input_byte))) {
  988. cinfo->err->error_exit((j_common_ptr) cinfo);
  989. }
  990. sb->buf[0] = (JOCTET) 0xFF;
  991. sb->buf[1] = (JOCTET) JPEG_EOI;
  992. src->bytes_in_buffer = 2;
  993. src->next_input_byte = sb->buf;
  994. }
  995. }
  996. /*
  997. * Terminate source --- called by jpeg_finish_decompress() after all
  998. * data for an image has been read. In our case pushes back any
  999. * remaining data, as it will be for another image and must be available
  1000. * for java to find out that there is another image. Also called if
  1001. * reseting state after reading a tables-only image.
  1002. */
  1003. GLOBAL(void)
  1004. imageio_term_source(j_decompress_ptr cinfo)
  1005. {
  1006. // To pushback, just seek back by src->bytes_in_buffer
  1007. struct jpeg_source_mgr *src = cinfo->src;
  1008. imageIODataPtr data = (imageIODataPtr) cinfo->client_data;
  1009. JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
  1010. jobject reader = data->imageIOobj;
  1011. if (src->bytes_in_buffer > 0) {
  1012. RELEASE_ARRAYS(env, data, src->next_input_byte);
  1013. (*env)->CallVoidMethod(env,
  1014. reader,
  1015. JPEGImageReader_pushBackID,
  1016. src->bytes_in_buffer);
  1017. if ((*env)->ExceptionOccurred(env)
  1018. || !GET_ARRAYS(env, data, &(src->next_input_byte))) {
  1019. cinfo->err->error_exit((j_common_ptr) cinfo);
  1020. }
  1021. src->bytes_in_buffer = 0;
  1022. //src->next_input_byte = sb->buf;
  1023. }
  1024. }
  1025. /********************* end of source manager ******************/
  1026. /********************* ICC profile support ********************/
  1027. /*
  1028. * The following routines are modified versions of the ICC
  1029. * profile support routines available from the IJG website.
  1030. * The originals were written by Todd Newman
  1031. * <tdn@eccentric.esd.sgi.com> and modified by Tom Lane for
  1032. * the IJG. They are further modified to fit in the context
  1033. * of the imageio JPEG plug-in.
  1034. */
  1035. /*
  1036. * Since an ICC profile can be larger than the maximum size of a JPEG marker
  1037. * (64K), we need provisions to split it into multiple markers. The format
  1038. * defined by the ICC specifies one or more APP2 markers containing the
  1039. * following data:
  1040. * Identifying string ASCII "ICC_PROFILE\0" (12 bytes)
  1041. * Marker sequence number 1 for first APP2, 2 for next, etc (1 byte)
  1042. * Number of markers Total number of APP2's used (1 byte)
  1043. * Profile data (remainder of APP2 data)
  1044. * Decoders should use the marker sequence numbers to reassemble the profile,
  1045. * rather than assuming that the APP2 markers appear in the correct sequence.
  1046. */
  1047. #define ICC_MARKER (JPEG_APP0 + 2) /* JPEG marker code for ICC */
  1048. #define ICC_OVERHEAD_LEN 14 /* size of non-profile data in APP2 */
  1049. #define MAX_BYTES_IN_MARKER 65533 /* maximum data len of a JPEG marker */
  1050. #define MAX_DATA_BYTES_IN_ICC_MARKER (MAX_BYTES_IN_MARKER - ICC_OVERHEAD_LEN)
  1051. /*
  1052. * Handy subroutine to test whether a saved marker is an ICC profile marker.
  1053. */
  1054. static boolean
  1055. marker_is_icc (jpeg_saved_marker_ptr marker)
  1056. {
  1057. return
  1058. marker->marker == ICC_MARKER &&
  1059. marker->data_length >= ICC_OVERHEAD_LEN &&
  1060. /* verify the identifying string */
  1061. GETJOCTET(marker->data[0]) == 0x49 &&
  1062. GETJOCTET(marker->data[1]) == 0x43 &&
  1063. GETJOCTET(marker->data[2]) == 0x43 &&
  1064. GETJOCTET(marker->data[3]) == 0x5F &&
  1065. GETJOCTET(marker->data[4]) == 0x50 &&
  1066. GETJOCTET(marker->data[5]) == 0x52 &&
  1067. GETJOCTET(marker->data[6]) == 0x4F &&
  1068. GETJOCTET(marker->data[7]) == 0x46 &&
  1069. GETJOCTET(marker->data[8]) == 0x49 &&
  1070. GETJOCTET(marker->data[9]) == 0x4C &&
  1071. GETJOCTET(marker->data[10]) == 0x45 &&
  1072. GETJOCTET(marker->data[11]) == 0x0;
  1073. }
  1074. /*
  1075. * See if there was an ICC profile in the JPEG file being read;
  1076. * if so, reassemble and return the profile data as a new Java byte array.
  1077. * If there was no ICC profile, return NULL.
  1078. *
  1079. * If the file contains invalid ICC APP2 markers, we throw an IIOException
  1080. * with an appropriate message.
  1081. */
  1082. jbyteArray
  1083. read_icc_profile (JNIEnv *env, j_decompress_ptr cinfo)
  1084. {
  1085. jpeg_saved_marker_ptr marker;
  1086. int num_markers = 0;
  1087. int num_found_markers = 0;
  1088. int seq_no;
  1089. JOCTET *icc_data;
  1090. JOCTET *dst_ptr;
  1091. unsigned int total_length;
  1092. #define MAX_SEQ_NO 255 // sufficient since marker numbers are bytes
  1093. jpeg_saved_marker_ptr icc_markers[MAX_SEQ_NO + 1];
  1094. int first; // index of the first marker in the icc_markers array
  1095. int last; // index of the last marker in the icc_markers array
  1096. jbyteArray data = NULL;
  1097. /* This first pass over the saved markers discovers whether there are
  1098. * any ICC markers and verifies the consistency of the marker numbering.
  1099. */
  1100. for (seq_no = 0; seq_no <= MAX_SEQ_NO; seq_no++)
  1101. icc_markers[seq_no] = NULL;
  1102. for (marker = cinfo->marker_list; marker != NULL; marker = marker->next) {
  1103. if (marker_is_icc(marker)) {
  1104. if (num_markers == 0)
  1105. num_markers = GETJOCTET(marker->data[13]);
  1106. else if (num_markers != GETJOCTET(marker->data[13])) {
  1107. JNU_ThrowByName(env, "javax/imageio/IIOException",
  1108. "Invalid icc profile: inconsistent num_markers fields");
  1109. return NULL;
  1110. }
  1111. seq_no = GETJOCTET(marker->data[12]);
  1112. /* Some third-party tools produce images with profile chunk
  1113. * numeration started from zero. It is inconsistent with ICC
  1114. * spec, but seems to be recognized by majority of image
  1115. * processing tools, so we should be more tolerant to this
  1116. * departure from the spec.
  1117. */
  1118. if (seq_no < 0 || seq_no > num_markers) {
  1119. JNU_ThrowByName(env, "javax/imageio/IIOException",
  1120. "Invalid icc profile: bad sequence number");
  1121. return NULL;
  1122. }
  1123. if (icc_markers[seq_no] != NULL) {
  1124. JNU_ThrowByName(env, "javax/imageio/IIOException",
  1125. "Invalid icc profile: duplicate sequence numbers");
  1126. return NULL;
  1127. }
  1128. icc_markers[seq_no] = marker;
  1129. num_found_markers ++;
  1130. }
  1131. }
  1132. if (num_markers == 0)
  1133. return NULL; // There is no profile
  1134. if (num_markers != num_found_markers) {
  1135. JNU_ThrowByName(env, "javax/imageio/IIOException",
  1136. "Invalid icc profile: invalid number of icc markers");
  1137. return NULL;
  1138. }
  1139. first = icc_markers[0] ? 0 : 1;
  1140. last = num_found_markers + first;
  1141. /* Check for missing markers, count total space needed.
  1142. */
  1143. total_length = 0;
  1144. for (seq_no = first; seq_no < last; seq_no++) {
  1145. unsigned int length;
  1146. if (icc_markers[seq_no] == NULL) {
  1147. JNU_ThrowByName(env, "javax/imageio/IIOException",
  1148. "Invalid icc profile: missing sequence number");
  1149. return NULL;
  1150. }
  1151. /* check the data length correctness */
  1152. length = icc_markers[seq_no]->data_length;
  1153. if (ICC_OVERHEAD_LEN > length || length > MAX_BYTES_IN_MARKER) {
  1154. JNU_ThrowByName(env, "javax/imageio/IIOException",
  1155. "Invalid icc profile: invalid data length");
  1156. return NULL;
  1157. }
  1158. total_length += (length - ICC_OVERHEAD_LEN);
  1159. }
  1160. if (total_length <= 0) {
  1161. JNU_ThrowByName(env, "javax/imageio/IIOException",
  1162. "Invalid icc profile: found only empty markers");
  1163. return NULL;
  1164. }
  1165. /* Allocate a Java byte array for assembled data */
  1166. data = (*env)->NewByteArray(env, total_length);
  1167. if (data == NULL) {
  1168. JNU_ThrowByName(env,
  1169. "java/lang/OutOfMemoryError",
  1170. "Reading ICC profile");
  1171. return NULL;
  1172. }
  1173. icc_data = (JOCTET *)(*env)->GetPrimitiveArrayCritical(env,
  1174. data,
  1175. NULL);
  1176. if (icc_data == NULL) {
  1177. JNU_ThrowByName(env, "javax/imageio/IIOException",
  1178. "Unable to pin icc profile data array");
  1179. return NULL;
  1180. }
  1181. /* and fill it in */
  1182. dst_ptr = icc_data;
  1183. for (seq_no = first; seq_no < last; seq_no++) {
  1184. JOCTET FAR *src_ptr = icc_markers[seq_no]->data + ICC_OVERHEAD_LEN;
  1185. unsigned int length =
  1186. icc_markers[seq_no]->data_length - ICC_OVERHEAD_LEN;
  1187. memcpy(dst_ptr, src_ptr, length);
  1188. dst_ptr += length;
  1189. }
  1190. /* finally, unpin the array */
  1191. (*env)->ReleasePrimitiveArrayCritical(env,
  1192. data,
  1193. icc_data,
  1194. 0);
  1195. return data;
  1196. }
  1197. /********************* end of ICC profile support *************/
  1198. /********************* Reader JNI calls ***********************/
  1199. JNIEXPORT void JNICALL
  1200. Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_initReaderIDs
  1201. (JNIEnv *env,
  1202. jclass cls,
  1203. jclass ImageInputStreamClass,
  1204. jclass qTableClass,
  1205. jclass huffClass) {
  1206. ImageInputStream_readID = (*env)->GetMethodID(env,
  1207. ImageInputStreamClass,
  1208. "read",
  1209. "([BII)I");
  1210. ImageInputStream_skipBytesID = (*env)->GetMethodID(env,
  1211. ImageInputStreamClass,
  1212. "skipBytes",
  1213. "(J)J");
  1214. JPEGImageReader_warningOccurredID = (*env)->GetMethodID(env,
  1215. cls,
  1216. "warningOccurred",
  1217. "(I)V");
  1218. JPEGImageReader_warningWithMessageID =
  1219. (*env)->GetMethodID(env,
  1220. cls,
  1221. "warningWithMessage",
  1222. "(Ljava/lang/String;)V");
  1223. JPEGImageReader_setImageDataID = (*env)->GetMethodID(env,
  1224. cls,
  1225. "setImageData",
  1226. "(IIIII[B)V");
  1227. JPEGImageReader_acceptPixelsID = (*env)->GetMethodID(env,
  1228. cls,
  1229. "acceptPixels",
  1230. "(IZ)V");
  1231. JPEGImageReader_passStartedID = (*env)->GetMethodID(env,
  1232. cls,
  1233. "passStarted",
  1234. "(I)V");
  1235. JPEGImageReader_passCompleteID = (*env)->GetMethodID(env,
  1236. cls,
  1237. "passComplete",
  1238. "()V");
  1239. JPEGImageReader_pushBackID = (*env)->GetMethodID(env,
  1240. cls,
  1241. "pushBack",