Skip to content

Commit

Permalink
split code by files
Browse files Browse the repository at this point in the history
  • Loading branch information
le0pard committed Jul 5, 2014
1 parent 7c7fe75 commit bd62334
Show file tree
Hide file tree
Showing 7 changed files with 557 additions and 470 deletions.
80 changes: 80 additions & 0 deletions ext/webp_ffi/jpegdec.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#include "./jpegdec.h"

#include <stdio.h>
#include <jpeglib.h>
#include <setjmp.h>
#include <stdlib.h>
#include <string.h>

struct my_error_mgr {
struct jpeg_error_mgr pub;
jmp_buf setjmp_buffer;
};

static void my_error_exit(j_common_ptr dinfo) {
struct my_error_mgr* myerr = (struct my_error_mgr*) dinfo->err;
(*dinfo->err->output_message) (dinfo);
longjmp(myerr->setjmp_buffer, 1);
}

int UtilReadJPEG(FILE* in_file, WebPPicture* const pic) {
int ok = 0;
int stride, width, height;
uint8_t* rgb = NULL;
struct jpeg_decompress_struct dinfo;
struct my_error_mgr jerr;
JSAMPROW buffer[1];

dinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = my_error_exit;

if (setjmp(jerr.setjmp_buffer)) {
Error:
jpeg_destroy_decompress(&dinfo);
goto End;
}

jpeg_create_decompress(&dinfo);
jpeg_stdio_src(&dinfo, in_file);
jpeg_read_header(&dinfo, TRUE);

dinfo.out_color_space = JCS_RGB;
dinfo.do_fancy_upsampling = TRUE;

jpeg_start_decompress(&dinfo);

if (dinfo.output_components != 3) {
goto Error;
}

width = dinfo.output_width;
height = dinfo.output_height;
stride = dinfo.output_width * dinfo.output_components * sizeof(*rgb);

rgb = (uint8_t*)malloc(stride * height);
if (rgb == NULL) {
goto End;
}
buffer[0] = (JSAMPLE*)rgb;

while (dinfo.output_scanline < dinfo.output_height) {
if (jpeg_read_scanlines(&dinfo, buffer, 1) != 1) {
goto End;
}
buffer[0] += stride;
}

jpeg_finish_decompress(&dinfo);
jpeg_destroy_decompress(&dinfo);

// WebP conversion.
pic->width = width;
pic->height = height;
ok = WebPPictureImportRGB(pic, rgb, stride);
if (!ok) goto Error;

End:
free(rgb);
return ok;
}

17 changes: 17 additions & 0 deletions ext/webp_ffi/jpegdec.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#include <stdio.h>

#include "webp/encode.h"
#include "webp/decode.h"

#ifdef __cplusplus
extern "C" {
#endif

// Reads a JPEG from 'in_file', returning the decoded output in 'pic'.
// The output is RGB.
// Returns true on success.
int UtilReadJPEG(FILE* in_file, struct WebPPicture* const pic);

#ifdef __cplusplus
} // extern "C"
#endif
212 changes: 212 additions & 0 deletions ext/webp_ffi/pngdec.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
#include "./pngdec.h"

#include <assert.h>
#include <stdio.h>
#include <png.h>
#include <setjmp.h> // note: this must be included *after* png.h
#include <stdlib.h>
#include <string.h>

static void PNGAPI error_function(png_structp png, png_const_charp dummy) {
(void)dummy; // remove variable-unused warning
longjmp(png_jmpbuf(png), 1);
}

int UtilReadPNG(FILE* in_file, WebPPicture* const pic, int keep_alpha) {
png_structp png;
png_infop info = NULL;
png_infop end_info = NULL;
int color_type, bit_depth, interlaced;
int has_alpha;
int num_passes;
int p;
int ok = 0;
png_uint_32 width, height, y;
int stride;
uint8_t* rgb = NULL;

png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
if (png == NULL) {
goto End;
}

png_set_error_fn(png, 0, error_function, NULL);
if (setjmp(png_jmpbuf(png))) {
Error:
png_destroy_read_struct(&png, &info, &end_info);
goto End;
}

info = png_create_info_struct(png);
if (info == NULL) goto Error;
end_info = png_create_info_struct(png);
if (end_info == NULL) goto Error;

png_init_io(png, in_file);
png_read_info(png, info);
if (!png_get_IHDR(png, info,
&width, &height, &bit_depth, &color_type, &interlaced,
NULL, NULL)) goto Error;

png_set_strip_16(png);
png_set_packing(png);
if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png);
if (color_type == PNG_COLOR_TYPE_GRAY ||
color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
if (bit_depth < 8) {
png_set_expand_gray_1_2_4_to_8(png);
}
png_set_gray_to_rgb(png);
}
if (png_get_valid(png, info, PNG_INFO_tRNS)) {
png_set_tRNS_to_alpha(png);
has_alpha = 1;
} else {
has_alpha = !!(color_type & PNG_COLOR_MASK_ALPHA);
}

if (!keep_alpha) {
png_set_strip_alpha(png);
has_alpha = 0;
}

num_passes = png_set_interlace_handling(png);
png_read_update_info(png, info);
stride = (has_alpha ? 4 : 3) * width * sizeof(*rgb);
rgb = (uint8_t*)malloc(stride * height);
if (rgb == NULL) goto Error;
for (p = 0; p < num_passes; ++p) {
for (y = 0; y < height; ++y) {
png_bytep row = rgb + y * stride;
png_read_rows(png, &row, NULL, 1);
}
}
png_read_end(png, end_info);
png_destroy_read_struct(&png, &info, &end_info);

pic->width = width;
pic->height = height;
pic->use_argb = 1;
ok = has_alpha ? WebPPictureImportRGBA(pic, rgb, stride)
: WebPPictureImportRGB(pic, rgb, stride);

if (!ok) {
goto Error;
}

End:
free(rgb);
return ok;
}





int UtilWritePNG(FILE* out_file, const WebPDecBuffer* const buffer) {
const uint32_t width = buffer->width;
const uint32_t height = buffer->height;
unsigned char* const rgb = buffer->u.RGBA.rgba;
const int stride = buffer->u.RGBA.stride;
const int has_alpha = (buffer->colorspace == MODE_RGBA);
png_structp png;
png_infop info;
png_uint_32 y;

png = png_create_write_struct(PNG_LIBPNG_VER_STRING,
NULL, error_function, NULL);
if (png == NULL) {
return 0;
}
info = png_create_info_struct(png);
if (info == NULL) {
png_destroy_write_struct(&png, NULL);
return 0;
}
if (setjmp(png_jmpbuf(png))) {
png_destroy_write_struct(&png, &info);
return 0;
}
png_init_io(png, out_file);
png_set_IHDR(png, info, width, height, 8,
has_alpha ? PNG_COLOR_TYPE_RGBA : PNG_COLOR_TYPE_RGB,
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT);
png_write_info(png, info);
for (y = 0; y < height; ++y) {
png_bytep row = rgb + y * stride;
png_write_rows(png, &row, 1);
}
png_write_end(png, info);
png_destroy_write_struct(&png, &info);
return 1;
}


int UtilWritePPM(FILE* fout, const WebPDecBuffer* const buffer, int alpha) {
const uint32_t width = buffer->width;
const uint32_t height = buffer->height;
const unsigned char* const rgb = buffer->u.RGBA.rgba;
const int stride = buffer->u.RGBA.stride;
const size_t bytes_per_px = alpha ? 4 : 3;
uint32_t y;

if (alpha) {
fprintf(fout, "P7\nWIDTH %d\nHEIGHT %d\nDEPTH 4\nMAXVAL 255\n"
"TUPLTYPE RGB_ALPHA\nENDHDR\n", width, height);
} else {
fprintf(fout, "P6\n%d %d\n255\n", width, height);
}
for (y = 0; y < height; ++y) {
if (fwrite(rgb + y * stride, width, bytes_per_px, fout) != bytes_per_px) {
return 0;
}
}
return 1;
}

int UtilWriteAlphaPlane(FILE* fout, const WebPDecBuffer* const buffer) {
const uint32_t width = buffer->width;
const uint32_t height = buffer->height;
const unsigned char* const a = buffer->u.YUVA.a;
const int a_stride = buffer->u.YUVA.a_stride;
uint32_t y;
assert(a != NULL);
fprintf(fout, "P5\n%d %d\n255\n", width, height);
for (y = 0; y < height; ++y) {
if (fwrite(a + y * a_stride, width, 1, fout) != 1) {
return 0;
}
}
return 1;
}

int UtilWritePGM(FILE* fout, const WebPDecBuffer* const buffer) {
const int width = buffer->width;
const int height = buffer->height;
const WebPYUVABuffer* const yuv = &buffer->u.YUVA;
// Save a grayscale PGM file using the IMC4 layout
// (http://www.fourcc.org/yuv.php#IMC4). This is a very
// convenient format for viewing the samples, esp. for
// odd dimensions.
int ok = 1;
int y;
const int uv_width = (width + 1) / 2;
const int uv_height = (height + 1) / 2;
const int out_stride = (width + 1) & ~1;
const int a_height = yuv->a ? height : 0;
fprintf(fout, "P5\n%d %d\n255\n", out_stride, height + uv_height + a_height);
for (y = 0; ok && y < height; ++y) {
ok &= (fwrite(yuv->y + y * yuv->y_stride, width, 1, fout) == 1);
if (width & 1) fputc(0, fout); // padding byte
}
for (y = 0; ok && y < uv_height; ++y) {
ok &= (fwrite(yuv->u + y * yuv->u_stride, uv_width, 1, fout) == 1);
ok &= (fwrite(yuv->v + y * yuv->v_stride, uv_width, 1, fout) == 1);
}
for (y = 0; ok && y < a_height; ++y) {
ok &= (fwrite(yuv->a + y * yuv->a_stride, width, 1, fout) == 1);
if (width & 1) fputc(0, fout); // padding byte
}
return ok;
}
24 changes: 24 additions & 0 deletions ext/webp_ffi/pngdec.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include <stdio.h>
#include <stdlib.h>

#include "webp/encode.h"
#include "webp/decode.h"

#ifdef __cplusplus
extern "C" {
#endif

// Reads a PNG from 'in_file', returning the decoded output in 'pic'.
// If 'keep_alpha' is true and the PNG has an alpha channel, the output is RGBA
// otherwise it will be RGB.
// Returns true on success.
int UtilReadPNG(FILE* in_file, struct WebPPicture* const pic, int keep_alpha);

int UtilWritePNG(FILE* out_file, const WebPDecBuffer* const buffer);
int UtilWritePPM(FILE* fout, const WebPDecBuffer* const buffer, int alpha);
int UtilWriteAlphaPlane(FILE* fout, const WebPDecBuffer* const buffer);
int UtilWritePGM(FILE* fout, const WebPDecBuffer* const buffer);

#ifdef __cplusplus
} // extern "C"
#endif
Loading

0 comments on commit bd62334

Please sign in to comment.