make ReadPNG and ReadJPEG take a filename instead of a FILE

-> read is a bit slower (memory allocation and such) than reading directly from disk.

-> we're not yet ready to accept stdin as input (-- -) because we still need to guess
the file type with GetImageType(). And since we can't rewind on stdin, this will need
a bit more work before being able to read from stdin.

Change-Id: I6491fac4b07d28d1854518325ead88669656ddbf
This commit is contained in:
Pascal Massimino 2015-12-06 09:23:17 +01:00
parent d478e58960
commit 4c60f63c64
5 changed files with 98 additions and 23 deletions

View File

@ -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_) {

View File

@ -19,11 +19,13 @@
#ifdef WEBP_HAVE_JPEG
#include <jpeglib.h>
#include <jerror.h>
#include <setjmp.h>
#include <stdlib.h>
#include <string.h>
#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 "

View File

@ -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

View File

@ -18,12 +18,14 @@
#include <stdio.h>
#ifdef WEBP_HAVE_PNG
#include <assert.h>
#include <png.h>
#include <setjmp.h> // note: this must be included *after* png.h
#include <stdlib.h>
#include <string.h>
#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;

View File

@ -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"