mirror of
https://github.com/webmproject/libwebp.git
synced 2025-01-27 07:02:55 +01:00
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:
parent
d478e58960
commit
4c60f63c64
@ -155,9 +155,9 @@ static int ReadPicture(const char* const filename, WebPPicture* const pic,
|
|||||||
}
|
}
|
||||||
format = GetImageType(in_file);
|
format = GetImageType(in_file);
|
||||||
if (format == PNG_) {
|
if (format == PNG_) {
|
||||||
ok = ReadPNG(in_file, pic, keep_alpha, metadata);
|
ok = ReadPNG(filename, pic, keep_alpha, metadata);
|
||||||
} else if (format == JPEG_) {
|
} else if (format == JPEG_) {
|
||||||
ok = ReadJPEG(in_file, pic, metadata);
|
ok = ReadJPEG(filename, pic, metadata);
|
||||||
} else if (format == TIFF_) {
|
} else if (format == TIFF_) {
|
||||||
ok = ReadTIFF(filename, pic, keep_alpha, metadata);
|
ok = ReadTIFF(filename, pic, keep_alpha, metadata);
|
||||||
} else if (format == WEBP_) {
|
} else if (format == WEBP_) {
|
||||||
|
@ -19,11 +19,13 @@
|
|||||||
|
|
||||||
#ifdef WEBP_HAVE_JPEG
|
#ifdef WEBP_HAVE_JPEG
|
||||||
#include <jpeglib.h>
|
#include <jpeglib.h>
|
||||||
|
#include <jerror.h>
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "webp/encode.h"
|
#include "webp/encode.h"
|
||||||
|
#include "./example_util.h"
|
||||||
#include "./metadata.h"
|
#include "./metadata.h"
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@ -208,13 +210,64 @@ static void my_error_exit(j_common_ptr dinfo) {
|
|||||||
longjmp(myerr->setjmp_buffer, 1);
|
longjmp(myerr->setjmp_buffer, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ReadJPEG(FILE* in_file, WebPPicture* const pic, Metadata* const metadata) {
|
typedef struct {
|
||||||
int ok = 0;
|
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;
|
int stride, width, height;
|
||||||
volatile struct jpeg_decompress_struct dinfo;
|
volatile struct jpeg_decompress_struct dinfo;
|
||||||
struct my_error_mgr jerr;
|
struct my_error_mgr jerr;
|
||||||
uint8_t* volatile rgb = NULL;
|
uint8_t* volatile rgb = NULL;
|
||||||
JSAMPROW buffer[1];
|
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
|
memset((j_decompress_ptr)&dinfo, 0, sizeof(dinfo)); // for setjmp sanity
|
||||||
dinfo.err = jpeg_std_error(&jerr.pub);
|
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_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);
|
if (metadata != NULL) SaveMetadataMarkers((j_decompress_ptr)&dinfo);
|
||||||
jpeg_read_header((j_decompress_ptr)&dinfo, TRUE);
|
jpeg_read_header((j_decompress_ptr)&dinfo, TRUE);
|
||||||
|
|
||||||
@ -277,12 +330,14 @@ int ReadJPEG(FILE* in_file, WebPPicture* const pic, Metadata* const metadata) {
|
|||||||
|
|
||||||
End:
|
End:
|
||||||
free(rgb);
|
free(rgb);
|
||||||
|
free((void*)ctx.data);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
#else // !WEBP_HAVE_JPEG
|
#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) {
|
struct Metadata* const metadata) {
|
||||||
(void)in_file;
|
(void)filename;
|
||||||
(void)pic;
|
(void)pic;
|
||||||
(void)metadata;
|
(void)metadata;
|
||||||
fprintf(stderr, "JPEG support not compiled. Please install the libjpeg "
|
fprintf(stderr, "JPEG support not compiled. Please install the libjpeg "
|
||||||
|
@ -22,10 +22,11 @@ extern "C" {
|
|||||||
struct Metadata;
|
struct Metadata;
|
||||||
struct WebPPicture;
|
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.
|
// The output is RGB or YUV depending on pic->use_argb value.
|
||||||
// Returns true on success.
|
// 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);
|
struct Metadata* const metadata);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -18,12 +18,14 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#ifdef WEBP_HAVE_PNG
|
#ifdef WEBP_HAVE_PNG
|
||||||
|
#include <assert.h>
|
||||||
#include <png.h>
|
#include <png.h>
|
||||||
#include <setjmp.h> // note: this must be included *after* png.h
|
#include <setjmp.h> // note: this must be included *after* png.h
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "webp/encode.h"
|
#include "webp/encode.h"
|
||||||
|
#include "./example_util.h"
|
||||||
#include "./metadata.h"
|
#include "./metadata.h"
|
||||||
|
|
||||||
static void PNGAPI error_function(png_structp png, png_const_charp error) {
|
static void PNGAPI error_function(png_structp png, png_const_charp error) {
|
||||||
@ -188,24 +190,39 @@ static int ExtractMetadataFromPNG(png_structp png,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ReadPNG(FILE* in_file, WebPPicture* const pic, int keep_alpha,
|
typedef struct {
|
||||||
Metadata* const metadata) {
|
const uint8_t* data;
|
||||||
volatile png_structp png;
|
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 info = NULL;
|
||||||
volatile png_infop end_info = NULL;
|
volatile png_infop end_info = NULL;
|
||||||
|
PNGReadContext context = { NULL, 0, 0 };
|
||||||
int color_type, bit_depth, interlaced;
|
int color_type, bit_depth, interlaced;
|
||||||
int has_alpha;
|
int has_alpha;
|
||||||
int num_passes;
|
int num_passes;
|
||||||
int p;
|
int p;
|
||||||
int ok = 0;
|
volatile int ok = 0;
|
||||||
png_uint_32 width, height, y;
|
png_uint_32 width, height, y;
|
||||||
png_uint_32 stride;
|
png_uint_32 stride;
|
||||||
uint8_t* volatile rgb = NULL;
|
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);
|
png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
|
||||||
if (png == NULL) {
|
if (png == NULL) goto End;
|
||||||
goto End;
|
|
||||||
}
|
|
||||||
|
|
||||||
png_set_error_fn(png, 0, error_function, NULL);
|
png_set_error_fn(png, 0, error_function, NULL);
|
||||||
if (setjmp(png_jmpbuf(png))) {
|
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);
|
end_info = png_create_info_struct(png);
|
||||||
if (end_info == NULL) goto Error;
|
if (end_info == NULL) goto Error;
|
||||||
|
|
||||||
png_init_io(png, in_file);
|
png_set_read_fn(png, &context, ReadFunc);
|
||||||
png_read_info(png, info);
|
png_read_info(png, info);
|
||||||
if (!png_get_IHDR(png, info,
|
if (!png_get_IHDR(png, info,
|
||||||
&width, &height, &bit_depth, &color_type, &interlaced,
|
&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_destroy_read_struct((png_structpp)&png,
|
||||||
(png_infopp)&info, (png_infopp)&end_info);
|
(png_infopp)&info, (png_infopp)&end_info);
|
||||||
}
|
}
|
||||||
|
free((void*)context.data);
|
||||||
free(rgb);
|
free(rgb);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
#else // !WEBP_HAVE_PNG
|
#else // !WEBP_HAVE_PNG
|
||||||
int ReadPNG(FILE* in_file, struct WebPPicture* const pic, int keep_alpha,
|
int ReadPNG(const char* const filename, struct WebPPicture* const pic,
|
||||||
struct Metadata* const metadata) {
|
int keep_alpha, struct Metadata* const metadata) {
|
||||||
(void)in_file;
|
(void)filename;
|
||||||
(void)pic;
|
(void)pic;
|
||||||
(void)keep_alpha;
|
(void)keep_alpha;
|
||||||
(void)metadata;
|
(void)metadata;
|
||||||
|
@ -21,13 +21,14 @@ extern "C" {
|
|||||||
struct Metadata;
|
struct Metadata;
|
||||||
struct WebPPicture;
|
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.
|
// 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
|
// 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.
|
// or YUVA. Otherwise, alpha channel is dropped and output is RGB or YUV.
|
||||||
// Returns true on success.
|
// Returns true on success.
|
||||||
int ReadPNG(FILE* in_file, struct WebPPicture* const pic, int keep_alpha,
|
int ReadPNG(const char* const filename, struct WebPPicture* const pic,
|
||||||
struct Metadata* const metadata);
|
int keep_alpha, struct Metadata* const metadata);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user