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