예제 #1
0
DTerr ImporterImageJPG::import(const FilePath &pathname, const std::string &args, DTuint &width, DTuint &height, std::shared_ptr<DTubyte> &data, DT3GLTextelFormat &format)
{
    
	//
	// The following is based on the libpng manual. http://www.libpng.org/pub/png/libpng-1.2.5-manual.html#section-3.1
	//

	//
	// Check the file header
	//

	// open the file
	BinaryFileStream file;
	DTerr err;
	if ((err = FileManager::open(file, pathname, true)) != DT3_ERR_NONE)
		return err;

    // This struct contains the JPEG decompression parameters and pointers to
    // working space (which is allocated as needed by the JPEG library).
    jpeg_decompress_struct cinfo;
    ImportSource           csrc;

    // 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.
    ImportErr jerr;

    cinfo.err = jpeg_std_error(&jerr.pub);
    jerr.pub.error_exit = ImporterImageJPG::error_handler;
    
    // Establish the setjmp return context for my_error_exit to use.
    if (setjmp(jerr.setjmp_buffer)) {
        // 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.
        jpeg_destroy_decompress(&cinfo);
        file.close();
        return DT3_ERR_FILE_WRONG_TYPE;
    }

    //  Now we can initialize the JPEG decompression object.
    jpeg_create_decompress(&cinfo);
    cinfo.src = (jpeg_source_mgr*) &csrc;

    //  Step 2: specify data source (eg, a file)
    jpeg_stream_src(&cinfo, file);

    //  Step 3: read file parameters with jpeg_read_header()
    jpeg_read_header(&cinfo, TRUE);

    //  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.

    //  Step 5: Start decompressor
    jpeg_start_decompress(&cinfo);
    
    ASSERT(cinfo.out_color_components == 3 && cinfo.data_precision == 8);
    
    // Build a buffer for reading in the image
    width = cinfo.output_width;
    height = cinfo.output_height;
    format = DT3GL_FORMAT_RGB;
    
    // Change data format to 16 bit
    data = std::shared_ptr<DTubyte>(new DTubyte[width * height * 3]);
	DTubyte *buffer = data.get();
    
    DTint row_stride = cinfo.output_width * cinfo.output_components;
    
    // Make a one-row-high sample array that will go away when done with image
    JSAMPARRAY scanline_buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
    
    // Step 6: while (scan lines remain to be read)
    // 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.

    while (cinfo.output_scanline < cinfo.output_height) {
        //jpeg_read_scanlines expects an array of pointers to scanlines.
        // Here the array is only one element long, but you could ask for
        // more than one scanline at a time if that's more convenient.

        jpeg_read_scanlines(&cinfo, scanline_buffer, 1);
        
        // Copy Row into buffer
        DTubyte *src_data = (DTubyte*) scanline_buffer[0];
        DTubyte *dst_data = (DTubyte*) &buffer[width * (height - cinfo.output_scanline) * 3];
        
        // Copy row
        ::memcpy(dst_data, src_data, row_stride);
    }

    // Step 7: Finish decompression
    jpeg_finish_decompress(&cinfo);

    // Step 8: Release JPEG decompression object
    // This is an important step since it will release a good deal of memory.
    jpeg_destroy_decompress(&cinfo);
    
//#endif

	return DT3_ERR_NONE;
}
예제 #2
0
/******************************************************************************
 *
 * Function jpeg_to_ximage
 *
 * This routine converts compressed jpeg data associated with a _DtGrStream 
 * into an XImage.  
 *
 * No X color allocation is done.  The image is quantized down to MAX_COLORS 
 * during decompression, and an array of XColor structures with the red, 
 * green, and blue fields initialized to the colors used in the image is
 * returned to the caller.  Each pixel value in the XImage data is an index
 * into this array.  The caller must use this information to allocate X
 * color cells and substitute the appropriate pixel values into the XImage
 * data array before using the XImage.
 *
 * The routine makes use of a custom source data manager to allow the JPEG
 * data source to be a _DtGrStream, a custom data destination manager to 
 * allow the decompressed and post-processed data to be written to an XImage,
 * and a custom error handler to allow standard _DtGr error codes to be
 * returned to the caller in the event of a JPEG library error.
 *
 *****************************************************************************/
enum _DtGrLoadStatus jpeg_to_ximage (
    _DtGrStream           *stream,
    Screen                *screen,
    Visual                *visual,
    Dimension             *in_out_width,
    Dimension             *in_out_height,
    XImage                **ximage,
    XColor                **xcolors,
    int                    *ncolors,
    int                    *xres)
{
    struct jpeg_decompress_struct cinfo;
    struct my_error_mgr jerr;
    djpeg_dest_ptr dest_mgr = NULL;
    ximg_dest_ptr dest;
    int i, num_scanlines, nullCount, ximWidth;
    unsigned char *ximData = NULL;
    Display *display = DisplayOfScreen(screen);
    int nplanes = DisplayPlanes(display,XScreenNumberOfScreen(screen));
    XColor *colors = NULL;

    /*
    ** Initialize the return values 
    */
    *ximage = NULL;
    *xres = *ncolors = *in_out_width = *in_out_height = 0;

    /*
    ** Initialize the jpeg library error handler with our custom routines
    */

    cinfo.err = jpeg_std_error(&jerr.pub);
    jerr.pub.error_exit = my_error_exit;
    jerr.pub.output_message = my_output_message;

    /* 
    ** Establish the setjmp return context for my_error_exit to use
    */
    if (setjmp(jerr.setjmp_buffer)) 
    {
        /* If we get here, the JPEG code has signaled an error.  We need to
        ** free memory, clean up the JPEG object, and return a failure code.
        */
        if (*ximage != NULL)
            XDestroyImage (*ximage);
        if (colors != NULL)
            free (colors);
        jpeg_destroy_decompress(&cinfo);
        return (_DtGrCONVERT_FAILURE);
    }

    /*
    ** Create a jpeg decompression object
    */
    jpeg_create_decompress(&cinfo);

    /*
    ** Create a custom source data manager
    */
    jpeg_stream_src(&cinfo, stream);

    /*
    ** Read the jpeg header 
    */
    jpeg_read_header(&cinfo, TRUE);
    if (cinfo.X_density > 0 &&
	(cinfo.density_unit == 1 || cinfo.density_unit == 2)) {
	if (cinfo.density_unit == 1)
	    *xres = cinfo.X_density;
	else
	    *xres = cinfo.X_density * 2.54 + 0.5;
    }

    /*
    ** Initialize our desired post-processing attributes
    */
    cinfo.quantize_colors = TRUE;
    cinfo.desired_number_of_colors = MAX_COLORS;

    /*
    ** Create a custom data destination manager to allow our processed data
    ** to be channeled into an XImage.
    */
    dest_mgr = init_jpeg_dest_mgr(&cinfo);

    /*
    ** Initialize the decompression state
    */
    jpeg_start_decompress(&cinfo);
    (*dest_mgr->start_output) (&cinfo, dest_mgr);

    /*
    ** Create an XImage to hold the processed data
    */
        
    nullCount = (4 - (cinfo.output_width % 4)) & 0x03;
    ximWidth = cinfo.output_width + nullCount;

    if (nplanes > 8 )
        ximData = (unsigned char *) malloc(ximWidth * 
                                           cinfo.output_height * 4 );
    else
        ximData = (unsigned char *) malloc(ximWidth * cinfo.output_height );

    if (!ximData) 
    {
        jpeg_destroy_decompress(&cinfo);
        return (_DtGrNO_MEMORY);
    }

    *ximage = XCreateImage(display, visual, nplanes,
                           (nplanes == 1) ? XYPixmap : ZPixmap, 
                           0, (char *)ximData, cinfo.output_width, 
                           cinfo.output_height, 32, 0);

    if (!*ximage) 
    {
        free (ximData);
        jpeg_destroy_decompress(&cinfo);
        return (_DtGrCONVERT_FAILURE);
    }

    /*
    ** Store the XImage in the custom destination manager
    */
    dest = (ximg_dest_ptr) dest_mgr;
    dest->ximage = *ximage;

    /*
    ** Process scanlines until there are none left
    */

    while (cinfo.output_scanline < cinfo.output_height) 
    {
        num_scanlines = jpeg_read_scanlines(&cinfo, 
                                            (JSAMPARRAY)dest_mgr->buffer, 
                                            dest_mgr->buffer_height);
        (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
    }

    /*
    ** Return the colormap info as an array of XColors which can be
    ** used later for X color allocation purposes.
    */

    if (cinfo.actual_number_of_colors) 
    {
        colors = (XColor *) malloc((unsigned) sizeof(XColor) * 
                                   cinfo.actual_number_of_colors);
	if (!colors)
	{
            XDestroyImage (*ximage);
            jpeg_destroy_decompress(&cinfo);
	    return (_DtGrNO_MEMORY);
        }
        for (i=0; i<cinfo.actual_number_of_colors; i++)
	{
            if (cinfo.out_color_space == JCS_GRAYSCALE)
	    {
                colors[i].red = colors[i].green = colors[i].blue = 
                    INTERP_TO_XCOLORSPACE(cinfo.colormap[0][i]);
            }
            else /* JCS_RGB */
	    {
                colors[i].red   = INTERP_TO_XCOLORSPACE(cinfo.colormap[0][i]);
                colors[i].green = INTERP_TO_XCOLORSPACE(cinfo.colormap[1][i]);
                colors[i].blue  = INTERP_TO_XCOLORSPACE(cinfo.colormap[2][i]);
            }
        }

        *xcolors = colors;	      
        *ncolors = cinfo.actual_number_of_colors;
    }

    /*
    ** Set the other return parameters
    */
    *in_out_width = cinfo.output_width;
    *in_out_height = cinfo.output_height;
 
    /*
    ** Shut down the decompression engine and free the allocated memory
    */
    (*dest_mgr->finish_output) (&cinfo, dest_mgr);
    jpeg_finish_decompress(&cinfo);
    jpeg_destroy_decompress(&cinfo);

    /*
    ** Return success
    */
    return (_DtGrSUCCESS);
}
예제 #3
0
image_t* image_load_jpg(image_t* x, stream_t* stream)
{
  image_t* im;

  TRACE1 ("loading jpeg file");

  if (!stream) {
    im = NULL;
  } else {
    int load;
    im = image_instantiate_toplevel (x);

    struct jpeg_decompress_struct cinfo;
    myerror_mgr errmgr;

    errmgr.im = im;
    errmgr.image_is_owned_p = (im != x);

    if (setjmp (errmgr.env)) {
	    jpeg_destroy_decompress(&cinfo);

	// coming back from an error
	return NULL;
    }

    /* insert here useless error test */
    /* jpeg object initialisation */
    jpeg_create_decompress (&cinfo);

    /* specify data source */
    jpeg_stream_src (&cinfo, stream);

    /* standard error */
    cinfo.err               = jpeg_std_error (&errmgr.super);
    errmgr.super.error_exit = image_load_jpeg_error_exit;

    if (jpeg_read_header(&cinfo, TRUE) != JPEG_HEADER_OK) {
	    return NULL;
    }

    if (jpeg_start_decompress(&cinfo) < 0) {
	    return NULL;
    }

    if (!cinfo.output_width || !cinfo.output_height) {
	    WARNING1("null size image.");
	    return NULL;
    }

    image_new(im,
	      cinfo.output_width,
	      cinfo.output_height,
	      cinfo.output_width);

    switch (cinfo.output_components) {
    case 1: /* GRAY */
	load = 1;
	break;
    case 3: // RGB
	load = 1;
	break;
    default:
	/* don't know how to load that */
	image_destroy (im);
	if(im != x) {
		image_retire (im);
	}
	im = NULL;

	load = 0;
    }

    if (load) {
	JSAMPARRAY scanline_buf;

	scanline_buf = (*cinfo.mem->alloc_sarray)
		((j_common_ptr) &cinfo, JPOOL_IMAGE,
		 cinfo.output_width *
		 cinfo.output_components,
		 cinfo.rec_outbuf_height);

	while (cinfo.output_scanline < cinfo.output_height) {
	    int n;

	    uint32_t* dest = im->pixels + im->pitch * cinfo.output_scanline;

	    n = jpeg_read_scanlines(&cinfo,
				    scanline_buf,
				    cinfo.rec_outbuf_height);

	    int s;
	    for (s = 0; s < n; s++) {
		    unsigned char* scanline = scanline_buf [s];

		    /* copy to image */
		    int i;
		    for (i = 0; i < im->width; i++) {
			    if(cinfo.output_components == 1) {
				    dest[i] = 0xff000000 |
					    (scanline[i] << 16) |
					    (scanline[i] << 8) |
					    (scanline[i]);
			    } else if(cinfo.output_components == 3) {
#if (BYTE_ORDER == LITTLE_ENDIAN && defined (PIXEL_RGBA8888)) ||	\
	(BYTE_ORDER == BIG_ENDIAN && defined (PIXEL_BGRA8888))
				    dest[i] =
					    0xff000000 |
					    (scanline [3*i + 0] << 16) |
					    (scanline [3*i + 1] << 8) |
					    (scanline [3*i + 2] << 0);
#else
				    /*dest[i] = 0xff000000 | //alpha
					    (scanline [3*i + 2] << 0) |
					    (scanline [3*i + 1] << 8) |
					    (scanline [3*i + 2] << 16);
				    */
				    dest[i] = 0xff000000 | // alpha
					    (scanline [3 * i + 0] << 0) | // r
					    (scanline [3 * i + 1] << 8) | // g
					    (scanline [3 * i + 2] << 16); // b

#endif
			    }
		    }
		    dest += im->pitch;
	    }
	}
    }

    jpeg_finish_decompress(&cinfo);

  }

    return im;
}