res_gltex_cache_t * Res_CacheInGLTEX_jpg( res_gltex_register_t *reg )
{
	struct jpeg_decompress_struct cinfo;

	ib_file_t	*h;
	unsigned char *buffer;
	int row_stride;
	struct my_error_mgr jerr;
	FILE	*b;

	int	pixels;
	unsigned char	*image, *ptr;
	res_gltex_cache_t		*gltex;
	

	h = IB_Open( reg->path );
//	b = fopen( "test.jpg", "rb" );

	if( !h )
	{
		__error( "load of '%s' failed\n", reg->path );
	}

//	memset( &cinfo, 0, sizeof( struct jpeg_decompress_struct ));

	cinfo.err = jpeg_std_error(&jerr.pub);
	jerr.pub.error_exit = jpeg_error_exit;
	
	if (setjmp (jerr.setjmp_buffer))                                              
	{

		jpeg_destroy_decompress (&cinfo);
		if( h )
			IB_Close( h );
		__error( "XJT: JPEG load error\n");
	       
	}



	printf( "%p\n", cinfo.err );


	// step 1

	jpeg_create_decompress(&cinfo);	
//	cinfo.err = jpeg_std_error (&jerr.pub);                                       
//	printf( "%p\n", cinfo.err );

	// step 2
	jpeg_ibase_src(&cinfo, h);
//	jpeg_stdio_src( &cinfo, b );

//	printf( "back\n" );
	
	// step 3
	jpeg_read_header(&cinfo, TRUE);


/*
	if( cinfo.jpeg_color_space != JCS_RGB )
	{
		__error( "colorspace is not RGB\n" );
	}
*/


	jpeg_start_decompress( &cinfo );
//	printf( "jpeg: %d %d %d\n", cinfo.image_width, cinfo.image_height, cinfo.output_components );
	if( cinfo.output_components != 3 )
	{
		__error( "jpeg file '%s' is not RGB\n", reg->path );
	}

	pixels = cinfo.output_width * cinfo.output_height;
	image = MM_Malloc( pixels * 3 );
       


	row_stride = cinfo.output_width * 3;

	ptr = image + ( row_stride * (cinfo.output_height - 1) );

	buffer = alloca( row_stride );

//	printf( "row_stride: %d\n", row_stride );

       

	while( cinfo.output_scanline < cinfo.output_height )
	{
//		__named_message( "%d\n", cinfo.output_scanline );
		jpeg_read_scanlines( &cinfo, &buffer, 1 ); 
	
		memcpy( ptr, buffer, row_stride );
		
		ptr -= row_stride;

	}

//	memset( image, 0, pixels *3 );

	jpeg_finish_decompress( &cinfo );
	jpeg_destroy_decompress( &cinfo );
	IB_Close( h );

	gltex = NEWTYPE( res_gltex_cache_t );
	gltex->width = cinfo.output_width;
	gltex->height = cinfo.output_height;

	__message( "%s: %d %d\n", reg->path, gltex->width, gltex->height );

	gltex->comp = resGltexComponents_rgb;
	Res_CreateGLTEX_rgb( cinfo.output_width, cinfo.output_height, image );
//	__error( "good\n" );

	return gltex;
}
Beispiel #2
0
// createImageFromJpeg decompresses a JPEG image to the standard image format
// source: https://github.com/ileben/ShivaVG/blob/master/examples/test_image.c
VGImage createImageFromJpeg(const char *filename) {
	FILE *infile;
	struct jpeg_decompress_struct jdc;
	struct jpeg_error_mgr jerr;
	JSAMPARRAY buffer;
	unsigned int bstride;
	unsigned int bbpp;

	VGImage img;
	VGubyte *data;
	unsigned int width;
	unsigned int height;
	unsigned int dstride;
	unsigned int dbpp;

	VGubyte *brow;
	VGubyte *drow;
	unsigned int x;
	unsigned int lilEndianTest = 1;
	VGImageFormat rgbaFormat;

	// Check for endianness
	if (((unsigned char *)&lilEndianTest)[0] == 1)
		rgbaFormat = VG_sABGR_8888;
	else
		rgbaFormat = VG_sRGBA_8888;

	// Try to open image file
	infile = fopen(filename, "rb");
	if (infile == NULL) {
		printf("Failed opening '%s' for reading!\n", filename);
		return VG_INVALID_HANDLE;
	}
	// Setup default error handling
	jdc.err = jpeg_std_error(&jerr);
	jpeg_create_decompress(&jdc);

	// Set input file
	jpeg_stdio_src(&jdc, infile);

	// Read header and start
	jpeg_read_header(&jdc, TRUE);
	jpeg_start_decompress(&jdc);
	width = jdc.output_width;
	height = jdc.output_height;

	// Allocate buffer using jpeg allocator
	bbpp = jdc.output_components;
	bstride = width * bbpp;
	buffer = (*jdc.mem->alloc_sarray)
	    ((j_common_ptr) & jdc, JPOOL_IMAGE, bstride, 1);

	// Allocate image data buffer
	dbpp = 4;
	dstride = width * dbpp;
	data = (VGubyte *) malloc(dstride * height);

	// Iterate until all scanlines processed
	while (jdc.output_scanline < height) {

		// Read scanline into buffer
		jpeg_read_scanlines(&jdc, buffer, 1);
		drow = data + (height - jdc.output_scanline) * dstride;
		brow = buffer[0];
		// Expand to RGBA
		for (x = 0; x < width; ++x, drow += dbpp, brow += bbpp) {
			switch (bbpp) {
			case 4:
				drow[0] = brow[0];
				drow[1] = brow[1];
				drow[2] = brow[2];
				drow[3] = brow[3];
				break;
			case 3:
				drow[0] = brow[0];
				drow[1] = brow[1];
				drow[2] = brow[2];
				drow[3] = 255;
				break;
			}
		}
	}

	// Create VG image
	img = vgCreateImage(rgbaFormat, width, height, VG_IMAGE_QUALITY_BETTER);
	vgImageSubData(img, data, dstride, rgbaFormat, 0, 0, width, height);

	// Cleanup
	jpeg_destroy_decompress(&jdc);
	fclose(infile);
	free(data);

	return img;
}
Beispiel #3
0
void HILL_read_jpeg(
    HILL_input_stream i,
    struct HILL_image_data *img
)
{
    unsigned width, height;
    enum HILL_pixel_format fmt;
    unsigned y;
    size_t bytes_per_row=0;
    size_t bytes=0;
    
    struct jpeg_decompression_data jpeg;
    struct jpeg_error_mgr jerr;
    struct jpeg_source_mgr jsrc;
    jpeg.i=i;

    if(setjmp(jpeg.env))/*Could not read the image*/
    {
        jpeg_destroy_decompress(&jpeg.cinfo);
        return;
    }
    
    /*Set the jpeg structures*/
    jpeg_std_error(&jerr);
    jerr.error_exit=read_jpeg_error_exit;
    jpeg.cinfo.err=&jerr;
    jpeg.cinfo.client_data=&jpeg;
    jpeg_create_decompress(&jpeg.cinfo);
    
    jsrc.init_source=read_jpeg_init_source;
    jsrc.fill_input_buffer=read_jpeg_fill_input_buffer;
    jsrc.skip_input_data=read_jpeg_skip_input_data;
    jsrc.resync_to_restart=jpeg_resync_to_restart;
    jsrc.term_source=read_jpeg_term_source;
    jpeg.cinfo.src=&jsrc;
    /*Check the file header*/
    if(jpeg_read_header(&jpeg.cinfo, TRUE)!=JPEG_HEADER_OK)
    {
        img->err=HILL_IMAGE_NOT_SUPPORTED;/*Not a JPEG image*/
        longjmp(jpeg.env, 2);/*since we have this construct, why not use it?*/
    }
    
    img->err=HILL_IMAGE_CORRUPTED;/*Assume the image is corrupted until done*/
    
    /*Get the pixel format*/
    switch(jpeg.cinfo.jpeg_color_space)
    {
    case JCS_GRAYSCALE:
        jpeg.cinfo.out_color_space=JCS_GRAYSCALE;
        fmt=HILL_BW8;
        break;
    case JCS_EXT_RGBA:
        fmt=HILL_RGBA8;
        jpeg.cinfo.out_color_space=JCS_EXT_RGBA;
        break;
    case JCS_RGB:
        fmt=HILL_RGB8;
        jpeg.cinfo.out_color_space=JCS_RGB;
        break;
    default:
        /*probably YUV or CMYK, translate it please*/
        fmt=HILL_RGB8;
        jpeg.cinfo.out_color_space=JCS_RGB;
    }
    
    if(jpeg_start_decompress(&jpeg.cinfo)==0)
    {/*Image is corrupted*/
        longjmp(jpeg.env, 3);
    }
    width=jpeg.cinfo.output_width;
    height=jpeg.cinfo.output_height;
    /*=============
     *READ THE JPEG
     *=============*/
    bytes_per_row=(width*HILL_get_pixel_format_bits(fmt))/8;
    bytes=height*bytes_per_row;
    img->w=width;
    img->h=height;
    img->fmt=fmt;
    img->data=malloc(bytes);

    for(y=0; y < height; )
    {
        uint8_t *scanline=(uint8_t*)img->data+y*bytes_per_row;
        y+=jpeg_read_scanlines(&jpeg.cinfo, ((JSAMPARRAY)&(scanline)), 1);
    }
    jpeg_finish_decompress(&jpeg.cinfo);
    jpeg_destroy_decompress(&jpeg.cinfo);
    img->err=HILL_IMAGE_NO_ERROR;
}
Beispiel #4
0
static int read_image_jpeg(FILE *file, png24_image *image)
{
    int retval;
    unsigned int width,height,row_stride;
    unsigned int bpp;
    unsigned int x,y,i;
    struct jpeg_decompress_struct cinfo;
    struct jpeg_error_mgr jerr;
    cinfo.err = jpeg_std_error(&jerr);
    jpeg_create_decompress(&cinfo);

    // decompress
    jpeg_stdio_src(&cinfo,file);
    retval=jpeg_read_header(&cinfo,TRUE);
    if(retval != 1)
    {
        return 1;
    }
    jpeg_start_decompress(&cinfo);

    width=cinfo.output_width;
    height=cinfo.output_height;
    bpp=cinfo.output_components;
    row_stride=width*bpp;

    // grayscale images not handled currently
    if (bpp == 1) {
        fprintf(stderr, "Error: grayscale JPEG images not handled currently.");
        return 1;
    }

    // allocate buffer size (always use RGBA)
    unsigned char* buffer = calloc(width*height*bpp,1);

    while(cinfo.output_scanline < height)
    {
        unsigned char *buffer_array[1];
        buffer_array[0] = buffer + cinfo.output_scanline*row_stride;
        jpeg_read_scanlines(&cinfo,buffer_array,1);
    }

    //convert to RGBA
    image->rgba_data = calloc(width*height*4,1);
    image->row_pointers = calloc(height,sizeof(unsigned char*));

    for(y=0; y<height; y++)
    {
        for(x=0; x<width; x++)
        {
            for(i=0; i<bpp; i++)
            {
                image->rgba_data[(y*width*4)+(x*4)+i] = buffer[(y*width*bpp)+(x*bpp)+i];
            }
            // default alpha 255
            image->rgba_data[(y*width*4) + (x*4) + 3] = 0xFF;
        }
        image->row_pointers[y] = &image->rgba_data[y*width*4];
    }
    image->width=width;
    image->height=height;
    jpeg_destroy_decompress(&cinfo);
    free(buffer);
    return 0;
}
Beispiel #5
0
bool loadJPEGScaled(QImage& image, const QString& path, int maximumSize)
{
    FileReadLocker lock(path);

    if (!isJpegImage(path))
    {
        return false;
    }

    FILE* const inputFile = fopen(QFile::encodeName(path).constData(), "rb");

    if (!inputFile)
    {
        return false;
    }

    struct jpeg_decompress_struct   cinfo;

    struct jpegutils_jpeg_error_mgr jerr;

    // JPEG error handling - thanks to Marcus Meissner
    cinfo.err                 = jpeg_std_error(&jerr);
    cinfo.err->error_exit     = jpegutils_jpeg_error_exit;
    cinfo.err->emit_message   = jpegutils_jpeg_emit_message;
    cinfo.err->output_message = jpegutils_jpeg_output_message;

    if (setjmp(jerr.setjmp_buffer))
    {
        jpeg_destroy_decompress(&cinfo);
        fclose(inputFile);
        return false;
    }

    jpeg_create_decompress(&cinfo);

#ifdef Q_OS_WIN

    QFile inFile(path);
    QByteArray buffer;

    if (inFile.open(QIODevice::ReadOnly))
    {
        buffer = inFile.readAll();
        inFile.close();
    }

    jpeg_memory_src(&cinfo, (JOCTET*)buffer.data(), buffer.size());

#else  // Q_OS_WIN

    jpeg_stdio_src(&cinfo, inputFile);

#endif // Q_OS_WIN

    jpeg_read_header(&cinfo, true);

    int imgSize = qMax(cinfo.image_width, cinfo.image_height);

    // libjpeg supports 1/1, 1/2, 1/4, 1/8
    int scale=1;

    while(maximumSize*scale*2 <= imgSize)
    {
        scale *= 2;
    }

    if (scale > 8)
    {
        scale = 8;
    }

    //cinfo.scale_num = 1;
    //cinfo.scale_denom = scale;
    cinfo.scale_denom *= scale;

    switch (cinfo.jpeg_color_space)
    {
        case JCS_UNKNOWN:
            break;
        case JCS_GRAYSCALE:
        case JCS_RGB:
        case JCS_YCbCr:
            cinfo.out_color_space = JCS_RGB;
            break;
        case JCS_CMYK:
        case JCS_YCCK:
            cinfo.out_color_space = JCS_CMYK;
            break;
        default:
            break;
    }

    jpeg_start_decompress(&cinfo);

    QImage img;

    // We only take RGB with 1 or 3 components, or CMYK with 4 components
    if (!(
            (cinfo.out_color_space == JCS_RGB  && (cinfo.output_components == 3 || cinfo.output_components == 1)) ||
            (cinfo.out_color_space == JCS_CMYK &&  cinfo.output_components == 4)
        ))
    {
        jpeg_destroy_decompress(&cinfo);
        fclose(inputFile);
        return false;
    }

    switch (cinfo.output_components)
    {
        case 3:
        case 4:
            img = QImage(cinfo.output_width, cinfo.output_height, QImage::Format_RGB32);
            break;
        case 1: // B&W image
            img = QImage(cinfo.output_width, cinfo.output_height, QImage::Format_Indexed8);
            img.setColorCount(256);

            for (int i = 0 ; i < 256 ; ++i)
            {
                img.setColor(i, qRgb(i, i, i));
            }

            break;
    }

    uchar* const data = img.bits();
    int bpl           = img.bytesPerLine();

    while (cinfo.output_scanline < cinfo.output_height)
    {
        uchar* d = data + cinfo.output_scanline * bpl;
        jpeg_read_scanlines(&cinfo, &d, 1);
    }

    jpeg_finish_decompress(&cinfo);

    if (cinfo.output_components == 3)
    {
        // Expand 24->32 bpp.
        for (uint j=0; j<cinfo.output_height; ++j)
        {
            uchar* in       = img.scanLine(j) + cinfo.output_width * 3;
            QRgb* const out = reinterpret_cast<QRgb*>(img.scanLine(j));

            for (uint i = cinfo.output_width; --i; )
            {
                in     -= 3;
                out[i] = qRgb(in[0], in[1], in[2]);
            }
        }
    }
    else if (cinfo.out_color_space == JCS_CMYK)
    {
        for (uint j = 0; j < cinfo.output_height; ++j)
        {
            uchar* in       = img.scanLine(j) + cinfo.output_width * 4;
            QRgb* const out = reinterpret_cast<QRgb*>(img.scanLine(j));

            for (uint i = cinfo.output_width; --i; )
            {
                in     -= 4;
                int k  = in[3];
                out[i] = qRgb(k * in[0] / 255, k * in[1] / 255, k * in[2] / 255);
            }
        }
    }

    if (cinfo.density_unit == 1)
    {
        img.setDotsPerMeterX(int(100. * cinfo.X_density / 2.54));
        img.setDotsPerMeterY(int(100. * cinfo.Y_density / 2.54));
    }
    else if (cinfo.density_unit == 2)
    {
        img.setDotsPerMeterX(int(100. * cinfo.X_density));
        img.setDotsPerMeterY(int(100. * cinfo.Y_density));
    }

    //int newMax = qMax(cinfo.output_width, cinfo.output_height);
    //int newx = maximumSize*cinfo.output_width / newMax;
    //int newy = maximumSize*cinfo.output_height / newMax;

    jpeg_destroy_decompress(&cinfo);
    fclose(inputFile);

    image = img;

    return true;
}
UInt64 JPGImageFileType::restoreData(      ImagePtr &OSG_JPG_ARG(image  ), 
                                     const UChar8   *OSG_JPG_ARG(buffer ),
                                           Int32     OSG_JPG_ARG(memSize))
{
#ifdef OSG_WITH_JPG
    UInt64    retCode = 0;
    struct local_error_mgr
    {
        struct jpeg_error_mgr   pub;
        jmp_buf                 setjmp_buffer;
    };

    unsigned char                   *destData;
    Image::PixelFormat              pixelFormat = osg::Image::OSG_INVALID_PF;

    unsigned long                    imageSize;
    typedef struct local_error_mgr  *local_error_ptr;
    struct local_error_mgr          jerr;
    struct jpeg_decompress_struct   cinfo;
    JSAMPARRAY                      imagebuffer;

    int                             row_stride;

    cinfo.err = jpeg_std_error(&jerr.pub);
    if(setjmp(jerr.setjmp_buffer))
    {
        jpeg_destroy_decompress(&cinfo);
        return 0;
    }

    jpeg_create_decompress(&cinfo);
    jpeg_memory_src(&cinfo, buffer, memSize);
    jpeg_read_header(&cinfo, TRUE);
    jpeg_start_decompress(&cinfo);

    switch(cinfo.output_components)
    {
    case 1:
        pixelFormat = Image::OSG_L_PF;
        break;
    case 2:
        pixelFormat = Image::OSG_LA_PF;
        break;
    case 3:
        pixelFormat = Image::OSG_RGB_PF;
        break;
    case 4:
        pixelFormat = Image::OSG_RGBA_PF;
        break;
    };

    if(image->set(pixelFormat, cinfo.output_width, cinfo.output_height))
    {
        imageSize = image->getSize();
        destData = image->editData() + imageSize;
        row_stride = cinfo.output_width * cinfo.output_components;
        imagebuffer = (*cinfo.mem->alloc_sarray) (reinterpret_cast<j_common_ptr>(&cinfo), JPOOL_IMAGE, row_stride, 1);
        while(cinfo.output_scanline < cinfo.output_height)
        {
            destData -= row_stride;
            jpeg_read_scanlines(&cinfo, imagebuffer, 1);
            memcpy(destData, *imagebuffer, row_stride);
        }

        retCode = imageSize;
    }
    else
        retCode = 0;

    jpeg_finish_decompress(&cinfo);
    jpeg_destroy_decompress(&cinfo);

    return retCode;

#else
    SWARNING <<
        getMimeType() <<
        " read is not compiled into the current binary " <<
        std::endl;
    return 0;
#endif
}
Beispiel #7
0
static Status jpg_decode_impl(rpU8 data, size_t size, jpeg_decompress_struct* cinfo, Tex* t)
{
	src_prepare(cinfo, data, size);

	// ignore return value since:
	// - suspension is not possible with the mem data source
	// - we passed TRUE to raise an error if table-only JPEG file
	(void)jpeg_read_header(cinfo, TRUE);

	// set libjpg output format. we cannot go with the default because
	// Photoshop writes non-standard CMYK files that must be converted to RGB.
	size_t flags = 0;
	cinfo->out_color_space = JCS_RGB;
	if(cinfo->num_components == 1)
	{
		flags |= TEX_GREY;
		cinfo->out_color_space = JCS_GRAYSCALE;
	}

	// lower quality, but faster
	cinfo->dct_method = JDCT_IFAST;
	cinfo->do_fancy_upsampling = FALSE;

	// ignore return value since suspension is not possible with the
	// mem data source.
	// note: since we've set out_color_space, JPEG will always
	// return an acceptable image format; no need to check.
	(void)jpeg_start_decompress(cinfo);

	// scaled output image dimensions and final bpp are now available.
	int w = cinfo->output_width;
	int h = cinfo->output_height;
	int bpp = cinfo->output_components * 8;

	// alloc destination buffer
	const size_t pitch = w * bpp / 8;
	const size_t imgSize = pitch * h;	// for allow_rows
	shared_ptr<u8> img;
	AllocateAligned(img, imgSize, pageSize);

	// read rows
	std::vector<RowPtr> rows = tex_codec_alloc_rows(img.get(), h, pitch, TEX_TOP_DOWN, 0);
	// could use cinfo->output_scanline to keep track of progress,
	// but we need to count lines_left anyway (paranoia).
	JSAMPARRAY row = (JSAMPARRAY)&rows[0];
	JDIMENSION lines_left = h;
	while(lines_left != 0)
	{
		JDIMENSION lines_read = jpeg_read_scanlines(cinfo, row, lines_left);
		row += lines_read;
		lines_left -= lines_read;

		// we've decoded in-place; no need to further process
	}

	// ignore return value since suspension is not possible with the
	// mem data source.
	(void)jpeg_finish_decompress(cinfo);

	Status ret = INFO::OK;
	if(cinfo->err->num_warnings != 0)
		ret = WARN::TEX_INVALID_DATA;

	// store image info and validate
	return ret | t->wrap(w,h,bpp,flags,img,0);
}
Beispiel #8
0
gint32
load_image (const gchar  *filename,
            GimpRunMode   runmode,
            gboolean      preview,
            GError      **error)
{
  gint32 volatile  image_ID;
  gint32           layer_ID;
  struct jpeg_decompress_struct cinfo;
  struct my_error_mgr           jerr;
  jpeg_saved_marker_ptr         marker;
  FILE            *infile;
  guchar          *buf;
  guchar         **rowbuf;
  GimpImageBaseType image_type;
  GimpImageType    layer_type;
  GeglBuffer      *buffer = NULL;
  const Babl      *format;
  gint             tile_height;
  gint             scanlines;
  gint             i, start, end;
#ifdef HAVE_LIBEXIF
  gint             orientation = 0;
#endif
#ifdef HAVE_LCMS
  cmsHTRANSFORM    cmyk_transform = NULL;
#else
  gpointer         cmyk_transform = NULL;
#endif

  /* We set up the normal JPEG error routines. */
  cinfo.err = jpeg_std_error (&jerr.pub);
  jerr.pub.error_exit = my_error_exit;

  if (!preview)
    {
      jerr.pub.output_message = my_output_message;
    }

  if ((infile = g_fopen (filename, "rb")) == NULL)
    {
      g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
                   _("Could not open '%s' for reading: %s"),
                   gimp_filename_to_utf8 (filename), g_strerror (errno));
      return -1;
    }

  if (!preview)
    gimp_progress_init_printf (_("Opening '%s'"),
                               gimp_filename_to_utf8 (filename));

  image_ID = -1;

  /* 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);
      if (infile)
        fclose (infile);

      if (image_ID != -1 && !preview)
        gimp_image_delete (image_ID);

      if (preview)
        destroy_preview ();

      if (buffer)
        g_object_unref (buffer);

      return -1;
    }

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

  /* Step 2: specify data source (eg, a file) */

  jpeg_stdio_src (&cinfo, infile);

  if (! preview)
    {
      /* - step 2.1: tell the lib to save the comments */
      jpeg_save_markers (&cinfo, JPEG_COM, 0xffff);

      /* - step 2.2: tell the lib to save APP1 data (EXIF or XMP) */
      jpeg_save_markers (&cinfo, JPEG_APP0 + 1, 0xffff);

      /* - step 2.3: tell the lib to save APP2 data (ICC profiles) */
      jpeg_save_markers (&cinfo, JPEG_APP0 + 2, 0xffff);
    }

  /* Step 3: read file parameters with jpeg_read_header() */

  jpeg_read_header (&cinfo, TRUE);

  /* We can ignore the return value from jpeg_read_header since
   *   (a) suspension is not possible with the stdio data source, and
   *   (b) we passed TRUE to reject a tables-only JPEG file as an error.
   * See libjpeg.doc for more info.
   */

  /* 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);

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

  /* temporary buffer */
  tile_height = gimp_tile_height ();
  buf = g_new (guchar,
               tile_height * cinfo.output_width * cinfo.output_components);

  rowbuf = g_new (guchar *, tile_height);

  for (i = 0; i < tile_height; i++)
    rowbuf[i] = buf + cinfo.output_width * cinfo.output_components * i;

  switch (cinfo.output_components)
    {
    case 1:
      image_type = GIMP_GRAY;
      layer_type = GIMP_GRAY_IMAGE;
      break;

    case 3:
      image_type = GIMP_RGB;
      layer_type = GIMP_RGB_IMAGE;
      break;

    case 4:
      if (cinfo.out_color_space == JCS_CMYK)
        {
          image_type = GIMP_RGB;
          layer_type = GIMP_RGB_IMAGE;
          break;
        }
      /*fallthrough*/

    default:
      g_message ("Don't know how to load JPEG images "
                 "with %d color channels, using colorspace %d (%d).",
                 cinfo.output_components, cinfo.out_color_space,
                 cinfo.jpeg_color_space);
      return -1;
      break;
    }

  if (preview)
    {
      image_ID = preview_image_ID;
    }
  else
    {
      image_ID = gimp_image_new_with_precision
        (cinfo.output_width, cinfo.output_height,
         image_type, GIMP_PRECISION_U8);

      gimp_image_undo_disable (image_ID);
      gimp_image_set_filename (image_ID, filename);
    }

  if (preview)
    {
      preview_layer_ID = gimp_layer_new (preview_image_ID, _("JPEG preview"),
                                         cinfo.output_width,
                                         cinfo.output_height,
                                         layer_type, 100, GIMP_NORMAL_MODE);
      layer_ID = preview_layer_ID;
    }
  else
    {
      layer_ID = gimp_layer_new (image_ID, _("Background"),
                                 cinfo.output_width,
                                 cinfo.output_height,
                                 layer_type, 100, GIMP_NORMAL_MODE);
    }

  if (! preview)
    {
      GString  *comment_buffer = NULL;
      guint8   *profile        = NULL;
      guint     profile_size   = 0;
#ifdef HAVE_LIBEXIF
      ExifData *exif_data      = NULL;
#endif

      /* Step 5.0: save the original JPEG settings in a parasite */
      jpeg_detect_original_settings (&cinfo, image_ID);

      /* Step 5.1: check for comments, or EXIF metadata in APP1 markers */
      for (marker = cinfo.marker_list; marker; marker = marker->next)
        {
          const gchar *data = (const gchar *) marker->data;
          gsize        len  = marker->data_length;

          if (marker->marker == JPEG_COM)
            {
#ifdef GIMP_UNSTABLE
              g_print ("jpeg-load: found image comment (%d bytes)\n",
                       marker->data_length);
#endif

              if (! comment_buffer)
                {
                  comment_buffer = g_string_new_len (data, len);
                }
              else
                {
                  /* concatenate multiple comments, separate them with LF */
                  g_string_append_c (comment_buffer, '\n');
                  g_string_append_len (comment_buffer, data, len);
                }
            }
          else if ((marker->marker == JPEG_APP0 + 1)
                   && (len > sizeof (JPEG_APP_HEADER_EXIF) + 8)
                   && ! strcmp (JPEG_APP_HEADER_EXIF, data))
            {
#ifdef GIMP_UNSTABLE
              g_print ("jpeg-load: found EXIF block (%d bytes)\n",
                       (gint) (len - sizeof (JPEG_APP_HEADER_EXIF)));
#endif
#ifdef HAVE_LIBEXIF
              if (! exif_data)
                exif_data = exif_data_new ();
              /* if there are multiple blocks, their data will be merged */
              exif_data_load_data (exif_data, (unsigned char *) data, len);
#endif
            }
        }

#ifdef HAVE_LIBEXIF
      if (!jpeg_load_exif_resolution (image_ID, exif_data))
#endif
        jpeg_load_resolution (image_ID, &cinfo);

      /* if we found any comments, then make a parasite for them */
      if (comment_buffer && comment_buffer->len)
        {
          GimpParasite *parasite;

          jpeg_load_sanitize_comment (comment_buffer->str);
          parasite = gimp_parasite_new ("gimp-comment",
                                        GIMP_PARASITE_PERSISTENT,
                                        strlen (comment_buffer->str) + 1,
                                        comment_buffer->str);
          gimp_image_attach_parasite (image_ID, parasite);
          gimp_parasite_free (parasite);

          g_string_free (comment_buffer, TRUE);
        }

#ifdef HAVE_LIBEXIF
      /* if we found any EXIF block, then attach the metadata to the image */
      if (exif_data)
        {
          gimp_metadata_store_exif (image_ID, exif_data);
          orientation = jpeg_exif_get_orientation (exif_data);
          exif_data_unref (exif_data);
          exif_data = NULL;
        }
#endif

      /* Step 5.2: check for XMP metadata in APP1 markers (after EXIF) */
      for (marker = cinfo.marker_list; marker; marker = marker->next)
        {
          const gchar *data = (const gchar *) marker->data;
          gsize        len  = marker->data_length;

          if ((marker->marker == JPEG_APP0 + 1)
              && (len > sizeof (JPEG_APP_HEADER_XMP) + 20)
              && ! strcmp (JPEG_APP_HEADER_XMP, data))
            {
              GimpParam *return_vals;
              gint       nreturn_vals;
              gchar     *xmp_packet;

#ifdef GIMP_UNSTABLE
              g_print ("jpeg-load: found XMP packet (%d bytes)\n",
                       (gint) (len - sizeof (JPEG_APP_HEADER_XMP)));
#endif
              xmp_packet = g_strndup (data + sizeof (JPEG_APP_HEADER_XMP),
                                      len - sizeof (JPEG_APP_HEADER_XMP));

              /* FIXME: running this through the PDB is not very efficient */
              return_vals = gimp_run_procedure ("plug-in-metadata-decode-xmp",
                                                &nreturn_vals,
                                                GIMP_PDB_IMAGE, image_ID,
                                                GIMP_PDB_STRING, xmp_packet,
                                                GIMP_PDB_END);

              if (return_vals[0].data.d_status != GIMP_PDB_SUCCESS)
                {
                  g_warning ("JPEG - unable to decode XMP metadata packet");
                }

              gimp_destroy_params (return_vals, nreturn_vals);
              g_free (xmp_packet);
            }
        }

      /* Step 5.3: check for an embedded ICC profile in APP2 markers */
      jpeg_icc_read_profile (&cinfo, &profile, &profile_size);

      if (cinfo.out_color_space == JCS_CMYK)
        {
          cmyk_transform = jpeg_load_cmyk_transform (profile, profile_size);
        }
      else if (profile) /* don't attach the profile if we are transforming */
        {
          GimpParasite *parasite;

          parasite = gimp_parasite_new ("icc-profile",
                                        GIMP_PARASITE_PERSISTENT |
                                        GIMP_PARASITE_UNDOABLE,
                                        profile_size, profile);
          gimp_image_attach_parasite (image_ID, parasite);
          gimp_parasite_free (parasite);
        }

      g_free (profile);

      /* Do not attach the "jpeg-save-options" parasite to the image
       * because this conflicts with the global defaults (bug #75398).
       */
    }

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

  buffer = gimp_drawable_get_buffer (layer_ID);
  format = babl_format (image_type == GIMP_RGB ? "R'G'B' u8" : "Y' u8");

  while (cinfo.output_scanline < cinfo.output_height)
    {
      start = cinfo.output_scanline;
      end   = cinfo.output_scanline + tile_height;
      end   = MIN (end, cinfo.output_height);

      scanlines = end - start;

      for (i = 0; i < scanlines; i++)
        jpeg_read_scanlines (&cinfo, (JSAMPARRAY) &rowbuf[i], 1);

      if (cinfo.out_color_space == JCS_CMYK)
        jpeg_load_cmyk_to_rgb (buf, cinfo.output_width * scanlines,
                               cmyk_transform);

      gegl_buffer_set (buffer,
                       GEGL_RECTANGLE (0, start, cinfo.output_width, scanlines),
                       0,
                       format,
                       buf,
                       GEGL_AUTO_ROWSTRIDE);

      if (! preview && (cinfo.output_scanline % 32) == 0)
        gimp_progress_update ((gdouble) cinfo.output_scanline /
                              (gdouble) cinfo.output_height);
    }

  /* Step 7: Finish decompression */

  jpeg_finish_decompress (&cinfo);
  /* We can ignore the return value since suspension is not possible
   * with the stdio data source.
   */

#ifdef HAVE_LCMS
  if (cmyk_transform)
    cmsDeleteTransform (cmyk_transform);
#endif

  /* Step 8: Release JPEG decompression object */

  /* This is an important step since it will release a good deal of memory. */
  jpeg_destroy_decompress (&cinfo);

  g_object_unref (buffer);

  /* free up the temporary buffers */
  g_free (rowbuf);
  g_free (buf);

  /* 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...)
   */
  fclose (infile);

  /* At this point you may want to check to see whether any corrupt-data
   * warnings occurred (test whether jerr.num_warnings is nonzero).
   */

  /* Detach from the drawable and add it to the image.
   */
  if (! preview)
    {
      gimp_progress_update (1.0);
    }

  gimp_image_insert_layer (image_ID, layer_ID, -1, 0);

#ifdef HAVE_LIBEXIF
  jpeg_exif_rotate_query (image_ID, orientation);
#endif

  return image_ID;
}
Beispiel #9
0
uvc_error_t uvc_mjpeg2yuyv(uvc_frame_t *in, uvc_frame_t *out) {

	out->actual_bytes = 0;	// XXX
	if (UNLIKELY(in->frame_format != UVC_FRAME_FORMAT_MJPEG))
		return UVC_ERROR_INVALID_PARAM;

	if (uvc_ensure_frame_size(out, in->width * in->height * 2) < 0)
		return UVC_ERROR_NO_MEM;

	size_t lines_read = 0;
	int i, j;
	int num_scanlines;
	register uint8_t *yuyv, *ycbcr;

	out->width = in->width;
	out->height = in->height;
	out->frame_format = UVC_FRAME_FORMAT_YUYV;
	out->step = in->width * 2;
	out->sequence = in->sequence;
	out->capture_time = in->capture_time;
	out->source = in->source;

	struct jpeg_decompress_struct dinfo;
	struct error_mgr jerr;
	dinfo.err = jpeg_std_error(&jerr.super);
	jerr.super.error_exit = _error_exit;

	if (setjmp(jerr.jmp)) {
		goto fail;
	}

	jpeg_create_decompress(&dinfo);
	jpeg_mem_src(&dinfo, in->data, in->actual_bytes/*in->data_bytes*/);	// XXX
	jpeg_read_header(&dinfo, TRUE);

	if (dinfo.dc_huff_tbl_ptrs[0] == NULL) {
		/* This frame is missing the Huffman tables: fill in the standard ones */
		insert_huff_tables(&dinfo);
	}

	dinfo.out_color_space = JCS_YCbCr;
	dinfo.dct_method = JDCT_IFAST;

	// start decompressor
	jpeg_start_decompress(&dinfo);

	// these dinfo.xxx valiables are only valid after jpeg_start_decompress
	const int row_stride = dinfo.output_width * dinfo.output_components;

	// allocate buffer
	register JSAMPARRAY buffer = (*dinfo.mem->alloc_sarray)
		((j_common_ptr) &dinfo, JPOOL_IMAGE, row_stride, MAX_READLINE);

	// local copy
	uint8_t *data = out->data;
	const int out_step = out->step;

	if (LIKELY(dinfo.output_height == out->height)) {
		for (; dinfo.output_scanline < dinfo.output_height ;) {
			// convert lines of mjpeg data to YCbCr
			num_scanlines = jpeg_read_scanlines(&dinfo, buffer, MAX_READLINE);
			// convert YCbCr to yuyv(YUV422)
			for (j = 0; j < num_scanlines; j++) {
				yuyv = data + (lines_read + j) * out_step;
				ycbcr = buffer[j];
				for (i = 0; i < row_stride; i += 24) {	// step by YCbCr x 8 pixels = 3 x 8 bytes
					YCbCr_YUYV_2(ycbcr + i, yuyv);
					YCbCr_YUYV_2(ycbcr + i + 6, yuyv);
					YCbCr_YUYV_2(ycbcr + i + 12, yuyv);
					YCbCr_YUYV_2(ycbcr + i + 18, yuyv);
				}
			}
			lines_read += num_scanlines;
		}
		out->actual_bytes = in->width * in->height * 2;	// XXX
	}

	jpeg_finish_decompress(&dinfo);
	jpeg_destroy_decompress(&dinfo);
	return lines_read == out->height ? UVC_SUCCESS : UVC_ERROR_OTHER;

fail:
	jpeg_destroy_decompress(&dinfo);
	return lines_read == out->height ? UVC_SUCCESS : UVC_ERROR_OTHER+1;
}
Beispiel #10
0
int loadJPG(ePtr<gPixmap> &result, const char *filename, ePtr<gPixmap> alpha)
{
	struct jpeg_decompress_struct cinfo;
	struct my_error_mgr jerr;
	JSAMPARRAY buffer;
	int row_stride;
	CFile infile(filename, "rb");
	result = 0;

	if (alpha)
	{
		if (alpha->surface->bpp != 8)
		{
			eWarning("[loadJPG] alpha channel for jpg must be 8bit");
			alpha = 0;
		}
	}

	if (!infile)
		return -1;
	cinfo.err = jpeg_std_error(&jerr.pub);
	jerr.pub.error_exit = my_error_exit;
	if (setjmp(jerr.setjmp_buffer)) {
		result = 0;
		jpeg_destroy_decompress(&cinfo);
		return -1;
	}
	jpeg_create_decompress(&cinfo);
	jpeg_stdio_src(&cinfo, infile);
	(void) jpeg_read_header(&cinfo, TRUE);
	cinfo.out_color_space = JCS_RGB;
	cinfo.scale_denom = 1;

	(void) jpeg_start_decompress(&cinfo);

	int grayscale = cinfo.output_components == 1;

	if (alpha)
	{
		if (((int)cinfo.output_width != alpha->surface->x) || ((int)cinfo.output_height != alpha->surface->y))
		{
			eWarning("[loadJPG] alpha channel size (%dx%d) must match jpeg size (%dx%d)", alpha->surface->x, alpha->surface->y, cinfo.output_width, cinfo.output_height);
			alpha = 0;
		}
		if (grayscale)
		{
			eWarning("[loadJPG] no support for grayscale + alpha at the moment");
			alpha = 0;
		}
	}

	result = new gPixmap(eSize(cinfo.output_width, cinfo.output_height), grayscale ? 8 : 32);

	row_stride = cinfo.output_width * cinfo.output_components;
	buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
	while (cinfo.output_scanline < cinfo.output_height) {
		int y = cinfo.output_scanline;
		(void) jpeg_read_scanlines(&cinfo, buffer, 1);
		unsigned char *dst = ((unsigned char*)result->surface->data) + result->surface->stride * y;
		unsigned char *src = (unsigned char*)buffer[0];
		unsigned char *palpha = alpha ? ((unsigned char*)alpha->surface->data + alpha->surface->stride * y) : 0;
		if (grayscale)
			memcpy(dst, src, cinfo.output_width);
		else
		{
			if (palpha)
			{
				for (int x = (int)cinfo.output_width; x != 0; --x)
				{
					*dst++ = src[2];
					*dst++ = src[1];
					*dst++ = src[0];
					*dst++ = *palpha++;
					src += 3;
				}
			}
			else
			{
				for (int x = (int)cinfo.output_width; x != 0; --x)
				{
					*dst++ = src[2];
					*dst++ = src[1];
					*dst++ = src[0];
					*dst++ = 0xFF;
					src += 3;
				}
			}
		}
	}
	(void) jpeg_finish_decompress(&cinfo);
	jpeg_destroy_decompress(&cinfo);
	return 0;
}
int fh_jpeg_load(const char *filename,unsigned char **buffer,int* x,int* y)
{
    //dbout("fh_jpeg_load_local (%s/%d/%d) {\n",basename(filename),*x,*y);
    struct jpeg_decompress_struct cinfo;
    struct jpeg_decompress_struct *ciptr;
    struct r_jpeg_error_mgr emgr;
    unsigned char *bp;
    int px,py,c;
    FILE *fh;
    JSAMPLE *lb;

    ciptr=&cinfo;
    if(!(fh=fopen(filename,"rb"))) return(FH_ERROR_FILE);
    ciptr->err=jpeg_std_error(&emgr.pub);
    emgr.pub.error_exit=jpeg_cb_error_exit;
    if(setjmp(emgr.envbuffer)==1)
    {
        // FATAL ERROR - Free the object and return...
        jpeg_destroy_decompress(ciptr);
        fclose(fh);
//	dbout("fh_jpeg_load } - FATAL ERROR\n");
        return(FH_ERROR_FORMAT);
    }

    jpeg_create_decompress(ciptr);
    jpeg_stdio_src(ciptr,fh);
    jpeg_read_header(ciptr,TRUE);
    ciptr->out_color_space=JCS_RGB;
    ciptr->dct_method=JDCT_FASTEST;
    if(*x==(int)ciptr->image_width)
        ciptr->scale_denom=1;
    else if(abs(*x*2 - ciptr->image_width) < 2)
        ciptr->scale_denom=2;
    else if(abs(*x*4 - ciptr->image_width) < 4)
        ciptr->scale_denom=4;
    else if(abs(*x*8 - ciptr->image_width) < 8)
        ciptr->scale_denom=8;
    else
        ciptr->scale_denom=1;

    jpeg_start_decompress(ciptr);

    px=ciptr->output_width;
    py=ciptr->output_height;
    c=ciptr->output_components;
    if(px > *x || py > *y)
    {
        // pic act larger, e.g. because of not responding jpeg server
        free(*buffer);
        *buffer = (unsigned char*) malloc(px*py*3);
        *x = px;
        *y = py;
    }

    if(c==3)
    {
        lb=(JSAMPLE*)(*ciptr->mem->alloc_small)((j_common_ptr) ciptr,JPOOL_PERMANENT,c*px);
        bp=*buffer;
        while(ciptr->output_scanline < ciptr->output_height)
        {
            jpeg_read_scanlines(ciptr, &lb, 1);
            memmove(bp,lb,px*c);
            bp+=px*c;
        }

    }
    jpeg_finish_decompress(ciptr);
    jpeg_destroy_decompress(ciptr);
    fclose(fh);
    //dbout("fh_jpeg_load_local }\n");
    return(FH_ERROR_OK);
}
Beispiel #12
0
void JP4::open(const string& _filename) {

  this->_filename = string(_filename);

  struct jpeg_error_mgr jerr;
  struct jpeg_decompress_struct dinfo;

  JSAMPARRAY buffer;

  FILE *ifp = NULL;

  dinfo.err = jpeg_std_error (&jerr);

  ifp = fopen(filename().c_str(), "rb");

  jpeg_create_decompress (&dinfo);
  jpeg_stdio_src (&dinfo, ifp);
  // instruct it to save EXIF at APP1 (0xe1) data (up to 64k)
  jpeg_save_markers(&dinfo, 0xe1, 0xffff);
  jpeg_read_header (&dinfo, TRUE);

  dinfo.do_block_smoothing = FALSE;
  dinfo.out_color_space = JCS_GRAYSCALE;

  // save raw APP1 data (if any)
  if (dinfo.marker_list) {
    _raw_app1_length = dinfo.marker_list[0].data_length;
    _raw_app1 = new unsigned char[_raw_app1_length];
    memcpy(_raw_app1, dinfo.marker_list[0].data, _raw_app1_length);
  }

  this->_width = dinfo.image_width;
  this->_height = dinfo.image_height;

  buffer = (*dinfo.mem->alloc_sarray)((j_common_ptr)&dinfo, JPOOL_IMAGE, width(), 1);

  _data = new unsigned short[width()*height()];

  jpeg_start_decompress (&dinfo);

  unsigned short* temp = new unsigned short[width()*height()];

  for (unsigned int line = 0; line < height(); line++) {
    jpeg_read_scanlines (&dinfo, buffer, 1);
    for (unsigned int column = 0; column < width(); column++)
      temp[line*width() + column] = buffer[0][column];
  }

  // EXIF
  readMakerNote();

  // JP4 deblocking
  // from http://code.google.com/p/gst-plugins-elphel/source/browse/trunk/jp462bayer/src/gstjp462bayer.c
  unsigned int y, x;
  unsigned int b_of = 0;
  unsigned int h_of;
  unsigned int i, j;
  unsigned int index1[16]={0,8,1,9,2,10,3,11,4,12,5,13,6,14,7,15};
  unsigned int  index2[16];

  for (j = 0;j < 16; ++j)
    index2[j] = index1[j] * width();

  for (y = 0; y < height(); y += 16, b_of += width() << 4)
    for (x = 0; x < width(); x += 16)
      for (j = 0, h_of = 0; j < 16; ++j, h_of += width())
        for (i = 0; i < 16; ++i)
          _data[x + i + h_of + b_of] = temp[x + index1[i] + index2[j] + b_of];

  jpeg_finish_decompress (&dinfo);
  fclose(ifp);
  delete[] temp;

}
Beispiel #13
0
    int jpeg_read(const char* filename,jpeg_datap result){
  
        auto jpegData = D2D::FileUtil::getInstacne()->getDataFromFile(filename,true);
        assert(!jpegData.isNull());
        
        /* these are standard libjpeg structures for reading(decompression) */
        struct jpeg_decompress_struct cinfo;
        /* 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.
         */
        struct MyErrorMgr jerr;
        /* libjpeg data structure for storing one row, that is, scanline of an image */
        JSAMPROW row_pointer[1] = {0};
        
        unsigned long location = 0;
        unsigned int i = 0;
        
        /* We set up the normal JPEG error routines, then override error_exit. */
        cinfo.err = jpeg_std_error(&jerr.pub);
        jerr.pub.error_exit = myErrorExit;
        /* Establish the setjmp return context for MyErrorExit 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);
            printf("decompress jpeg : %s error.\n",filename);
            abort();
            return -1;
        }
        
        /* setup decompression process and source, then read JPEG header */
        jpeg_create_decompress( &cinfo );
        
        jpeg_mem_src( &cinfo, const_cast<unsigned char*>(jpegData.getBytes()),jpegData.getSize());
        
        /* reading the image header which contains image information */
#if (JPEG_LIB_VERSION >= 90)
        // libjpeg 0.9 adds stricter types.
        jpeg_read_header( &cinfo, TRUE );
#else
        jpeg_read_header( &cinfo, true );
#endif
        
        // we only support RGB or grayscale
        if (cinfo.jpeg_color_space == JCS_GRAYSCALE)
        {
            result->format = Texture2D::PixelFormat::I8;
        }else
        {
            cinfo.out_color_space = JCS_RGB;
            result->format = Texture2D::PixelFormat::RGB888;
        }
        
        /* Start decompression jpeg here */
        jpeg_start_decompress( &cinfo );
        
        /* init image info */
        result->width  = cinfo.output_width;
        result->height = cinfo.output_height;
        
        row_pointer[0] = static_cast<unsigned char*>(malloc(cinfo.output_width*cinfo.output_components * sizeof(unsigned char)));
        
        ssize_t dataLen = cinfo.output_width * cinfo.output_height*cinfo.output_components;
        result->data = static_cast<unsigned char*>(malloc(dataLen * sizeof(unsigned char)));
        
        /* now actually read the jpeg into the raw buffer */
        /* read one scan line at a time */
        while( cinfo.output_scanline < cinfo.output_height ){
            
            jpeg_read_scanlines( &cinfo, row_pointer, 1 );
            for( i=0; i<cinfo.output_width*cinfo.output_components;i++)
            {
                result->data[location++] = row_pointer[0][i];
            }
        }
        
        /* When read image file with broken data, jpeg_finish_decompress() may cause error.
         * Besides, jpeg_destroy_decompress() shall deallocate and release all memory associated
         * with the decompression object.
         * So it doesn't need to call jpeg_finish_decompress().
         */
        //jpeg_finish_decompress( &cinfo );
        jpeg_destroy_decompress( &cinfo );
        
        if (row_pointer[0] != nullptr)
        {
            free(row_pointer[0]);
        };
        
        return 0;
    }
Beispiel #14
0
static void load_jpg_entry_helper(ALLEGRO_FILE *fp,
   struct load_jpg_entry_helper_data *data, int flags)
{
   struct jpeg_decompress_struct cinfo;
   struct my_err_mgr jerr;
   ALLEGRO_LOCKED_REGION *lock;
   int w, h, s;

   /* ALLEGRO_NO_PREMULTIPLIED_ALPHA does not apply.
    * ALLEGRO_KEEP_INDEX does not apply.
    */
   (void)flags;

   data->error = false;

   cinfo.err = jpeg_std_error(&jerr.pub);
   jerr.pub.error_exit = my_error_exit;
   if (setjmp(jerr.jmpenv) != 0) {
      /* Longjmp'd. */
      data->error = true;
      goto longjmp_error;
   }

   data->buffer = al_malloc(BUFFER_SIZE);
   if (!data->buffer) {
      data->error = true;
      goto error;
   }

   jpeg_create_decompress(&cinfo);
   jpeg_packfile_src(&cinfo, fp, data->buffer);
   jpeg_read_header(&cinfo, true);
   jpeg_start_decompress(&cinfo);

   w = cinfo.output_width;
   h = cinfo.output_height;
   s = cinfo.output_components;

   /* Only one and three components make sense in a JPG file. */
   if (s != 1 && s != 3) {
      data->error = true;
      ALLEGRO_ERROR("%d components makes no sense\n", s);
      goto error;
   }

   data->bmp = al_create_bitmap(w, h);
   if (!data->bmp) {
      data->error = true;
      ALLEGRO_ERROR("%dx%d bitmap creation failed\n", w, h);
      goto error;
   }

   /* Allegro's pixel format is endian independent, so that in
    * ALLEGRO_PIXEL_FORMAT_RGB_888 the lower 8 bits always hold the Blue
    * component.  On a little endian system this is in byte 0.  On a big
    * endian system this is in byte 2.
    *
    * libjpeg expects byte 0 to hold the Red component, byte 1 to hold the
    * Green component, byte 2 to hold the Blue component.  Hence on little
    * endian systems we need the opposite format, ALLEGRO_PIXEL_FORMAT_BGR_888.
    */
#ifdef ALLEGRO_BIG_ENDIAN
   lock = al_lock_bitmap(data->bmp, ALLEGRO_PIXEL_FORMAT_RGB_888,
       ALLEGRO_LOCK_WRITEONLY);
#else
   lock = al_lock_bitmap(data->bmp, ALLEGRO_PIXEL_FORMAT_BGR_888,
       ALLEGRO_LOCK_WRITEONLY);
#endif

   if (s == 3) {
      /* Colour. */
      int y;

      for (y = cinfo.output_scanline; y < h; y = cinfo.output_scanline) {
         unsigned char *out[1];
         out[0] = ((unsigned char *)lock->data) + y * lock->pitch;
         jpeg_read_scanlines(&cinfo, (void *)out, 1);
      }
   }
   else if (s == 1) {
      /* Greyscale. */
      unsigned char *in;
      unsigned char *out;
      int x, y;

      data->row = al_malloc(w);
      for (y = cinfo.output_scanline; y < h; y = cinfo.output_scanline) {
         jpeg_read_scanlines(&cinfo, (void *)&data->row, 1);
         in = data->row;
         out = ((unsigned char *)lock->data) + y * lock->pitch;
         for (x = 0; x < w; x++) {
            *out++ = *in;
            *out++ = *in;
            *out++ = *in;
            in++;
         }
      }
   }

 error:
   jpeg_finish_decompress(&cinfo);

 longjmp_error:
   jpeg_destroy_decompress(&cinfo);

   if (data->bmp) {
      if (al_is_bitmap_locked(data->bmp)) {
         al_unlock_bitmap(data->bmp);
      }
      if (data->error) {
         al_destroy_bitmap(data->bmp);
         data->bmp = NULL;
      }
   }

   al_free(data->buffer);
   al_free(data->row);
}
static int
jpeg_image_control(ErlDrvData handle, unsigned int command, 
		   char* buf, int count, 
		   char** res, int res_size)
{
  JSAMPROW row;
  ErlDrvBinary* bin = 0;

  switch (command) {
  case 0: {			/* Read */
    struct jpeg_decompress_struct cinfo;
    int row_stride;		/* physical row width in output buffer */
    unsigned char* rbuf;
    struct my_error_mgr jerr;

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

    /* 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.
       */
      char buffer[JMSG_LENGTH_MAX];

      /* Create the message */
      (cinfo.err->format_message)((j_common_ptr) &cinfo, buffer);
      jpeg_destroy_decompress(&cinfo);

      bin = driver_alloc_binary(4+strlen(buffer));
      rbuf = bin->orig_bytes;
      ((unsigned *)rbuf)[0] = 0;
      rbuf += 4;
      memcpy(rbuf, buffer, strlen(buffer));
      *res = (void *) bin;
      return 0;
    }

    jpeg_create_decompress(&cinfo);
    jpeg_buffer_src(&cinfo, buf, count);
    (void) jpeg_read_header(&cinfo, TRUE);
    (void) jpeg_start_decompress(&cinfo);

    row_stride = cinfo.output_width * cinfo.output_components;
    res_size = row_stride * cinfo.output_height;
    bin = driver_alloc_binary(res_size+12);
    rbuf = bin->orig_bytes;
    ((unsigned *)rbuf)[0] = cinfo.output_width;
    ((unsigned *)rbuf)[1] = cinfo.output_height;
    ((unsigned *)rbuf)[2] = cinfo.output_components;
    rbuf += 12;
    while (cinfo.output_scanline < cinfo.output_height) {
      row = (JSAMPROW) rbuf;
      (void) jpeg_read_scanlines(&cinfo, &row, 1);
      rbuf += row_stride;
    }
    (void) jpeg_finish_decompress(&cinfo);
    *res = (void *) bin;
    return 0;
  }
  case 1: {			/* Write */
    struct jpeg_compress_struct cinfo;
    struct jpeg_error_mgr jerr;
    int row_stride;		/* physical row width */

    bin = driver_alloc_binary(count);

    cinfo.err = jpeg_std_error(&jerr);
    jpeg_create_compress(&cinfo);

    jpeg_buffer_dest(&cinfo, bin);
    cinfo.image_width = ((unsigned *)buf)[0];
    cinfo.image_height = ((unsigned *)buf)[1];
    cinfo.input_components = ((unsigned *)buf)[2];
    cinfo.in_color_space = JCS_RGB;
    jpeg_set_defaults(&cinfo);
    buf += 12;
    count -= 12;

    jpeg_start_compress(&cinfo, TRUE);
    row_stride = cinfo.input_components * cinfo.image_width;
        
    while (cinfo.next_scanline < cinfo.image_height) {
      row = (JSAMPROW) buf;
      (void) jpeg_write_scanlines(&cinfo, &row, 1);
      buf += row_stride;
    }

    jpeg_finish_compress(&cinfo);
    bin = jpeg_buffer_dest_get_bin(&cinfo);
    jpeg_destroy_compress(&cinfo);
    *res = (void *) bin;
    return 0;
  }
  default:
    return -1;			/* Error return, throws exception in erlang */
  }
}
Beispiel #16
0
/*read jpeg*/
unsigned char* image_read_jpeg_file( char *filename )
{
   //int** imageMat = NULL;
   unsigned char *raw_image = NULL;
	/* these are standard libjpeg structures for reading(decompression) */
	struct jpeg_decompress_struct cinfo;
	struct jpeg_error_mgr jerr;
	/* libjpeg data structure for storing one row, that is, scanline of an image */
	JSAMPROW row_pointer[1];
	
	FILE *infile = fopen( filename, "rb" );
	unsigned long location = 0;
	int i = 0;
	
	if ( !infile )
	{
		printf("Error opening jpeg file %s\n!", filename );
		//return -1;
	}
	/* here we set up the standard libjpeg error handler */
	cinfo.err = jpeg_std_error( &jerr );
	/* setup decompression process and source, then read JPEG header */
	jpeg_create_decompress( &cinfo );
	/* this makes the library read from infile */
	jpeg_stdio_src( &cinfo, infile );
	/* reading the image header which contains image information */
	jpeg_read_header( &cinfo, TRUE );
	/* Uncomment the following to output image information, if needed. */


   /*get input image width and height*/
   width = cinfo.image_width;
   height = cinfo.image_height;
   components_per_pixel = cinfo.num_components;
   color_space = cinfo.jpeg_color_space;


	/* decompression of the jpeg */
	jpeg_start_decompress( &cinfo );

	/* allocate memory to hold the uncompressed image */
	raw_image = (unsigned char*)malloc( cinfo.output_width*cinfo.output_height*cinfo.num_components );


	/* now actually read the jpeg into the raw buffer */
	row_pointer[0] = (unsigned char *)malloc( cinfo.output_width*cinfo.num_components );
	
   /* read one scan line at a time */
	while( cinfo.output_scanline < cinfo.image_height )
	{
		jpeg_read_scanlines( &cinfo, row_pointer, 1 );
		for( i=0; i<cinfo.image_width*cinfo.num_components;i++) 
			raw_image[location++] = row_pointer[0][i];
	}

	/* wrap up decompression, destroy objects, free pointers and close open files */
	jpeg_finish_decompress( &cinfo );
	jpeg_destroy_decompress( &cinfo );
	free( row_pointer[0] );
	fclose( infile );


	return raw_image;
}
Beispiel #17
0
static FIBITMAP * DLL_CALLCONV
Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
	if (handle) {
		FIBITMAP *dib = NULL;

		try {
			// set up the jpeglib structures

			struct jpeg_decompress_struct cinfo;
			struct jpeg_error_mgr jerr;

			// step 1: allocate and initialize JPEG decompression object

			cinfo.err = jpeg_std_error(&jerr);

			jerr.error_exit     = jpeg_error_exit;
			jerr.output_message = jpeg_output_message;

			jpeg_create_decompress(&cinfo);

			// step 2a: specify data source (eg, a handle)

			jpeg_freeimage_src(&cinfo, handle, io);

			// step 2b: save special markers for later reading
			
			jpeg_save_markers(&cinfo, JPEG_COM, 0xFFFF);
			for(int m = 0; m < 16; m++) {
				jpeg_save_markers(&cinfo, JPEG_APP0 + m, 0xFFFF);
			}

			// step 3: read handle parameters with jpeg_read_header()

			jpeg_read_header(&cinfo, TRUE);

			// step 4: set parameters for decompression

			unsigned int scale_denom = 1;		// fraction by which to scale image
			int	requested_size = flags >> 16;	// requested user size in pixels
			if(requested_size > 0) {
				// the JPEG codec can perform x2, x4 or x8 scaling on loading
				// try to find the more appropriate scaling according to user's need
				double scale = MAX((double)cinfo.image_width, (double)cinfo.image_height) / (double)requested_size;
				if(scale >= 8) {
					scale_denom = 8;
				} else if(scale >= 4) {
					scale_denom = 4;
				} else if(scale >= 2) {
					scale_denom = 2;
				}
			}
			cinfo.scale_num = 1;
			cinfo.scale_denom = scale_denom;

			if ((flags & JPEG_ACCURATE) != JPEG_ACCURATE) {
				cinfo.dct_method          = JDCT_IFAST;
				cinfo.do_fancy_upsampling = FALSE;
			}

			// step 5a: start decompressor and calculate output width and height

			jpeg_start_decompress(&cinfo);

			// step 5b: allocate dib and init header

			if((cinfo.num_components == 4) && (cinfo.out_color_space == JCS_CMYK)) {
				// CMYK image
				if((flags & JPEG_CMYK) == JPEG_CMYK) {
					// load as CMYK
					dib = FreeImage_Allocate(cinfo.output_width, cinfo.output_height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
					if(!dib) return NULL;
					FreeImage_GetICCProfile(dib)->flags |= FIICC_COLOR_IS_CMYK;
				} else {
					// load as CMYK and convert to RGB
					dib = FreeImage_Allocate(cinfo.output_width, cinfo.output_height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
					if(!dib) return NULL;
				}
			} else {
				// RGB or greyscale image
				dib = FreeImage_Allocate(cinfo.output_width, cinfo.output_height, 8 * cinfo.num_components, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
				if(!dib) return NULL;

				if (cinfo.num_components == 1) {
					// build a greyscale palette
					RGBQUAD *colors = FreeImage_GetPalette(dib);

					for (int i = 0; i < 256; i++) {
						colors[i].rgbRed   = (BYTE)i;
						colors[i].rgbGreen = (BYTE)i;
						colors[i].rgbBlue  = (BYTE)i;
					}
				}
			}
			if(scale_denom != 1) {
				// store original size info if a scaling was requested
				store_size_info(dib, cinfo.image_width, cinfo.image_height);
			}

			// step 5c: handle metrices

			if (cinfo.density_unit == 1) {
				// dots/inch
				FreeImage_SetDotsPerMeterX(dib, (unsigned) (((float)cinfo.X_density) / 0.0254000 + 0.5));
				FreeImage_SetDotsPerMeterY(dib, (unsigned) (((float)cinfo.Y_density) / 0.0254000 + 0.5));
			} else if (cinfo.density_unit == 2) {
				// dots/cm
				FreeImage_SetDotsPerMeterX(dib, (unsigned) (cinfo.X_density * 100));
				FreeImage_SetDotsPerMeterY(dib, (unsigned) (cinfo.Y_density * 100));
			}

			// step 6a: while (scan lines remain to be read) jpeg_read_scanlines(...);

			if((cinfo.out_color_space == JCS_CMYK) && ((flags & JPEG_CMYK) != JPEG_CMYK)) {
				// convert from CMYK to RGB

				JSAMPARRAY buffer;		// output row buffer
				unsigned row_stride;	// physical row width in output buffer

				// JSAMPLEs per row in output buffer
				row_stride = cinfo.output_width * cinfo.output_components;
				// make a one-row-high sample array that will go away when done with image
				buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);

				while (cinfo.output_scanline < cinfo.output_height) {
					JSAMPROW src = buffer[0];
					JSAMPROW dst = FreeImage_GetScanLine(dib, cinfo.output_height - cinfo.output_scanline - 1);

					jpeg_read_scanlines(&cinfo, buffer, 1);

					for(unsigned x = 0; x < FreeImage_GetWidth(dib); x++) {
						WORD K = (WORD)src[3];
						dst[FI_RGBA_RED]   = (BYTE)((K * src[0]) / 255);
						dst[FI_RGBA_GREEN] = (BYTE)((K * src[1]) / 255);
						dst[FI_RGBA_BLUE]  = (BYTE)((K * src[2]) / 255);
						src += 4;
						dst += 3;
					}
				}
			} else {
				// normal case (RGB or greyscale image)

				while (cinfo.output_scanline < cinfo.output_height) {
					JSAMPROW dst = FreeImage_GetScanLine(dib, cinfo.output_height - cinfo.output_scanline - 1);

					jpeg_read_scanlines(&cinfo, &dst, 1);
				}

				// step 6b: swap red and blue components (see LibJPEG/jmorecfg.h: #define RGB_RED, ...)
				// The default behavior of the JPEG library is kept "as is" because LibTIFF uses 
				// LibJPEG "as is".

#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
				if(cinfo.num_components == 3) {
					for(unsigned y = 0; y < FreeImage_GetHeight(dib); y++) {
						BYTE *target = FreeImage_GetScanLine(dib, y);
						for(unsigned x = 0; x < FreeImage_GetWidth(dib); x++) {
							INPLACESWAP(target[0], target[2]);
							target += 3;
						}
					}
				}
#endif
			}

			// step 7: read special markers

			read_markers(&cinfo, dib);

			// step 8: finish decompression

			jpeg_finish_decompress(&cinfo);

			// step 9: release JPEG decompression object

			jpeg_destroy_decompress(&cinfo);

			// check for automatic Exif rotation
			if((flags & JPEG_EXIFROTATE) == JPEG_EXIFROTATE) {
				rotate_exif(&dib);
			}

			// everything went well. return the loaded dib

			return (FIBITMAP *)dib;
		} catch (...) {
			if(NULL != dib) {
				FreeImage_Unload(dib);
			}
		}
	}

	return NULL;
}
Beispiel #18
0
GLOBAL(int) read_JPEG_file (char * filename, char *dest) {  
	  struct jpeg_decompress_struct cinfo;
	  struct error_mgr jerr;
	  FILE *infile;
	  FILE *outfile;   
	  JSAMPARRAY buffer;      
	  int row_stride, lines=0;   
	  
	  
	  if ((infile = fopen(filename, "rb")) == NULL) {
	  	fprintf(stderr, "Can't open: %s\n", filename);
	        return 0;
	        }
	  
	  if ((outfile = fopen(dest, "wb+")) == NULL) {
	  	fprintf(stderr, "Can't open: %s\n", filename);
	        return 0;
	        }
	  
	  cinfo.err = jpeg_std_error(&jerr.pub);
	  jerr.pub.error_exit = my_error_exit;  
	  
	  if (setjmp(jerr.setjmp_buffer)) {
	 	jpeg_destroy_decompress(&cinfo);
	  	jpeg_destroy_decompress(&cinfo);
	  	fclose(infile);
	  	fclose (outfile);
	  	return 0;
	  	}
	  
	  jpeg_create_decompress(&cinfo);
	  jpeg_stdio_src(&cinfo, infile);
	  (void) jpeg_read_header(&cinfo, TRUE);
	  (void) jpeg_start_decompress(&cinfo);
	  row_stride = cinfo.output_width * cinfo.output_components;

	  fprintf (stderr, "Information about: %s:\n", filename);
	  fprintf (stderr, "Width : %d\n", cinfo.output_width);
	  fprintf (stderr, "Height: %d\n", cinfo.output_height);
	  fprintf (stderr, "Components: %d\n", cinfo.output_components);
	  fprintf (stderr, "Size: %d\n", row_stride*cinfo.output_height);
	  
	  buffer = (*cinfo.mem->alloc_sarray)
	                  ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
	  
	  /* put a header in the image ( a pnm header )  */
	  
	  
	  fprintf (outfile,"P6\n%d %d\n255\n", cinfo.output_width, cinfo.output_height);
	  
	  
	  /* read line per line  */
	  
	  while (cinfo.output_scanline < cinfo.output_height) {
	      (void) jpeg_read_scanlines(&cinfo, buffer, 1);
              fwrite (buffer[0], row_stride, 1, outfile);
	      lines++;
	      }

	  (void) jpeg_finish_decompress(&cinfo);
	  jpeg_destroy_decompress(&cinfo);
	    
	  fclose(infile);
	  fclose (outfile);
	      
	}	           
Beispiel #19
0
static bool read_jpeg_image(QImage *outImage,
                            QSize scaledSize, QRect scaledClipRect,
                            QRect clipRect, int inQuality, j_decompress_ptr info, struct my_error_mgr* err  )
{
    if (!setjmp(err->setjmp_buffer)) {
        // -1 means default quality.
        int quality = inQuality;
        if (quality < 0)
            quality = 75;

        // If possible, merge the scaledClipRect into either scaledSize
        // or clipRect to avoid doing a separate scaled clipping pass.
        // Best results are achieved by clipping before scaling, not after.
        if (!scaledClipRect.isEmpty()) {
            if (scaledSize.isEmpty() && clipRect.isEmpty()) {
                // No clipping or scaling before final clip.
                clipRect = scaledClipRect;
                scaledClipRect = QRect();
            } else if (scaledSize.isEmpty()) {
                // Clipping, but no scaling: combine the clip regions.
                scaledClipRect.translate(clipRect.topLeft());
                clipRect = scaledClipRect.intersected(clipRect);
                scaledClipRect = QRect();
            } else if (clipRect.isEmpty()) {
                // No clipping, but scaling: if we can map back to an
                // integer pixel boundary, then clip before scaling.
                if ((info->image_width % scaledSize.width()) == 0 &&
                        (info->image_height % scaledSize.height()) == 0) {
                    int x = scaledClipRect.x() * info->image_width /
                            scaledSize.width();
                    int y = scaledClipRect.y() * info->image_height /
                            scaledSize.height();
                    int width = (scaledClipRect.right() + 1) *
                                info->image_width / scaledSize.width() - x;
                    int height = (scaledClipRect.bottom() + 1) *
                                 info->image_height / scaledSize.height() - y;
                    clipRect = QRect(x, y, width, height);
                    scaledSize = scaledClipRect.size();
                    scaledClipRect = QRect();
                }
            } else {
                // Clipping and scaling: too difficult to figure out,
                // and not a likely use case, so do it the long way.
            }
        }

        // Determine the scale factor to pass to libjpeg for quick downscaling.
        if (!scaledSize.isEmpty()) {
            if (clipRect.isEmpty()) {
                info->scale_denom =
                    qMin(info->image_width / scaledSize.width(),
                         info->image_height / scaledSize.height());
            } else {
                info->scale_denom =
                    qMin(clipRect.width() / scaledSize.width(),
                         clipRect.height() / scaledSize.height());
            }
            if (info->scale_denom < 2) {
                info->scale_denom = 1;
            } else if (info->scale_denom < 4) {
                info->scale_denom = 2;
            } else if (info->scale_denom < 8) {
                info->scale_denom = 4;
            } else {
                info->scale_denom = 8;
            }
            info->scale_num = 1;
            if (!clipRect.isEmpty()) {
                // Correct the scale factor so that we clip accurately.
                // It is recommended that the clip rectangle be aligned
                // on an 8-pixel boundary for best performance.
                while (info->scale_denom > 1 &&
                       ((clipRect.x() % info->scale_denom) != 0 ||
                        (clipRect.y() % info->scale_denom) != 0 ||
                        (clipRect.width() % info->scale_denom) != 0 ||
                        (clipRect.height() % info->scale_denom) != 0)) {
                    info->scale_denom /= 2;
                }
            }
        }

        // If high quality not required, use fast decompression
        if( quality < HIGH_QUALITY_THRESHOLD ) {
            info->dct_method = JDCT_IFAST;
            info->do_fancy_upsampling = FALSE;
        }

        (void) jpeg_calc_output_dimensions(info);

        // Determine the clip region to extract.
        QRect imageRect(0, 0, info->output_width, info->output_height);
        QRect clip;
        if (clipRect.isEmpty()) {
            clip = imageRect;
        } else if (info->scale_denom == info->scale_num) {
            clip = clipRect.intersected(imageRect);
        } else {
            // The scale factor was corrected above to ensure that
            // we don't miss pixels when we scale the clip rectangle.
            clip = QRect(clipRect.x() / int(info->scale_denom),
                         clipRect.y() / int(info->scale_denom),
                         clipRect.width() / int(info->scale_denom),
                         clipRect.height() / int(info->scale_denom));
            clip = clip.intersected(imageRect);
        }

        // Allocate memory for the clipped QImage.
        if (!ensureValidImage(outImage, info, clip.size()))
            longjmp(err->setjmp_buffer, 1);

        // Avoid memcpy() overhead if grayscale with no clipping.
        bool quickGray = (info->output_components == 1 &&
                          clip == imageRect);
        if (!quickGray) {
            // Ask the jpeg library to allocate a temporary row.
            // The library will automatically delete it for us later.
            // The libjpeg docs say we should do this before calling
            // jpeg_start_decompress().  We can't use "new" here
            // because we are inside the setjmp() block and an error
            // in the jpeg input stream would cause a memory leak.
            JSAMPARRAY rows = (info->mem->alloc_sarray)
                              ((j_common_ptr)info, JPOOL_IMAGE,
                               info->output_width * info->output_components, 1);

            (void) jpeg_start_decompress(info);

            while (info->output_scanline < info->output_height) {
                int y = int(info->output_scanline) - clip.y();
                if (y >= clip.height())
                    break;      // We've read the entire clip region, so abort.

                (void) jpeg_read_scanlines(info, rows, 1);

                if (y < 0)
                    continue;   // Haven't reached the starting line yet.

                if (info->output_components == 3) {
                    uchar *in = rows[0] + clip.x() * 3;
                    QRgb *out = (QRgb*)outImage->scanLine(y);
                    rgb888ToRgb32ConverterPtr(out, in, clip.width());
                } else if (info->out_color_space == JCS_CMYK) {
                    // Convert CMYK->RGB.
                    uchar *in = rows[0] + clip.x() * 4;
                    QRgb *out = (QRgb*)outImage->scanLine(y);
                    for (int i = 0; i < clip.width(); ++i) {
                        int k = in[3];
                        *out++ = qRgb(k * in[0] / 255, k * in[1] / 255,
                                      k * in[2] / 255);
                        in += 4;
                    }
                } else if (info->output_components == 1) {
                    // Grayscale.
                    memcpy(outImage->scanLine(y),
                           rows[0] + clip.x(), clip.width());
                }
            }
        } else {
            // Load unclipped grayscale data directly into the QImage.
            (void) jpeg_start_decompress(info);
            while (info->output_scanline < info->output_height) {
                uchar *row = outImage->scanLine(info->output_scanline);
                (void) jpeg_read_scanlines(info, &row, 1);
            }
        }

        if (info->output_scanline == info->output_height)
            (void) jpeg_finish_decompress(info);

        if (info->density_unit == 1) {
            outImage->setDotsPerMeterX(int(100. * info->X_density / 2.54));
            outImage->setDotsPerMeterY(int(100. * info->Y_density / 2.54));
        } else if (info->density_unit == 2) {
            outImage->setDotsPerMeterX(int(100. * info->X_density));
            outImage->setDotsPerMeterY(int(100. * info->Y_density));
        }

        if (scaledSize.isValid() && scaledSize != clip.size()) {
            *outImage = outImage->scaled(scaledSize, Qt::IgnoreAspectRatio, quality >= HIGH_QUALITY_THRESHOLD ? Qt::SmoothTransformation : Qt::FastTransformation);
        }

        if (!scaledClipRect.isEmpty())
            *outImage = outImage->copy(scaledClipRect);
        return !outImage->isNull();
    }
    else
        return false;
}
Beispiel #20
0
u_char *decode_jpeg (const char *file_name, fb_info *jpeg_inf)
{
	register JSAMPARRAY lineBuf;
	struct jpeg_decompress_struct cinfo;
	struct jpeg_error_mgr err_mgr;
	int bytesPerPix;
	FILE *inFile;
	u_char *retBuf;
    
    
	FILE * f;

    jpeg_file = open(file_name, O_RDONLY);
	if (NULL == jpeg_file)	{ 
		fprintf (stderr, "Error Open %s: %s\n",
			    filename, strerror(errno));
		return NULL;
	}

	cinfo.err = jpeg_std_error (&err_mgr);
	err_mgr.error_exit = jpeg_error_exit;	

	jpeg_create_decompress (&cinfo);
	jpeg_stdio_src (&cinfo, inFile);
	jpeg_read_header (&cinfo, 1);
	cinfo.do_fancy_upsampling = 0;
	cinfo.do_block_smoothing = 0;
	jpeg_start_decompress (&cinfo);

	/* 2010.2.6 and some... */
	jpeg_inf->w = cinfo.output_width;
	jpeg_inf->h = cinfo.output_height;

	short w,h;
	short *widthPtr = &w;
	short *heightPtr = &h;
	w = jpeg_inf->w;
	h = jpeg_inf->h;
	

	bytesPerPix = cinfo.output_components;

	lineBuf = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE, (*widthPtr * bytesPerPix), 1);
	retBuf = (u_char *) malloc (3 * (*widthPtr * *heightPtr));
		
	if (NULL == retBuf) {
		perror (NULL);
		return NULL;
	}
		

	if (3 == bytesPerPix) {
		int y;
			
		for (y = 0; y < cinfo.output_height; ++y)	{	
			jpeg_read_scanlines (&cinfo, lineBuf, 1);
			memcpy ((retBuf + y * *widthPtr * 3),lineBuf[0],3 * *widthPtr);
		}
	}
	else if (1 == bytesPerPix) { 
		unsigned int col;
		int lineOffset = (*widthPtr * 3);
		int lineBufIndex;
		int x ;
		int y;
						
		for (y = 0; y < cinfo.output_height; ++y) {
			jpeg_read_scanlines (&cinfo, lineBuf, 1);
				
			lineBufIndex = 0;
			for (x = 0; x < lineOffset; ++x) {
				col = lineBuf[0][lineBufIndex];
			
				retBuf[(lineOffset * y) + x] = col;
				++x;
				retBuf[(lineOffset * y) + x] = col;
				++x;
				retBuf[(lineOffset * y) + x] = col;
				
				++lineBufIndex;
			}			
		}
	}
	else {
		fprintf (stderr, "Error: the number of color channels is %d.  This program only handles 1 or 3\n", bytesPerPix);
		return NULL;
	}
	jpeg_finish_decompress (&cinfo);
	jpeg_destroy_decompress (&cinfo);
	fclose (inFile);
			
	return retBuf;
}
Beispiel #21
0
gint32
load_thumbnail_image (const gchar   *filename,
                      gint          *width,
                      gint          *height,
                      GimpImageType *type,
                      GError       **error)
{
  gint32 volatile  image_ID;
  ExifData        *exif_data;
  gint32           layer_ID;
  struct jpeg_decompress_struct cinfo;
  struct my_error_mgr           jerr;
  guchar          *buf;
  guchar         **rowbuf;
  GimpImageBaseType image_type;
  GimpImageType    layer_type;
  GeglBuffer      *buffer = NULL;
  gint             tile_height;
  gint             scanlines;
  gint             i, start, end;
  gint             orientation;
  my_src_ptr       src;
  FILE            *infile;

  image_ID = -1;
  exif_data = jpeg_exif_data_new_from_file (filename, NULL);

  if (! ((exif_data) && (exif_data->data) && (exif_data->size > 0)))
    return -1;

  orientation = jpeg_exif_get_orientation (exif_data);

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

  gimp_progress_init_printf (_("Opening thumbnail for '%s'"),
                             gimp_filename_to_utf8 (filename));

  /* 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);

      if (image_ID != -1)
        gimp_image_delete (image_ID);

      if (exif_data)
        {
          exif_data_unref (exif_data);
          exif_data = NULL;
        }

      if (buffer)
        g_object_unref (buffer);

      return -1;
    }

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

  /* Step 2: specify data source (eg, a file) */

  if (cinfo.src == NULL)
    cinfo.src = (struct jpeg_source_mgr *)(*cinfo.mem->alloc_small)
      ((j_common_ptr) &cinfo, JPOOL_PERMANENT,
       sizeof (my_source_mgr));

  src = (my_src_ptr) cinfo.src;

  src->pub.init_source       = init_source;
  src->pub.fill_input_buffer = fill_input_buffer;
  src->pub.skip_input_data   = skip_input_data;
  src->pub.resync_to_restart = jpeg_resync_to_restart;
  src->pub.term_source       = term_source;

  src->pub.bytes_in_buffer   = exif_data->size;
  src->pub.next_input_byte   = exif_data->data;

  src->buffer = exif_data->data;
  src->size = exif_data->size;

  /* 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);

  /* 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.  In
   * this example, we need to make an output work buffer of the
   * right size.
   */

  /* temporary buffer */
  tile_height = gimp_tile_height ();
  buf = g_new (guchar,
               tile_height * cinfo.output_width * cinfo.output_components);

  rowbuf = g_new (guchar *, tile_height);

  for (i = 0; i < tile_height; i++)
    rowbuf[i] = buf + cinfo.output_width * cinfo.output_components * i;

  /* Create a new image of the proper size and associate the
   * filename with it.
   */
  switch (cinfo.output_components)
    {
    case 1:
      image_type = GIMP_GRAY;
      layer_type = GIMP_GRAY_IMAGE;
      break;

    case 3:
      image_type = GIMP_RGB;
      layer_type = GIMP_RGB_IMAGE;
      break;

    case 4:
      if (cinfo.out_color_space == JCS_CMYK)
        {
          image_type = GIMP_RGB;
          layer_type = GIMP_RGB_IMAGE;
          break;
        }
      /*fallthrough*/

    default:
      g_message ("Don't know how to load JPEG images "
                 "with %d color channels, using colorspace %d (%d).",
                 cinfo.output_components, cinfo.out_color_space,
                 cinfo.jpeg_color_space);

      if (exif_data)
        {
          exif_data_unref (exif_data);
          exif_data = NULL;
        }

      return -1;
      break;
    }

  image_ID = gimp_image_new (cinfo.output_width, cinfo.output_height,
                             image_type);

  gimp_image_undo_disable (image_ID);
  gimp_image_set_filename (image_ID, filename);

  jpeg_load_resolution (image_ID, &cinfo);

  layer_ID = gimp_layer_new (image_ID, _("Background"),
                             cinfo.output_width,
                             cinfo.output_height,
                             layer_type, 100, GIMP_NORMAL_MODE);

  /* 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.
   */
  buffer = gimp_drawable_get_buffer (layer_ID);

  while (cinfo.output_scanline < cinfo.output_height)
    {
      start = cinfo.output_scanline;
      end   = cinfo.output_scanline + tile_height;
      end   = MIN (end, cinfo.output_height);
      scanlines = end - start;

      for (i = 0; i < scanlines; i++)
        jpeg_read_scanlines (&cinfo, (JSAMPARRAY) &rowbuf[i], 1);

      if (cinfo.out_color_space == JCS_CMYK)
        jpeg_load_cmyk_to_rgb (buf, cinfo.output_width * scanlines, NULL);

      gegl_buffer_set (buffer,
                       GEGL_RECTANGLE (0, start, cinfo.output_width, scanlines),
                       0,
                       NULL,
                       buf,
                       GEGL_AUTO_ROWSTRIDE);

      gimp_progress_update ((gdouble) cinfo.output_scanline /
                            (gdouble) cinfo.output_height);
    }

  /* Step 7: Finish decompression */

  jpeg_finish_decompress (&cinfo);
  /* We can ignore the return value since suspension is not possible
   * with the stdio data source.
   */

  /* Step 8: Release JPEG decompression object */

  /* This is an important step since it will release a good deal
   * of memory.
   */
  jpeg_destroy_decompress (&cinfo);

  g_object_unref (buffer);

  /* free up the temporary buffers */
  g_free (rowbuf);
  g_free (buf);

  /* At this point you may want to check to see whether any
   * corrupt-data warnings occurred (test whether
   * jerr.num_warnings is nonzero).
   */
  gimp_image_insert_layer (image_ID, layer_ID, -1, 0);


  /* NOW to get the dimensions of the actual image to return the
   * calling app
   */
  cinfo.err = jpeg_std_error (&jerr.pub);
  jerr.pub.error_exit = my_error_exit;
  jerr.pub.output_message = my_output_message;

  if ((infile = g_fopen (filename, "rb")) == NULL)
    {
      g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
                   _("Could not open '%s' for reading: %s"),
                   gimp_filename_to_utf8 (filename), g_strerror (errno));

      if (exif_data)
        {
          exif_data_unref (exif_data);
          exif_data = NULL;
        }

      return -1;
    }

  /* 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);

      if (image_ID != -1)
        gimp_image_delete (image_ID);

      if (exif_data)
        {
          exif_data_unref (exif_data);
          exif_data = NULL;
        }

      return -1;
    }

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

  /* Step 2: specify data source (eg, a file) */

  jpeg_stdio_src (&cinfo, infile);

  /* Step 3: read file parameters with jpeg_read_header() */

  jpeg_read_header (&cinfo, TRUE);

  jpeg_start_decompress (&cinfo);

  *width  = cinfo.output_width;
  *height = cinfo.output_height;

  /* Step 4: Release JPEG decompression object */

  /* This is an important step since it will release a good deal
   * of memory.
   */
  jpeg_destroy_decompress (&cinfo);

  fclose (infile);

  if (exif_data)
    {
      exif_data_unref (exif_data);
      exif_data = NULL;
    }

  jpeg_exif_rotate (image_ID, orientation);

  *type = layer_type;

  return image_ID;
}
Beispiel #22
0
//! creates a surface from the file
IImage* CImageLoaderJPG::loadImage(io::IReadFile* file) const
{
	#ifndef _IRR_COMPILE_WITH_LIBJPEG_
	os::Printer::log("Can't load as not compiled with _IRR_COMPILE_WITH_LIBJPEG_:", file->getFileName(), ELL_DEBUG);
	return 0;
	#else

	if (!file)
		return 0;

	Filename = file->getFileName();

	u8 **rowPtr=0;
	u8* input = new u8[file->getSize()];
	file->read(input, file->getSize());

	// allocate and initialize JPEG decompression object
	struct jpeg_decompress_struct cinfo;
	struct irr_jpeg_error_mgr jerr;

	//We have to set up the error handler first, in case the initialization
	//step fails.  (Unlikely, but it could happen if you are out of memory.)
	//This routine fills in the contents of struct jerr, and returns jerr's
	//address which we place into the link field in cinfo.

	cinfo.err = jpeg_std_error(&jerr.pub);
	cinfo.err->error_exit = error_exit;
	cinfo.err->output_message = output_message;

	// compatibility fudge:
	// we need to use setjmp/longjmp for error handling as gcc-linux
	// crashes when throwing within external c code
	if (setjmp(jerr.setjmp_buffer))
	{
		// If we get here, the JPEG code has signaled an error.
		// We need to clean up the JPEG object and return.

		jpeg_destroy_decompress(&cinfo);

		delete [] input;
		delete [] rowPtr;

		// return null pointer
		return 0;
	}

	// Now we can initialize the JPEG decompression object.
	jpeg_create_decompress(&cinfo);

	// specify data source
	jpeg_source_mgr jsrc;

	// Set up data pointer
	jsrc.bytes_in_buffer = file->getSize();
	jsrc.next_input_byte = (JOCTET*)input;
	cinfo.src = &jsrc;

	jsrc.init_source = init_source;
	jsrc.fill_input_buffer = fill_input_buffer;
	jsrc.skip_input_data = skip_input_data;
	jsrc.resync_to_restart = jpeg_resync_to_restart;
	jsrc.term_source = term_source;

	// Decodes JPG input from whatever source
	// Does everything AFTER jpeg_create_decompress
	// and BEFORE jpeg_destroy_decompress
	// Caller is responsible for arranging these + setting up cinfo

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

	bool useCMYK=false;
	if (cinfo.jpeg_color_space==JCS_CMYK)
	{
		cinfo.out_color_space=JCS_CMYK;
		cinfo.out_color_components=4;
		useCMYK=true;
	}
	else
	{
		cinfo.out_color_space=JCS_RGB;
		cinfo.out_color_components=3;
	}
	cinfo.output_gamma=2.2;
	cinfo.do_fancy_upsampling=FALSE;

	// Start decompressor
	jpeg_start_decompress(&cinfo);

	// Get image data
	u16 rowspan = cinfo.image_width * cinfo.out_color_components;
	u32 width = cinfo.image_width;
	u32 height = cinfo.image_height;

	// Allocate memory for buffer
	u8* output = new u8[rowspan * height];

	// 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.
	// Create array of row pointers for lib
	rowPtr = new u8* [height];

	for( u32 i = 0; i < height; i++ )
		rowPtr[i] = &output[ i * rowspan ];

	u32 rowsRead = 0;

	while( cinfo.output_scanline < cinfo.output_height )
		rowsRead += jpeg_read_scanlines( &cinfo, &rowPtr[rowsRead], cinfo.output_height - rowsRead );

	delete [] rowPtr;
	// Finish decompression

	jpeg_finish_decompress(&cinfo);

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

	// convert image
	IImage* image = 0;
	if (useCMYK)
	{
		image = new CImage(ECF_R8G8B8,
				core::dimension2d<u32>(width, height));
		const u32 size = 3*width*height;
		u8* data = (u8*)image->getData();
		if (data)
		{
			for (u32 i=0,j=0; i<size; i+=3, j+=4)
			{
				// Also works without K, but has more contrast with K multiplied in
//				data[i+0] = output[j+2];
//				data[i+1] = output[j+1];
//				data[i+2] = output[j+0];
				data[i+0] = (char)(output[j+2]*(output[j+3]/255.f));
				data[i+1] = (char)(output[j+1]*(output[j+3]/255.f));
				data[i+2] = (char)(output[j+0]*(output[j+3]/255.f));
			}
		}
		delete [] output;
	}
	else
		image = new CImage(ECF_R8G8B8,
				core::dimension2d<u32>(width, height), output);

	delete [] input;

	return image;

	#endif
}
Beispiel #23
0
/** @brief Convert an MJPEG frame to RGB
 * @ingroup frame
 *
 * @param in MJPEG frame
 * @param out RGB frame
 */
uvc_error_t uvc_mjpeg2rgb(uvc_frame_t *in, uvc_frame_t *out) {
	struct jpeg_decompress_struct dinfo;
	struct error_mgr jerr;
	size_t lines_read;
	// local copy
	uint8_t *data = out->data;
	const int out_step = out->step;

	int num_scanlines, i;
	lines_read = 0;
	unsigned char *buffer[MAX_READLINE];

	out->actual_bytes = 0;	// XXX
	if (UNLIKELY(in->frame_format != UVC_FRAME_FORMAT_MJPEG))
		return UVC_ERROR_INVALID_PARAM;

	if (uvc_ensure_frame_size(out, in->width * in->height * 3) < 0)
		return UVC_ERROR_NO_MEM;

	out->width = in->width;
	out->height = in->height;
	out->frame_format = UVC_FRAME_FORMAT_RGB;
	out->step = in->width * 3;
	out->sequence = in->sequence;
	out->capture_time = in->capture_time;
	out->source = in->source;

	dinfo.err = jpeg_std_error(&jerr.super);
	jerr.super.error_exit = _error_exit;

	if (setjmp(jerr.jmp)) {
		goto fail;
	}

	jpeg_create_decompress(&dinfo);
	jpeg_mem_src(&dinfo, in->data, in->actual_bytes/*in->data_bytes*/);
	jpeg_read_header(&dinfo, TRUE);

	if (dinfo.dc_huff_tbl_ptrs[0] == NULL) {
		/* This frame is missing the Huffman tables: fill in the standard ones */
		insert_huff_tables(&dinfo);
	}

	dinfo.out_color_space = JCS_RGB;
	dinfo.dct_method = JDCT_IFAST;

	jpeg_start_decompress(&dinfo);

	if (LIKELY(dinfo.output_height == out->height)) {
		for (; dinfo.output_scanline < dinfo.output_height ;) {
			buffer[0] = data + (lines_read) * out_step;
			for (i = 1; i < MAX_READLINE; i++)
				buffer[i] = buffer[i-1] + out_step;
			num_scanlines = jpeg_read_scanlines(&dinfo, buffer, MAX_READLINE);
			lines_read += num_scanlines;
		}
		out->actual_bytes = in->width * in->height * 3;	// XXX
	}
	jpeg_finish_decompress(&dinfo);
	jpeg_destroy_decompress(&dinfo);
	return lines_read == out->height ? UVC_SUCCESS : UVC_ERROR_OTHER;	// XXX

fail:
	jpeg_destroy_decompress(&dinfo);
	return UVC_ERROR_OTHER+1;
}
Beispiel #24
0
int LoadJPG( const char *filename, unsigned char **pic, int *width, int *height ) {
  /* This struct contains the JPEG decompression parameters and pointers to
   * working space (which is allocated as needed by the JPEG library).
   */
  struct jpeg_decompress_struct cinfo;
  /* 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.
   */
  /* This struct represents a JPEG error handler.  It is declared separately
   * because applications often want to supply a specialized error handler
   * (see the second half of this file for an example).  But here we just
   * take the easy way out and use the standard error handler, which will
   * print a message on stderr and call exit() if compression fails.
   * Note that this struct must live as long as the main JPEG parameter
   * struct, to avoid dangling-pointer problems.
   */
  struct jpeg_error_mgr jerr;
  /* More stuff */
  fileHandle_t infile;		/* source file */
  JSAMPARRAY buffer;		/* Output row buffer */
  int row_stride;		/* physical row width in output buffer */
  unsigned char *out;

  /* In this example we want to open the input file before doing anything else,
   * so that the setjmp() error recovery below can assume the file is open.
   * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
   * requires it in order to read binary files.
   */

  FS_FOpenFileRead( filename, &infile, qfalse );
  if (infile == 0) {
    return 0;
  }

  /* Step 1: allocate and initialize JPEG decompression object */

  /* We have to set up the error handler first, in case the initialization
   * step fails.  (Unlikely, but it could happen if you are out of memory.)
   * This routine fills in the contents of struct jerr, and returns jerr's
   * address which we place into the link field in cinfo.
   */
  cinfo.err = jpeg_std_error(&jerr);

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

  /* Step 2: specify data source (eg, a file) */

  jpeg_stdio_src(&cinfo, (unsigned char *)infile);

  /* Step 3: read file parameters with jpeg_read_header() */

  (void) jpeg_read_header(&cinfo, TRUE);
  /* We can ignore the return value from jpeg_read_header since
   *   (a) suspension is not possible with the stdio data source, and
   *   (b) we passed TRUE to reject a tables-only JPEG file as an error.
   * See libjpeg.doc for more info.
   */

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

  (void) jpeg_start_decompress(&cinfo);
  /* We can ignore the return value since suspension is not possible
   * with the stdio data source.
   */

  /* 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.
   * In this example, we need to make an output work buffer of the right size.
   */ 
  /* JSAMPLEs per row in output buffer */
  row_stride = cinfo.output_width * cinfo.output_components;

  out = Z_Malloc(cinfo.output_width*cinfo.output_height*cinfo.output_components);

  *pic = out;
  *width = cinfo.output_width;
  *height = cinfo.output_height;

  /* 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.
   */
  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.
     */
	buffer = (JSAMPARRAY)out+(row_stride*cinfo.output_scanline);
    (void) jpeg_read_scanlines(&cinfo, buffer, 1);
  }

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

  /* Step 8: Release JPEG decompression object */

  /* This is an important step since it will release a good deal of memory. */
  jpeg_destroy_decompress(&cinfo);

  /* 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...)
   */
  FS_FCloseFile(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 1;
}
/*!
Tries to fill the image object with the data read from
the given input stream. Returns true on success.
*/
bool JPGImageFileType::read(ImagePtr &OSG_JPG_ARG(image), std::istream &OSG_JPG_ARG(is),
                            const std::string &OSG_JPG_ARG(mimetype))
{
#ifdef OSG_WITH_JPG

    struct osg_jpeg_error_mgr jerr;
    struct jpeg_decompress_struct cinfo;

    cinfo.err = jpeg_std_error(&jerr.pub);
    if (setjmp(jerr.setjmp_buffer))
        return false;
    cinfo.err->error_exit = osg_jpeg_error_exit;
    cinfo.err->output_message = osg_jpeg_output_message;

    jpeg_create_decompress(&cinfo);

    SourceManager *sourceManager =
        new ((*cinfo.mem->alloc_small)(reinterpret_cast<j_common_ptr>(&cinfo), JPOOL_IMAGE, sizeof(SourceManager)))
        SourceManager(&cinfo, is);
    cinfo.src = reinterpret_cast<jpeg_source_mgr*>(sourceManager);

    jpeg_read_header(&cinfo, TRUE);
    jpeg_start_decompress(&cinfo);

    Image::PixelFormat pixelFormat;
    switch (cinfo.output_components)
    {
    case 1:
        pixelFormat = Image::OSG_L_PF;
        break;
    case 3:
        pixelFormat = Image::OSG_RGB_PF;
        break;
    default:
        pixelFormat = Image::OSG_INVALID_PF;
        break;
    };

    bool retCode;
    if (image->set(pixelFormat, cinfo.output_width, cinfo.output_height) == true)
    {
        Real32 res_x = Real32(cinfo.X_density);
        Real32 res_y = Real32(cinfo.Y_density);
        UInt16 res_unit = UInt16(cinfo.density_unit);
        if(res_unit == 2) // centimeter
        {
            // convert dpcm to dpi.
            res_x *= 2.54f;
            res_y *= 2.54f;
            res_unit = Image::OSG_RESUNIT_INCH;
        }
        image->setResX(res_x);
        image->setResY(res_y);
        image->setResUnit(res_unit);

        unsigned char *destData = image->editData() + image->getSize();
        int row_stride = cinfo.output_width * cinfo.output_components;
        while (cinfo.output_scanline < cinfo.output_height)
        {
            destData -= row_stride;
            jpeg_read_scanlines(&cinfo, &destData, 1);
        }
        retCode = true;
    }
	else
		retCode = false;

    jpeg_finish_decompress(&cinfo);
    jpeg_destroy_decompress(&cinfo);

	return retCode;

#else

    SWARNING <<
        getMimeType() <<
        " read is not compiled into the current binary " <<
        std::endl;
    return false;

#endif
}
Beispiel #26
0
Image ImageJpgFile (uint8_t * buf, uint32_t size)
{
   ImageFile *Image;
  struct jpeg_decompress_struct cinfo;
  struct my_error_mgr jerr;
  int row_stride;    /* physical row width in output buffer */
  JSAMPARRAY buffer;
  int bufp;
  int i;
//  RGBcolor *out;

  /* ==== Step 1: allocate and initialize JPEG decompression object */
  /* We set up the normal JPEG error routines, then override error_exit. */
  cinfo.err = jpeg_std_error(&jerr.pub);
  
  jerr.pub.error_exit = my_error_exit;

  if (setjmp(jerr.setjmp_buffer))
  {
	  jpeg_destroy_decompress(&cinfo);
	  return NULL;
  }

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

  /* ==== Step 2: specify data source (memory buffer, in this case) */
  jpeg_memory_src (&cinfo, (char *)buf, size);

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

  /* ==== Step 4: set parameters for decompression */
  // We want max quality, doesnt matter too much it can be a bit slow

  // We almost always want RGB output (no grayscale, yuv etc)
  if (cinfo.jpeg_color_space != JCS_GRAYSCALE)
    cinfo.out_color_space = JCS_RGB;

  // Recalculate output image dimensions
  jpeg_calc_output_dimensions (&cinfo);

  /* ==== Step 5: Start decompressor */

  (void) jpeg_start_decompress (&cinfo);
  /* 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.
   * In this example, we need to make an output work buffer of the right size.
   */
  Image = MakeImageFile(cinfo.output_width, cinfo.output_height);

  /* JSAMPLEs per row in output buffer */
  row_stride = cinfo.output_width * cinfo.output_components;
  /* Make a one-row-high sample array that will go away when done with image */
   buffer = (*cinfo.mem->alloc_sarray)
    ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, cinfo.output_height);

   // read into the buffer upside down...
   for( i = 0; i < Image->height; i++ )
	{
		if( Image->flags & IF_FLAG_INVERTED )
   	   buffer[i] = (JSAMPROW)(Image->image + 
                  ( ( (Image->height - i) - 1 ) * Image->width ));
		else
	      buffer[i] = (JSAMPROW)(Image->image + (  i * Image->width ));
	}

  /* ==== 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.
   */
  bufp = 0;
   while (cinfo.output_scanline < cinfo.output_height)
      jpeg_read_scanlines( &cinfo, buffer + cinfo.output_scanline, cinfo.image_height );


  /* blah! we're in 32 bit color space - and this reads 
   * into 24 bit space - WHY oh WHY is that... ahh well
   * we need to update this */
   for( i = 0; i < Image->height; i++ )
   {
      int j;
      char *row;
      row = (char*)buffer[i];
      for( j = Image->width; j > 0; j-- )
      {
			row[j * 4 - 1] = (uint8_t)0xff;
			if( bGLColorMode )
			{
				row[j * 4 - 2] = row[j*3-1];
				row[j * 4 - 3] = row[j*3-2];
				row[j * 4 - 4] = row[j*3-3];
			}
			else
			{
				row[j * 4 - 2] = row[j*3-3];
				row[j * 4 - 3] = row[j*3-2];
				row[j * 4 - 4] = row[j*3-1];
			}
      }
   }
  /* ==== Step 7: Finish decompression */

  (void) jpeg_finish_decompress(&cinfo);
  /* We can ignore the return value since suspension is not possible
   * with the buffer data source.
   */

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


  /* 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 Image;
}
Beispiel #27
0
int main(int argc, char **argv) 
{
  JSAMPARRAY buf = malloc(sizeof(JSAMPROW)*BUF_LINES);
  jpeg_saved_marker_ptr exif_marker, cmarker;
  MD5_CTX *MD5 = malloc(sizeof(MD5_CTX));
  volatile int i;
  int c,j,lines_read, err_count;
  unsigned char ch;
  char namebuf[1024];
  long fs;
  unsigned char *md5buf,digest[16];
  char digest_text[33];
  
  global_total_errors=0;
  if (rcsid); /* to keep compiler from not complaining about rcsid */
 
  cinfo.err = jpeg_std_error(&jerr.pub);
  jpeg_create_decompress(&cinfo);
  jerr.pub.error_exit=my_error_exit;
  jerr.pub.output_message=my_output_message;

  if (!buf || !MD5) no_memory();
  if (argc<2) {
    if (quiet_mode < 2) fprintf(stderr,"jpeginfo: file arguments missing\n"
			     "Try 'jpeginfo "
			     "--help"
			     "' for more information.\n");
    exit(1);
  }
 
  /* parse command line parameters */
  while(1) {
    opt_index=0;
    if ( (c=getopt_long(argc,argv,"livVdcChqm:f:5",
			long_options,&opt_index))  == -1) 
      break;
    switch (c) {
    case 'm':
        if (!strcasecmp(optarg,"all")) del_mode=0;
        else if (!strcasecmp(optarg,"erronly")) del_mode=1;
	else if (!quiet_mode) 
	  fprintf(stderr,"Unknown parameter for -m, --mode.\n");
      break;
    case 'f':
        if (!strcmp(optarg,"-")) listfile=stdin;
	else if ((listfile=fopen(optarg,"r"))==NULL) {
	  fprintf(stderr,"Cannot open file '%s'.\n",optarg);
	  exit(2);
	}
	input_from_file=1;
	break;
    case 'v':
      verbose_mode=1;
      break;
    case 'V':
      fprintf(stderr,"jpeginfo v" VERSION "  " HOST_TYPE 
	      "\nCopyright (c) Timo Kokkonen, 1995-2002.\n"); 
      exit(0);
    case 'd':
      delete_mode=1;
      break;
    case 'c':
      check_mode=1;
      break;
    case 'h':
      p_usage();
      break;
    case 'q':
      quiet_mode++;
      break;
    case 'l':
      list_mode=1;
      break;
    case 'i':
      longinfo_mode=1;
      break;
    case '5':
      md5_mode=1;
      break;
    case 'C':
      com_mode=1;
      break;
    case '?':
      break;

    default:
      if (!quiet_mode) 
	fprintf(stderr,"jpeginfo: error parsing parameters.\n");
    }
  }

  if (delete_mode && verbose_mode && !quiet_mode) 
    fprintf(stderr,"jpeginfo: delete mode enabled (%s)\n",
	    !del_mode?"normal":"errors only"); 

  i=1;  
  do {
   if (input_from_file) {
     if (!fgetstr(namebuf,sizeof(namebuf),listfile)) break;
     current=namebuf;
   } 
   else current=argv[i];
 
   if (current[0]==0) continue;
   if (current[0]=='-' && !input_from_file) continue;
 
   if (setjmp(jerr.setjmp_buffer)) {
      jpeg_abort_decompress(&cinfo);
      fclose(infile);
      if (list_mode && quiet_mode < 2) printf(" %s",current);
      if (quiet_mode < 2) printf(" [ERROR]\n");
      if (delete_mode) delete_file(current,verbose_mode,quiet_mode);
      continue;
   }

   if ((infile=fopen(current,"r"))==NULL) {
     if (!quiet_mode) fprintf(stderr, "jpeginfo: can't open '%s'\n", current);
     continue;
   }
   if (is_dir(infile)) {
     fclose(infile);
     if (verbose_mode) printf("directory: %s  skipped\n",current); 
     continue;
   }

   fs=filesize(infile);

   if (md5_mode) {
     md5buf=malloc(fs);
     if (!md5buf) no_memory();
     fread(md5buf,1,fs,infile);
     rewind(infile);
     
     MD5Init(MD5);
     MD5Update(MD5,md5buf,fs);
     MD5Final(digest,MD5);
     md2str(digest,digest_text);

     free(md5buf);
   }

   if (!list_mode && quiet_mode < 2) printf("%s ",current);

   global_error_counter=0;
   err_count=jerr.pub.num_warnings;
   if (com_mode) jpeg_save_markers(&cinfo, JPEG_COM, 0xffff);
   jpeg_save_markers(&cinfo, EXIF_JPEG_MARKER, 0xffff);
   jpeg_stdio_src(&cinfo, infile);
   jpeg_read_header(&cinfo, TRUE); 

   /* check for Exif marker */
   exif_marker=NULL;
   cmarker=cinfo.marker_list;
   while (cmarker) {
     if (cmarker->marker == EXIF_JPEG_MARKER) {
       if (!memcmp(cmarker->data,EXIF_IDENT_STRING,6)) exif_marker=cmarker;
     }
     cmarker=cmarker->next;
   }   

   if (quiet_mode < 2) {
     printf("%4d x %-4d %2dbit ",(int)cinfo.image_width,
            (int)cinfo.image_height,(int)cinfo.num_components*8);

     if (exif_marker) printf("Exif  ");
     else if (cinfo.saw_JFIF_marker) printf("JFIF  ");
     else if (cinfo.saw_Adobe_marker) printf("Adobe ");
     else printf("n/a   "); 

     if (longinfo_mode) {
       printf("%s %s",(cinfo.progressive_mode?"Progressive":"Normal"),
	      (cinfo.arith_code?"Arithmetic":"Huffman") );

       if (cinfo.density_unit==1||cinfo.density_unit==2) 
	 printf(",%ddp%c",MIN(cinfo.X_density,cinfo.Y_density),
		(cinfo.density_unit==1?'i':'c') );
     
       if (cinfo.CCIR601_sampling) printf(",CCIR601");
       printf(" %7ld ",fs);

     } else printf("%c %7ld ",(cinfo.progressive_mode?'P':'N'),fs);

     if (md5_mode) printf("%s ",digest_text);
     if (list_mode) printf("%s ",current);

     if (com_mode) {
       cmarker=cinfo.marker_list;
       while (cmarker) {
	 if (cmarker->marker == JPEG_COM) {
	   printf("\"");
	   for (j=0;j<cmarker->data_length;j++) {
	     ch = cmarker->data[j];
	     if (ch < 32 || iscntrl(ch)) continue;
	     printf("%c",cmarker->data[j]);
	   }
	   printf("\" ");
	 }
	 cmarker=cmarker->next;
       }
     }
   }

   if (check_mode) {
     cinfo.out_color_space=JCS_GRAYSCALE; /* to speed up the process... */
     cinfo.scale_denom = 8;
     cinfo.scale_num = 1;
     jpeg_start_decompress(&cinfo);
 
     for (j=0;j<BUF_LINES;j++) {
        buf[j]=malloc(sizeof(JSAMPLE)*cinfo.output_width*
                                      cinfo.out_color_components);
        if (!buf[j]) no_memory();
     }

     while (cinfo.output_scanline < cinfo.output_height) {
       lines_read = jpeg_read_scanlines(&cinfo, buf,BUF_LINES);
     }

     jpeg_finish_decompress(&cinfo);
     for(j=0;j<BUF_LINES;j++) free(buf[j]);

     if (!global_error_counter) {
       if (quiet_mode < 2) printf(" [OK]\n");
     }
     else {
       if (quiet_mode < 2) printf(" [WARNING]\n");
       if (delete_mode && !del_mode) 
	 delete_file(current,verbose_mode,quiet_mode);
     }
   }
   else { /* !check_mode */
     if (quiet_mode < 2) printf("\n"); 
     jpeg_abort_decompress(&cinfo);
   }

   fclose(infile);
  
  } while (++i<argc || input_from_file);

  jpeg_destroy_decompress(&cinfo);
  free(buf);
  free(MD5);

  return (global_total_errors>0?1:0); /* return 1 if any errors found file(s)
					 we checked */
}
Beispiel #28
0
GdkPixBuf *image_load(FILE *f)
{
	int w,h,i,j;
	art_u8 *pixels=NULL, *dptr;
	unsigned char *lines[4], /* Used to expand rows, via rec_outbuf_height, from
				  the header file:
				  "* Usually rec_outbuf_height will be 1 or 2, at most 4." */
		**lptr;
	struct jpeg_decompress_struct cinfo;
	struct iojpeg_JPEG_error_mgr jerr;
	GdkPixBuf *pixbuf;

	/* setup error handler */
	cinfo.err = jpeg_std_error(&(jerr.pub));
	jerr.pub.error_exit = g_JPEGFatalErrorHandler;

	if (sigsetjmp(jerr.setjmp_buffer, 1)) {
		/* Whoops there was a jpeg error */
		if (pixels != NULL)
			art_free(pixels);
		jpeg_destroy_decompress(&cinfo);
		return NULL;
	}

	/* load header, setup */
	jpeg_create_decompress(&cinfo);
	jpeg_stdio_src(&cinfo, f);
	jpeg_read_header(&cinfo, TRUE);
	jpeg_start_decompress(&cinfo);
	cinfo.do_fancy_upsampling = FALSE;
	cinfo.do_block_smoothing = FALSE;

	w = cinfo.output_width;
	h = cinfo.output_height;
	g_print("w: %d h: %d\n", w, h);

	pixels = art_alloc(h * w * 3);
	if (pixels == NULL) {
		jpeg_destroy_decompress(&cinfo);
		return NULL;
	}
	dptr = pixels;

	/* decompress all the lines, a few at a time */

	while (cinfo.output_scanline < cinfo.output_height) {
		lptr = lines;
		for (i=0;i<cinfo.rec_outbuf_height;i++) {
			*lptr++=dptr;
			dptr+=w*3;
		}
		jpeg_read_scanlines(&cinfo, lines, cinfo.rec_outbuf_height);
		if (cinfo.output_components==1) {
			/* expand grey->colour */
			/* expand from the end of the memory down, so we can use
			   the same buffer */
			for (i=cinfo.rec_outbuf_height-1;i>=0;i--) {
				unsigned char *from, *to;
				from = lines[i]+w-1;
				to = lines[i]+w*3-3;
				for (j=w-1;j>=0;j--) {
					to[0] = from[0];
					to[1] = from[0];
					to[2] = from[0];
					to-=3;
					from--;
				}
			}
		}
	}

	jpeg_finish_decompress(&cinfo);
	jpeg_destroy_decompress(&cinfo);

	/* finish off, create the pixbuf */
	pixbuf = gdk_pixbuf_new (art_pixbuf_new_rgb (pixels, w, h, (w * 3)),
				 NULL);
	if (!pixbuf)
		art_free (pixels);
	
	return pixbuf;
}
Beispiel #29
-1
void R_LoadJPG(const char *filename, unsigned char **pic, int *width, int *height)
{
  /* This struct contains the JPEG decompression parameters and pointers to
   * working space (which is allocated as needed by the JPEG library).
   */
  struct jpeg_decompress_struct cinfo = {NULL};
  /* 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.
   */
  /* This struct represents a JPEG error handler.  It is declared separately
   * because applications often want to supply a specialized error handler
   * (see the second half of this file for an example).  But here we just
   * take the easy way out and use the standard error handler, which will
   * print a message on stderr and call exit() if compression fails.
   * Note that this struct must live as long as the main JPEG parameter
   * struct, to avoid dangling-pointer problems.
   */
  q_jpeg_error_mgr_t jerr;
  /* More stuff */
  JSAMPARRAY buffer;		/* Output row buffer */
  unsigned int row_stride;	/* physical row width in output buffer */
  unsigned int pixelcount, memcount;
  unsigned int sindex, dindex;
  byte *out;
  int len;
	union {
		byte *b;
		void *v;
	} fbuffer;
  byte  *buf;

  /* In this example we want to open the input file before doing anything else,
   * so that the setjmp() error recovery below can assume the file is open.
   * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
   * requires it in order to read binary files.
   */

  len = ri.FS_ReadFile ( ( char * ) filename, &fbuffer.v);
  if (!fbuffer.b || len < 0) {
	return;
  }

  /* Step 1: allocate and initialize JPEG decompression object */

  /* We have to set up the error handler first, in case the initialization
   * step fails.  (Unlikely, but it could happen if you are out of memory.)
   * This routine fills in the contents of struct jerr, and returns jerr's
   * address which we place into the link field in cinfo.
   */
  cinfo.err = jpeg_std_error(&jerr.pub);
  cinfo.err->error_exit = R_JPGErrorExit;
  cinfo.err->output_message = R_JPGOutputMessage;

  /* Establish the setjmp return context for R_JPGErrorExit 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);
    ri.FS_FreeFile(fbuffer.v);

    /* Append the filename to the error for easier debugging */
    ri.Printf(PRINT_ALL, ", loading file %s\n", filename);
    return;
  }

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

  /* Step 2: specify data source (eg, a file) */

  jpeg_mem_src(&cinfo, fbuffer.b, len);

  /* Step 3: read file parameters with jpeg_read_header() */

  (void) jpeg_read_header(&cinfo, TRUE);
  /* We can ignore the return value from jpeg_read_header since
   *   (a) suspension is not possible with the stdio data source, and
   *   (b) we passed TRUE to reject a tables-only JPEG file as an error.
   * See libjpeg.doc for more info.
   */

  /* Step 4: set parameters for decompression */

  /*
   * Make sure it always converts images to RGB color space. This will
   * automatically convert 8-bit greyscale images to RGB as well.
   */
  cinfo.out_color_space = JCS_RGB;

  /* Step 5: Start decompressor */

  (void) jpeg_start_decompress(&cinfo);
  /* We can ignore the return value since suspension is not possible
   * with the stdio data source.
   */

  /* 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.
   * In this example, we need to make an output work buffer of the right size.
   */ 
  /* JSAMPLEs per row in output buffer */

  pixelcount = cinfo.output_width * cinfo.output_height;

  if(!cinfo.output_width || !cinfo.output_height
      || ((pixelcount * 4) / cinfo.output_width) / 4 != cinfo.output_height
      || pixelcount > 0x1FFFFFFF || cinfo.output_components != 3
    )
  {
    // Free the memory to make sure we don't leak memory
    ri.FS_FreeFile (fbuffer.v);
    jpeg_destroy_decompress(&cinfo);
  
    ri.Error(ERR_DROP, "LoadJPG: %s has an invalid image format: %dx%d*4=%d, components: %d", filename,
		    cinfo.output_width, cinfo.output_height, pixelcount * 4, cinfo.output_components);
  }

  memcount = pixelcount * 4;
  row_stride = cinfo.output_width * cinfo.output_components;

  out = ri.Malloc(memcount);

  *width = cinfo.output_width;
  *height = cinfo.output_height;

  /* 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.
   */
  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.
     */
	buf = ((out+(row_stride*cinfo.output_scanline)));
	buffer = &buf;
    (void) jpeg_read_scanlines(&cinfo, buffer, 1);
  }
  
  buf = out;

  // Expand from RGB to RGBA
  sindex = pixelcount * cinfo.output_components;
  dindex = memcount;

  do
  {	
    buf[--dindex] = 255;
    buf[--dindex] = buf[--sindex];
    buf[--dindex] = buf[--sindex];
    buf[--dindex] = buf[--sindex];
  } while(sindex);

  *pic = out;

  /* Step 7: Finish decompression */

  jpeg_finish_decompress(&cinfo);
  /* We can ignore the return value since suspension is not possible
   * with the stdio data source.
   */

  /* Step 8: Release JPEG decompression object */

  /* This is an important step since it will release a good deal of memory. */
  jpeg_destroy_decompress(&cinfo);

  /* 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...)
   */
  ri.FS_FreeFile (fbuffer.v);

  /* 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! */
}
cairo_surface_t* guacenc_jpeg_decoder(unsigned char* data, int length) {

    struct jpeg_decompress_struct cinfo;
    struct jpeg_error_mgr jerr;

    /* Create decompressor with standard error handling */
    jpeg_create_decompress(&cinfo);
    cinfo.err = jpeg_std_error(&jerr);

    /* Read JPEG directly from memory buffer */
    jpeg_mem_src(&cinfo, data, length);

    /* Read and validate JPEG header */
    if (!jpeg_read_header(&cinfo, TRUE)) {
        guacenc_log(GUAC_LOG_WARNING, "Invalid JPEG data");
        jpeg_destroy_decompress(&cinfo);
        return NULL;
    }

    /* Begin decompression */
    cinfo.out_color_space = JCS_RGB;
    jpeg_start_decompress(&cinfo);

    /* Pull JPEG dimensions from decompressor */
    int width = cinfo.output_width;
    int height = cinfo.output_height;

    /* Allocate sufficient buffer space for one JPEG scanline */
    unsigned char* jpeg_scanline = malloc(width * 3);

    /* Create blank Cairo surface (no transparency in JPEG) */
    cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24,
            width, height);

    /* Pull underlying buffer and its stride */
    int stride = cairo_image_surface_get_stride(surface);
    unsigned char* row = cairo_image_surface_get_data(surface);

    /* Read JPEG into surface */
    while (cinfo.output_scanline < height) {

        /* Read single scanline */
        unsigned char* buffers[1] = { jpeg_scanline };
        jpeg_read_scanlines(&cinfo, buffers, 1);

        /* Copy scanline to Cairo surface */
        guacenc_jpeg_copy_scanline(row, jpeg_scanline, width);

        /* Advance to next row of Cairo surface */
        row += stride;

    }

    /* Scanline buffer is no longer needed */
    free(jpeg_scanline);

    /* End decompression */
    jpeg_finish_decompress(&cinfo);

    /* Free decompressor */
    jpeg_destroy_decompress(&cinfo);

    /* JPEG was read successfully */
    return surface;

}