Created
June 26, 2014 09:42
-
-
Save c4pt0r/4758304c22673d909492 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <png.h> | |
#include <webp/encode.h> | |
#include <webp/mux.h> | |
static void PNGAPI error_function(png_structp png, png_const_charp dummy) { | |
(void)dummy; // remove variable-unused warning | |
longjmp(png_jmpbuf(png), 1); | |
} | |
/* read png file into webpicture */ | |
static int ReadPNG(FILE* in_file, WebPPicture* const pic, int keep_alpha) { | |
png_structp png; | |
png_infop info; | |
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, NULL, NULL); | |
free(rgb); | |
goto End; | |
} | |
info = png_create_info_struct(png); | |
if (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; | |
} | |
if (keep_alpha && has_alpha) { | |
pic->colorspace |= WEBP_CSP_ALPHA_BIT; | |
} | |
num_passes = png_set_interlace_handling(png); | |
png_read_update_info(png, info); | |
stride = ((keep_alpha && 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, info); | |
png_destroy_read_struct(&png, &info, NULL); | |
pic->width = width; | |
pic->height = height; | |
ok = (keep_alpha && has_alpha) ? | |
WebPPictureImportRGBA(pic, rgb, stride) : | |
WebPPictureImportRGB(pic, rgb, stride); | |
free(rgb); | |
End: | |
return ok; | |
} | |
static int FileWriter(const uint8_t* data, size_t data_size, | |
const WebPPicture* const pic) { | |
FILE* const out = (FILE*)pic->custom_ptr; | |
return data_size ? (fwrite(data, data_size, 1, out) == 1) : 1; | |
} | |
int PNG2WebP(const char* in, int q, uint8_t** out, size_t* out_sz) { | |
WebPPicture picture; | |
WebPConfig config; | |
WebPAuxStats stats; | |
WebPMemoryWriter memory_writer; | |
WebPMux* mux = NULL; | |
WebPMux* mux_single = NULL; | |
FILE* in_file; | |
FILE* out_file; | |
int keep_alpha = 1; | |
int alpha_q = 100; | |
int alpha_method = 1; | |
uint8_t* compressed_alpha = NULL; | |
size_t compressed_alpha_size = 0; | |
uint8_t* compressed_rgb = NULL; | |
size_t compressed_rgb_size = 0; | |
int ret = 0; | |
if (!WebPPictureInit(&picture) || !WebPConfigInit(&config)) { | |
ret = -1; | |
goto Error; | |
} | |
config.quality = q; | |
in_file = fopen(in, "rb"); | |
if (!ReadPNG(in_file, &picture, keep_alpha)) { | |
ret = -2; | |
goto Error; | |
} | |
WebPMemoryWriterInit(&memory_writer); | |
picture.writer = WebPMemoryWrite; | |
picture.custom_ptr = (void*)&memory_writer; | |
//out_file = fopen("out.webp", "wb"); | |
//picture.writer = FileWriter; | |
//picture.custom_ptr = (void*)out_file; | |
if (!WebPEncode(&config, &picture)) { | |
ret = -3; | |
goto Error; | |
} | |
*out_sz = memory_writer.size; | |
*out = (uint8_t*)malloc(memory_writer.size); | |
memcpy(*out, memory_writer.mem, memory_writer.size); | |
Error: | |
WebPPictureFree(&picture); | |
fclose(in_file); | |
return ret; | |
} | |
int main(int argc, const char *argv[]) { | |
uint8_t* out = NULL; | |
size_t sz = 0; | |
if (PNG2WebP(argv[1], 90, &out, &sz) == 0) { | |
printf("%ld", sz); | |
free(out); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment