From b6d007ac4145cd826910c41f7d7c3ee66af59c37 Mon Sep 17 00:00:00 2001 From: Alexey Vasiliev Date: Wed, 13 Mar 2013 14:38:09 +0200 Subject: [PATCH] output_format --- ext/webp_ffi/util.c | 30 ++++++++++++++++++++++++++---- ext/webp_ffi/webp_ffi.c | 4 ++++ lib/webp/c.rb | 2 +- lib/webp/options.rb | 11 +++++++++-- spec/webp_ffi_spec.rb | 12 ++++++++++++ 5 files changed, 52 insertions(+), 7 deletions(-) diff --git a/ext/webp_ffi/util.c b/ext/webp_ffi/util.c index 3a13a7f..e6aec8b 100644 --- a/ext/webp_ffi/util.c +++ b/ext/webp_ffi/util.c @@ -258,6 +258,28 @@ static int UtilWritePNG(FILE* out_file, const WebPDecBuffer* const buffer) { return 1; } +static 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; +} + static int UtilReadTIFF(const char* const filename, WebPPicture* const pic, int keep_alpha) { TIFF* const tif = TIFFOpen(filename, "r"); @@ -371,12 +393,12 @@ int UtilSaveOutput(const WebPDecBuffer* const buffer, if (format == PNG) { ok &= UtilWritePNG(fout, buffer); - } - /* } else if (format == PAM) { - ok &= WritePPM(fout, buffer, 1); + ok &= UtilWritePPM(fout, buffer, 1); } else if (format == PPM) { - ok &= WritePPM(fout, buffer, 0); + ok &= UtilWritePPM(fout, buffer, 0); + } + /* } else if (format == PGM) { ok &= WritePGM(fout, buffer); } else if (format == ALPHA_PLANE_ONLY) { diff --git a/ext/webp_ffi/webp_ffi.c b/ext/webp_ffi/webp_ffi.c index 7b9d30a..d6a3705 100644 --- a/ext/webp_ffi/webp_ffi.c +++ b/ext/webp_ffi/webp_ffi.c @@ -199,6 +199,10 @@ int webp_decode(const char *in_file, const char *out_file, const FfiWebpDecodeCo return 1; } + if (decode_config->output_format != format){ + format = decode_config->output_format; + } + VP8StatusCode status = VP8_STATUS_OK; size_t data_size = 0; const uint8_t* data = NULL; diff --git a/lib/webp/c.rb b/lib/webp/c.rb index 9bfdc08..423b1ec 100644 --- a/lib/webp/c.rb +++ b/lib/webp/c.rb @@ -1,7 +1,7 @@ module WebP module C # enum - OutputFileFormat = enum( :png, 1, + OutputFileFormat = enum( :png, 0, :pam, :ppm, :pgm, diff --git a/lib/webp/options.rb b/lib/webp/options.rb index ec16f9c..abed806 100644 --- a/lib/webp/options.rb +++ b/lib/webp/options.rb @@ -8,7 +8,6 @@ def initialize(options) def encode_pointer options_pointer = FFI::MemoryPointer.new :char, C::FfiWebpEncodeConfig.size, false options_struct = C::FfiWebpEncodeConfig.new options_pointer - # default [:lossless, :method, :target_size, :target_PSNR, :segments, :sns_strength, :filter_strength, :filter_sharpness, :filter_type, :autofilter, :alpha_compression, :alpha_filtering, @@ -17,7 +16,6 @@ def encode_pointer options_struct[key] = @user_options[key] ? @user_options[key] : -1 end encode_default(options_struct) - # users [:quality, :crop_x, :crop_y, :crop_w, :crop_h, :resize_w, :resize_h].each do |key| options_struct[key] = @user_options[key] if @user_options[key] @@ -28,6 +26,11 @@ def encode_pointer def decode_pointer options_pointer = FFI::MemoryPointer.new :char, C::FfiWebpDecodeConfig.size, false options_struct = C::FfiWebpDecodeConfig.new options_pointer + decode_default(options_struct) + # options + if @user_options[:output_format] && [:png, :pam, :ppm, :pgm, :alpha_plane_only].include?(@user_options[:output_format]) + options_struct[:output_format] = C::OutputFileFormat[@user_options[:output_format]] + end options_pointer end @@ -39,6 +42,10 @@ def encode_default(options_struct) options_struct[:crop_w] = options_struct[:crop_h] = 0 options_struct[:resize_w] = options_struct[:resize_h] = 0 end + + def decode_default(options_struct) + options_struct[:output_format] = C::OutputFileFormat[:png] + end end end diff --git a/spec/webp_ffi_spec.rb b/spec/webp_ffi_spec.rb index 58b6bbb..c572a4a 100644 --- a/spec/webp_ffi_spec.rb +++ b/spec/webp_ffi_spec.rb @@ -136,5 +136,17 @@ end end end + + context "decode with output_format" do + [:pam, :ppm].each do |output_format| + factories[:webp].each do |image| + it "#{image}.webp image to #{output_format}" do + in_filename = File.expand_path(File.join(File.dirname(__FILE__), "factories/#{image}.webp")) + out_filename = File.expand_path(File.join(@out_dir, "#{image}.#{output_format}.png")) + WebP.decode(in_filename, out_filename, output_format: output_format).should be_true + end + end + end + end end \ No newline at end of file