/* Read the jpeg from file or buffer. */ static int vips__jpeg_read( ReadJpeg *jpeg, VipsImage *out, gboolean header_only ) { /* Need to read in APP1 (EXIF metadata), APP2 (ICC profile), APP13 * (photoshop IPCT). */ jpeg_save_markers( &jpeg->cinfo, JPEG_APP0 + 1, 0xffff ); jpeg_save_markers( &jpeg->cinfo, JPEG_APP0 + 2, 0xffff ); jpeg_save_markers( &jpeg->cinfo, JPEG_APP0 + 13, 0xffff ); /* Convert! */ if( header_only ) { if( read_jpeg_header( jpeg, out ) ) return( -1 ); /* Swap width and height if we're going to rotate this image. */ if( jpeg->autorotate ) { VipsAngle angle = vips_autorot_get_angle( out ); if( angle == VIPS_ANGLE_D90 || angle == VIPS_ANGLE_D270 ) VIPS_SWAP( int, out->Xsize, out->Ysize ); /* We won't be returning an orientation tag. */ (void) vips_image_remove( out, ORIENTATION ); } }
/* Read a JPEG file into a VIPS image. */ int vips__jpeg_read_file( const char *filename, VipsImage *out, gboolean header_only, int shrink, gboolean fail ) { ReadJpeg *jpeg; int result; if( !(jpeg = readjpeg_new( out, shrink, fail )) ) return( -1 ); /* Here for longjmp() from vips__new_error_exit() during startup. */ if( setjmp( jpeg->eman.jmp ) ) { (void) readjpeg_free( jpeg ); return( -1 ); } /* Set input to file. */ if( readjpeg_file( jpeg, filename ) ) { (void) readjpeg_free( jpeg ); return( -1 ); } /* Need to read in APP1 (EXIF metadata), APP2 (ICC profile), APP13 * (photoshop IPCT). */ jpeg_save_markers( &jpeg->cinfo, JPEG_APP0 + 1, 0xffff ); jpeg_save_markers( &jpeg->cinfo, JPEG_APP0 + 2, 0xffff ); jpeg_save_markers( &jpeg->cinfo, JPEG_APP0 + 13, 0xffff ); /* Convert! */ if( header_only ) result = read_jpeg_header( jpeg, out ); else result = read_jpeg_image( jpeg, out ); /* Don't call readjpeg_free(), we're probably still live. */ return( result ); }
/** * im_bufjpeg2vips: * @buf: memory area to load * @len: size of memory area * @out: image to write * @header_only: set to just read the header * * Read a JPEG-formatted memory block into a VIPS image. It can read most * 8-bit JPEG images, including CMYK and YCbCr. * * This function is handy for processing JPEG image thumbnails. * * See also: #VipsFormat, im_jpeg2vips(). * * Returns: 0 on success, -1 on error. */ int im_bufjpeg2vips( void *buf, size_t len, IMAGE *out, gboolean header_only ) { struct jpeg_decompress_struct cinfo; ErrorManager eman; int result; gboolean invert_pels; /* Make jpeg dcompression object. */ cinfo.err = jpeg_std_error( &eman.pub ); eman.pub.error_exit = new_error_exit; eman.pub.output_message = new_output_message; eman.fp = NULL; if( setjmp( eman.jmp ) ) { /* Here for longjmp() from new_error_exit(). */ jpeg_destroy_decompress( &cinfo ); return( -1 ); } jpeg_create_decompress( &cinfo ); /* Make input. */ buf_source( &cinfo, buf, len ); /* Need to read in APP1 (EXIF metadata) and APP2 (ICC profile). */ jpeg_save_markers( &cinfo, JPEG_APP0 + 1, 0xffff ); jpeg_save_markers( &cinfo, JPEG_APP0 + 2, 0xffff ); /* Convert! */ result = read_jpeg_header( &cinfo, out, &invert_pels, 1 ); if( !header_only && !result ) result = read_jpeg_image( &cinfo, out, invert_pels ); /* Close and tidy. */ jpeg_destroy_decompress( &cinfo ); return( result ); }
/* Read a cinfo to a VIPS image. */ static int read_jpeg_image( ReadJpeg *jpeg, VipsImage *out ) { struct jpeg_decompress_struct *cinfo = &jpeg->cinfo; VipsImage **t = (VipsImage **) vips_object_local_array( VIPS_OBJECT( out ), 3 ); VipsImage *im; /* Here for longjmp() from vips__new_error_exit(). */ if( setjmp( jpeg->eman.jmp ) ) return( -1 ); t[0] = vips_image_new(); if( read_jpeg_header( jpeg, t[0] ) ) return( -1 ); jpeg_start_decompress( cinfo ); #ifdef DEBUG printf( "read_jpeg_image: starting decompress\n" ); #endif /*DEBUG*/ if( vips_image_generate( t[0], NULL, read_jpeg_generate, NULL, jpeg, NULL ) || vips_sequential( t[0], &t[1], "tile_height", 8, "access", jpeg->readbehind ? VIPS_ACCESS_SEQUENTIAL : VIPS_ACCESS_SEQUENTIAL_UNBUFFERED, NULL ) ) return( -1 ); im = t[1]; if( jpeg->autorotate ) im = read_jpeg_rotate( VIPS_OBJECT( out ), im ); if( vips_image_write( im, out ) ) return( -1 ); return( 0 ); }
/* Read a cinfo to a VIPS image. */ static int read_jpeg_image( ReadJpeg *jpeg, VipsImage *out ) { struct jpeg_decompress_struct *cinfo = &jpeg->cinfo; VipsImage **t = (VipsImage **) vips_object_local_array( VIPS_OBJECT( out ), 3 ); /* Here for longjmp() from vips__new_error_exit(). */ if( setjmp( jpeg->eman.jmp ) ) return( -1 ); t[0] = vips_image_new(); if( read_jpeg_header( jpeg, t[0] ) ) return( -1 ); /* Set decompressing to make readjpeg_free() call * jpeg_stop_decompress(). */ jpeg_start_decompress( cinfo ); jpeg->decompressing = TRUE; #ifdef DEBUG printf( "read_jpeg_image: starting decompress\n" ); #endif /*DEBUG*/ if( vips_image_generate( t[0], NULL, read_jpeg_generate, NULL, jpeg, NULL ) || vips_sequential( t[0], &t[1], "tile_height", 8, NULL ) || vips_image_write( t[1], out ) ) return( -1 ); return( 0 ); }
int vips__jpeg_read_buffer( void *buf, size_t len, VipsImage *out, gboolean header_only, int shrink, int fail ) { ReadJpeg *jpeg; int result; if( !(jpeg = readjpeg_new( out, shrink, fail )) ) return( -1 ); if( setjmp( jpeg->eman.jmp ) ) { (void) readjpeg_free( jpeg ); return( -1 ); } /* Set input to buffer. */ readjpeg_buffer( jpeg, buf, len ); /* Need to read in APP1 (EXIF metadata) and APP2 (ICC profile). */ jpeg_save_markers( &jpeg->cinfo, JPEG_APP0 + 1, 0xffff ); jpeg_save_markers( &jpeg->cinfo, JPEG_APP0 + 2, 0xffff ); /* Convert! */ if( header_only ) result = read_jpeg_header( jpeg, out ); else result = read_jpeg_image( jpeg, out ); /* Don't call readjpeg_free(), we're probably still live. */ return( result ); }
/* Read a JPEG file into a VIPS image. */ static int jpeg2vips( const char *name, IMAGE *out, gboolean header_only ) { char filename[FILENAME_MAX]; char mode[FILENAME_MAX]; char *p, *q; int shrink; struct jpeg_decompress_struct cinfo; ErrorManager eman; FILE *fp; int result; gboolean invert_pels; gboolean fail_on_warn; /* By default, we ignore any warnings. We want to get as much of * the user's data as we can. */ fail_on_warn = FALSE; /* Parse the filename. */ im_filename_split( name, filename, mode ); p = &mode[0]; shrink = 1; if( (q = im_getnextoption( &p )) ) { shrink = atoi( q ); if( shrink != 1 && shrink != 2 && shrink != 4 && shrink != 8 ) { im_error( "im_jpeg2vips", _( "bad shrink factor %d" ), shrink ); return( -1 ); } } if( (q = im_getnextoption( &p )) ) { if( im_isprefix( "fail", q ) ) fail_on_warn = TRUE; } /* Make jpeg dcompression object. */ cinfo.err = jpeg_std_error( &eman.pub ); eman.pub.error_exit = new_error_exit; eman.pub.output_message = new_output_message; eman.fp = NULL; if( setjmp( eman.jmp ) ) { /* Here for longjmp() from new_error_exit(). */ jpeg_destroy_decompress( &cinfo ); return( -1 ); } jpeg_create_decompress( &cinfo ); /* Make input. */ if( !(fp = im__file_open_read( filename, NULL, FALSE )) ) return( -1 ); eman.fp = fp; jpeg_stdio_src( &cinfo, fp ); /* Need to read in APP1 (EXIF metadata) and APP2 (ICC profile). */ jpeg_save_markers( &cinfo, JPEG_APP0 + 1, 0xffff ); jpeg_save_markers( &cinfo, JPEG_APP0 + 2, 0xffff ); /* Convert! */ result = read_jpeg_header( &cinfo, out, &invert_pels, shrink ); if( !header_only && !result ) result = read_jpeg_image( &cinfo, out, invert_pels ); /* Close and tidy. */ fclose( fp ); eman.fp = NULL; jpeg_destroy_decompress( &cinfo ); if( eman.pub.num_warnings != 0 ) { if( fail_on_warn ) { im_error( "im_jpeg2vips", "%s", im_error_buffer() ); result = -1; } else { im_warn( "im_jpeg2vips", _( "read gave %ld warnings" ), eman.pub.num_warnings ); im_warn( "im_jpeg2vips", "%s", im_error_buffer() ); } } return( result ); }