diff --git a/examples/cwebp.c b/examples/cwebp.c index d7f8a7c0..c326bba6 100644 --- a/examples/cwebp.c +++ b/examples/cwebp.c @@ -155,9 +155,9 @@ static int ReadPicture(const char* const filename, WebPPicture* const pic, } format = GetImageType(in_file); if (format == PNG_) { - ok = ReadPNG(in_file, pic, keep_alpha, metadata); + ok = ReadPNG(filename, pic, keep_alpha, metadata); } else if (format == JPEG_) { - ok = ReadJPEG(in_file, pic, metadata); + ok = ReadJPEG(filename, pic, metadata); } else if (format == TIFF_) { ok = ReadTIFF(filename, pic, keep_alpha, metadata); } else if (format == WEBP_) { diff --git a/examples/jpegdec.c b/examples/jpegdec.c index c06da8dc..af72bfae 100644 --- a/examples/jpegdec.c +++ b/examples/jpegdec.c @@ -19,11 +19,13 @@ #ifdef WEBP_HAVE_JPEG #include +#include #include #include #include #include "webp/encode.h" +#include "./example_util.h" #include "./metadata.h" // ----------------------------------------------------------------------------- @@ -208,13 +210,64 @@ static void my_error_exit(j_common_ptr dinfo) { longjmp(myerr->setjmp_buffer, 1); } -int ReadJPEG(FILE* in_file, WebPPicture* const pic, Metadata* const metadata) { - int ok = 0; +typedef struct { + struct jpeg_source_mgr pub; + const uint8_t* data; + size_t data_size; +} JPEGReadContext; + +static void ContextInit(j_decompress_ptr cinfo) { + JPEGReadContext* const ctx = (JPEGReadContext*)cinfo->src; + ctx->pub.next_input_byte = ctx->data; + ctx->pub.bytes_in_buffer = ctx->data_size; +} + +static int ContextFill(j_decompress_ptr cinfo) { + // we shouldn't get here. + ERREXIT(cinfo, JERR_FILE_READ); + return 0; +} + +static void ContextSkip(j_decompress_ptr cinfo, long jump_size) { + JPEGReadContext* const ctx = (JPEGReadContext*)cinfo->src; + size_t jump = (size_t)jump_size; + if (jump > ctx->pub.bytes_in_buffer) { // Don't overflow the buffer. + jump = ctx->pub.bytes_in_buffer; + } + ctx->pub.bytes_in_buffer -= jump; + ctx->pub.next_input_byte += jump; +} + +static void ContextTerm(j_decompress_ptr cinfo) { + (void)cinfo; +} + +static void ContextSetup(volatile struct jpeg_decompress_struct* const cinfo, + JPEGReadContext* const ctx) { + cinfo->src = (struct jpeg_source_mgr*)ctx; + ctx->pub.init_source = ContextInit; + ctx->pub.fill_input_buffer = ContextFill; + ctx->pub.skip_input_data = ContextSkip; + ctx->pub.resync_to_restart = jpeg_resync_to_restart; + ctx->pub.term_source = ContextTerm; + ctx->pub.bytes_in_buffer = 0; + ctx->pub.next_input_byte = NULL; +} + +int ReadJPEG(const char* const filename, WebPPicture* const pic, + Metadata* const metadata) { + volatile int ok = 0; int stride, width, height; volatile struct jpeg_decompress_struct dinfo; struct my_error_mgr jerr; uint8_t* volatile rgb = NULL; JSAMPROW buffer[1]; + JPEGReadContext ctx; + + memset(&ctx, 0, sizeof(ctx)); + + ok = ExUtilReadFile(filename, &ctx.data, &ctx.data_size); + if (!ok) goto End; memset((j_decompress_ptr)&dinfo, 0, sizeof(dinfo)); // for setjmp sanity dinfo.err = jpeg_std_error(&jerr.pub); @@ -228,7 +281,7 @@ int ReadJPEG(FILE* in_file, WebPPicture* const pic, Metadata* const metadata) { } jpeg_create_decompress((j_decompress_ptr)&dinfo); - jpeg_stdio_src((j_decompress_ptr)&dinfo, in_file); + ContextSetup(&dinfo, &ctx); if (metadata != NULL) SaveMetadataMarkers((j_decompress_ptr)&dinfo); jpeg_read_header((j_decompress_ptr)&dinfo, TRUE); @@ -277,12 +330,14 @@ int ReadJPEG(FILE* in_file, WebPPicture* const pic, Metadata* const metadata) { End: free(rgb); + free((void*)ctx.data); return ok; } #else // !WEBP_HAVE_JPEG -int ReadJPEG(FILE* in_file, struct WebPPicture* const pic, +int ReadJPEG(const char* const filename, + struct WebPPicture* const pic, struct Metadata* const metadata) { - (void)in_file; + (void)filename; (void)pic; (void)metadata; fprintf(stderr, "JPEG support not compiled. Please install the libjpeg " diff --git a/examples/jpegdec.h b/examples/jpegdec.h index 799164cd..d6c126fb 100644 --- a/examples/jpegdec.h +++ b/examples/jpegdec.h @@ -22,10 +22,11 @@ extern "C" { struct Metadata; struct WebPPicture; -// Reads a JPEG from 'in_file', returning the decoded output in 'pic'. +// Reads a JPEG from 'filename', returning the decoded output in 'pic'. +// If 'filename' is equal '-', input is read from stdin. // The output is RGB or YUV depending on pic->use_argb value. // Returns true on success. -int ReadJPEG(FILE* in_file, struct WebPPicture* const pic, +int ReadJPEG(const char* const filename, struct WebPPicture* const pic, struct Metadata* const metadata); #ifdef __cplusplus diff --git a/examples/pngdec.c b/examples/pngdec.c index cb8b389a..d1439547 100644 --- a/examples/pngdec.c +++ b/examples/pngdec.c @@ -18,12 +18,14 @@ #include #ifdef WEBP_HAVE_PNG +#include #include #include // note: this must be included *after* png.h #include #include #include "webp/encode.h" +#include "./example_util.h" #include "./metadata.h" static void PNGAPI error_function(png_structp png, png_const_charp error) { @@ -188,24 +190,39 @@ static int ExtractMetadataFromPNG(png_structp png, return 1; } -int ReadPNG(FILE* in_file, WebPPicture* const pic, int keep_alpha, - Metadata* const metadata) { - volatile png_structp png; +typedef struct { + const uint8_t* data; + size_t data_size; + png_size_t offset; +} PNGReadContext; + +static void ReadFunc(png_structp png_ptr, png_bytep data, png_size_t length) { + PNGReadContext* const ctx = (PNGReadContext*)png_get_io_ptr(png_ptr); + assert(ctx->offset + length <= ctx->data_size); + memcpy(data, ctx->data + ctx->offset, length); + ctx->offset += length; +} + +int ReadPNG(const char* const filename, struct WebPPicture* const pic, + int keep_alpha, struct Metadata* const metadata) { + volatile png_structp png = NULL; volatile png_infop info = NULL; volatile png_infop end_info = NULL; + PNGReadContext context = { NULL, 0, 0 }; int color_type, bit_depth, interlaced; int has_alpha; int num_passes; int p; - int ok = 0; + volatile int ok = 0; png_uint_32 width, height, y; png_uint_32 stride; uint8_t* volatile rgb = NULL; + ok = ExUtilReadFile(filename, &context.data, &context.data_size); + if (!ok) goto End; + png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); - if (png == NULL) { - goto End; - } + if (png == NULL) goto End; png_set_error_fn(png, 0, error_function, NULL); if (setjmp(png_jmpbuf(png))) { @@ -219,7 +236,7 @@ int ReadPNG(FILE* in_file, WebPPicture* const pic, int keep_alpha, end_info = png_create_info_struct(png); if (end_info == NULL) goto Error; - png_init_io(png, in_file); + png_set_read_fn(png, &context, ReadFunc); png_read_info(png, info); if (!png_get_IHDR(png, info, &width, &height, &bit_depth, &color_type, &interlaced, @@ -282,13 +299,14 @@ int ReadPNG(FILE* in_file, WebPPicture* const pic, int keep_alpha, png_destroy_read_struct((png_structpp)&png, (png_infopp)&info, (png_infopp)&end_info); } + free((void*)context.data); free(rgb); return ok; } #else // !WEBP_HAVE_PNG -int ReadPNG(FILE* in_file, struct WebPPicture* const pic, int keep_alpha, - struct Metadata* const metadata) { - (void)in_file; +int ReadPNG(const char* const filename, struct WebPPicture* const pic, + int keep_alpha, struct Metadata* const metadata) { + (void)filename; (void)pic; (void)keep_alpha; (void)metadata; diff --git a/examples/pngdec.h b/examples/pngdec.h index 3fb16830..f04bf526 100644 --- a/examples/pngdec.h +++ b/examples/pngdec.h @@ -21,13 +21,14 @@ extern "C" { struct Metadata; struct WebPPicture; -// Reads a PNG from 'in_file', returning the decoded output in 'pic'. +// Reads a PNG from 'filename', returning the decoded output in 'pic'. +// If 'filename' is equal '-', input is read from stdin. // Output is RGBA or YUVA, depending on pic->use_argb value. // If 'keep_alpha' is true and the PNG has an alpha channel, the output is RGBA // or YUVA. Otherwise, alpha channel is dropped and output is RGB or YUV. // Returns true on success. -int ReadPNG(FILE* in_file, struct WebPPicture* const pic, int keep_alpha, - struct Metadata* const metadata); +int ReadPNG(const char* const filename, struct WebPPicture* const pic, + int keep_alpha, struct Metadata* const metadata); #ifdef __cplusplus } // extern "C"