/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This file was based upon the example.c stub file included in the
* release 6 of the Independent JPEG Group's free JPEG software.
* It has been updated to conform to release 6b.
*/
/* First, if system header files define "boolean" map it to "system_boolean" */
#include <stdio.h>
#include <setjmp.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include "jni.h"
#include "jni_util.h"
/* undo "system_boolean" hack and undef FAR since we don't use it anyway */
#include <jpeglib.h>
#include "jerror.h"
/* The method IDs we cache. Note that the last two belongs to the
* java.io.InputStream class.
*/
/* Initialize the Java VM instance variable when the library is
first loaded */
{
return JNI_VERSION_1_2;
}
/*
* ERROR HANDLING:
*
* The JPEG library's standard error handler (jerror.c) is divided into
* several "methods" which you can override individually. This lets you
* adjust the behavior without duplicating a lot of code, which you might
* have to update with each future release.
*
* Our example here shows how to override the "error_exit" method so that
* control is returned to the library's caller when a fatal error occurs,
* rather than calling exit() as the standard error_exit method does.
*
* routine which calls the JPEG library must first execute a setjmp() call to
* establish the return point. We want the replacement error_exit to do a
* longjmp(). But we need to make the setjmp buffer accessible to the
* error_exit routine. To do this, we make a private extension of the
* standard JPEG error handler object. (If we were using C++, we'd say we
* were making a subclass of the regular error handler.)
*
* Here's the extended error handler struct:
*/
struct sun_jpeg_error_mgr {
};
/*
* Here's the routine that will replace the standard error_exit method:
*/
METHODDEF(void)
{
/* cinfo->err really points to a sun_jpeg_error_mgr struct */
/* Always display the message. */
/* We could postpone this until after returning, if we chose. */
/* (*cinfo->err->output_message) (cinfo); */
/* For Java, we will format the message and put it in the error we throw. */
/* Return control to the setjmp point */
}
/*
* Error Message handling
*
* This overrides the output_message method to send JPEG messages
*
*/
METHODDEF(void)
{
/* Create the message */
/* Send it to stderr, adding a newline */
}
/*
* INPUT HANDLING:
*
* The JPEG library's input management is defined by the jpeg_source_mgr
* structure which contains two fields to convey the information in the
* buffer and 5 methods which perform all buffer management. The library
* defines a standard input manager that uses stdio for obtaining compressed
* jpeg data, but here we need to use Java to get our data.
*
* We need to make the Java class information accessible to the source_mgr
* input routines. We also need to store a pointer to the start of the
* Java array being used as an input buffer so that it is not moved or
* garbage collected while the JPEG library is using it. To store these
* things, we make a private extension of the standard JPEG jpeg_source_mgr
* object.
*
* Here's the extended source manager struct:
*/
struct sun_jpeg_source_mgr {
int suspendable;
unsigned long remaining_skip;
/* More stuff */
union pixptr {
int *ip;
unsigned char *bp;
} outbuf;
};
/* We use Get/ReleasePrimitiveArrayCritical functions to avoid
* the need to copy buffer elements.
*
* MAKE SURE TO:
*
* - carefully insert pairs of RELEASE_ARRAYS and GET_ARRAYS around
* callbacks to Java.
* - call RELEASE_ARRAYS before returning to Java.
*
* Otherwise things will go horribly wrong. There may be memory leaks,
* excessive pinning, or even VM crashes!
*
* Note that GetPrimitiveArrayCritical may fail!
*/
{
} else {
}
}
}
}
{
if (src->hInputBuffer) {
return 0;
}
if ((int)(src->inbufoffset) >= 0) {
}
}
if (src->hOutputBuffer) {
return 0;
}
}
return 1;
}
/*
* Initialize source. This is called by jpeg_read_header() before any
* data is actually read. Unlike init_destination(), it may leave
* bytes_in_buffer set to 0 (in which case a fill_input_buffer() call
* will occur immediately).
*/
GLOBAL(void)
{
}
/*
* This is called whenever bytes_in_buffer has reached zero and more
* data is wanted. In typical applications, it should read fresh data
* into the buffer (ignoring the current state of next_input_byte and
* bytes_in_buffer), reset the pointer & count to the start of the
* buffer, and return TRUE indicating that the buffer has been reloaded.
* It is not necessary to fill the buffer entirely, only to obtain at
* least one more byte. bytes_in_buffer MUST be set to a positive value
* if TRUE is returned. A FALSE return should only be used when I/O
* suspension is desired (this mode is discussed in the next section).
*/
/*
* Note that with I/O suspension turned on, this procedure should not
* do any work since the JPEG library has a very simple backtracking
* mechanism which relies on the fact that the buffer will be filled
* only when it has backed out to the top application level. When
* suspendable is turned on, the sun_jpeg_fill_suspended_buffer will
* do the actual work of filling the buffer.
*/
{
if (src->suspendable) {
return FALSE;
}
if (src->remaining_skip) {
}
}
if (ret <= 0) {
/* Silently accept truncated JPEG files */
ret = 2;
}
return TRUE;
}
/*
* Note that with I/O suspension turned on, the JPEG library requires
* that all buffer filling be done at the top application level. Due
* to the way that backtracking works, this procedure should save all
* of the data that was left in the buffer when suspension occured and
* only read new data at the end.
*/
GLOBAL(void)
{
int ret;
}
return;
}
if (src->remaining_skip) {
}
/* Save the data currently in the buffer */
}
if (buflen <= 0) {
}
return;
}
}
if (ret <= 0) {
/* Silently accept truncated JPEG files */
ret = 2;
}
return;
}
/*
* Skip num_bytes worth of data. The buffer pointer and count should
* be advanced over num_bytes input bytes, refilling the buffer as
* needed. This is used to skip over a potentially large amount of
* uninteresting data (such as an APPn marker). In some applications
* it may be possible to optimize away the reading of the skipped data,
* but it's not clear that being smart is worth much trouble; large
* skips are uncommon. bytes_in_buffer may be zero on return.
* A zero or negative skip count should be treated as a no-op.
*/
/*
* Note that with I/O suspension turned on, this procedure should not
* do any I/O since the JPEG library has a very simple backtracking
* mechanism which relies on the fact that the buffer will be filled
* only when it has backed out to the top application level.
*/
GLOBAL(void)
{
int ret;
int buflen;
if (num_bytes < 0) {
return;
}
src->remaining_skip = 0;
ret = (int)src->pub.bytes_in_buffer; /* this conversion is safe, because capacity of the buffer is limited by jnit */
return;
}
if (src->suspendable) {
return;
}
/* Note that the signature for the method indicates that it takes
* and returns a long. Casting the int num_bytes to a long on
* the input should work well enough, and if we assume that the
* return value for this particular method should always be less
* than the argument value (or -1), then the return value coerced
* to an int should return us the information we need...
*/
while (num_bytes > 0) {
}
if (ret < 0) {
break;
}
}
}
if (num_bytes > 0) {
/* Silently accept truncated JPEG files */
} else {
}
}
/*
* Terminate source --- called by jpeg_finish_decompress() after all
* data has been read. Often a no-op.
*/
GLOBAL(void)
{
}
{
"(IIZZZ)Z");
"read", "([BII)I");
"available", "()I");
}
/*
* The Windows Itanium Aug 2002 SDK generates bad code
* for this routine. Disable optimization for now.
*/
#ifdef _M_IA64
#endif
{
/* This struct contains the JPEG decompression parameters and pointers to
* working space (which is allocated as needed by the JPEG library).
*/
/* We use our private extension JPEG error handler.
* Note that this struct must live as long as the main JPEG parameter
* struct, to avoid dangling-pointer problems.
*/
int ret;
unsigned char *bp;
int grayscale;
int hasalpha;
int buffered_mode;
int final_pass;
/* Step 0: verify the inputs. */
if (hInputBuffer == 0 || hInputStream == 0) {
return;
}
/* Step 1: allocate and initialize JPEG decompression object */
/* We set up the normal JPEG error routines, then override error_exit. */
/* We need to setup our own print routines */
/* Establish the setjmp return context for sun_jpeg_error_exit to use. */
/* If we get here, the JPEG code has signaled an error.
* We need to clean up the JPEG object, close the input file, and return.
*/
buffer);
}
return;
}
/* Now we can initialize the JPEG decompression object. */
/* Step 2: specify data source (eg, a file) */
jsrc.hOutputBuffer = 0;
jsrc.remaining_skip = 0;
return;
}
/* Step 3: read file parameters with jpeg_read_header() */
/* select buffered-image mode if it is a progressive JPEG only */
#ifdef YCCALPHA
#else
hasalpha = 0;
#endif
/* We can ignore the return value from jpeg_read_header since
* (a) suspension is not possible with the stdio data source, and
* (nor with the Java input source)
* (b) we passed TRUE to reject a tables-only JPEG file as an error.
* See libjpeg.doc for more info.
*/
/* No more interest in this image... */
return;
}
/* Make a one-row-high sample array with enough room to expand to ints */
if (grayscale) {
} else {
}
return;
}
/* Step 4: set parameters for decompression */
/* In this example, we don't need to change any of the defaults set by
* jpeg_read_header(), so we do nothing here.
*/
/* For the first pass for Java, we want to deal with RGB for simplicity */
/* Unfortunately, the JPEG code does not automatically convert Grayscale */
/* to RGB, so we have to deal with Grayscale explicitly. */
}
/* Step 5: Start decompressor */
/* We may need to do some setup of our own at this point before reading
* the data. After jpeg_start_decompress() we have the correct scaled
* output image dimensions available, as well as the output colormap
* if we asked for color quantization.
*/
/* Step 6: while (scan lines remain to be read) */
/* jpeg_read_scanlines(...); */
/* Here we use the library's state variable cinfo.output_scanline as the
* loop counter, so that we don't have to keep track ourselves.
*/
if (buffered_mode) {
final_pass = FALSE;
} else {
final_pass = TRUE;
}
do {
if (buffered_mode) {
do {
if (ret == JPEG_REACHED_EOI) {
final_pass = TRUE;
}
}
if (! final_pass) {
do {
if (ret == JPEG_REACHED_EOI) {
break;
}
}
if (grayscale) {
} else {
if (hasalpha) {
}
} else {
}
}
}
/* No more interest in this image... */
return;
}
}
if (buffered_mode) {
}
} while (! final_pass);
/* Step 7: Finish decompression */
(void) jpeg_finish_decompress(&cinfo);
/* We can ignore the return value since suspension is not possible
* with the stdio data source.
* (nor with the Java data source)
*/
/* Step 8: Release JPEG decompression object */
/* This is an important step since it will release a good deal of memory. */
/* After finish_decompress, we can close the input file.
* Here we postpone it until after no more JPEG errors are possible,
* so as to simplify the setjmp error logic above. (Actually, I don't
* think that jpeg_destroy can do an error exit, but why assume anything...)
*/
/* Not needed for Java - the Java code will close the file */
/* fclose(infile); */
/* At this point you may want to check to see whether any corrupt-data
* warnings occurred (test whether jerr.pub.num_warnings is nonzero).
*/
/* And we're done! */
return;
}
#ifdef _M_IA64
#endif
/*
* SOME FINE POINTS:
*
* In the above code, we ignored the return value of jpeg_read_scanlines,
* which is the number of scanlines actually read. We could get away with
* this because we asked for only one line at a time and we weren't using
* a suspending data source. See libjpeg.doc for more info.
*
* We cheated a bit by calling alloc_sarray() after jpeg_start_decompress();
* we should have done it beforehand to ensure that the space would be
* counted against the JPEG max_memory setting. In some systems the above
* code would risk an out-of-memory error. However, in general we don't
* know the output image dimensions before jpeg_start_decompress(), unless we
* call jpeg_calc_output_dimensions(). See libjpeg.doc for more about this.
*
* Scanlines are returned in the same order as they appear in the JPEG file,
* which is standardly top-to-bottom. If you must emit data bottom-to-top,
* you can use one of the virtual arrays provided by the JPEG memory manager
* to invert the data. See wrbmp.c for an example.
*
* As with compression, some operating modes may require temporary files.
* On some systems you may need to set up a signal handler to ensure that
* temporary files are deleted if the program is interrupted. See libjpeg.doc.
*/