diff options
Diffstat (limited to 'base/gfx/png_encoder.cc')
-rw-r--r-- | base/gfx/png_encoder.cc | 240 |
1 files changed, 0 insertions, 240 deletions
diff --git a/base/gfx/png_encoder.cc b/base/gfx/png_encoder.cc deleted file mode 100644 index 10a60c6..0000000 --- a/base/gfx/png_encoder.cc +++ /dev/null @@ -1,240 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/basictypes.h" -#include "base/gfx/png_encoder.h" -#include "base/logging.h" -#include "base/scoped_ptr.h" -#include "third_party/skia/include/core/SkBitmap.h" -#include "third_party/skia/include/core/SkUnPreMultiply.h" - -extern "C" { -#if defined(USE_SYSTEM_LIBPNG) -#include <png.h> -#else -#include "third_party/libpng/png.h" -#endif -} - -namespace { - -// Converts BGRA->RGBA and RGBA->BGRA. -void ConvertBetweenBGRAandRGBA(const unsigned char* input, int pixel_width, - unsigned char* output) { - for (int x = 0; x < pixel_width; x++) { - const unsigned char* pixel_in = &input[x * 4]; - unsigned char* pixel_out = &output[x * 4]; - pixel_out[0] = pixel_in[2]; - pixel_out[1] = pixel_in[1]; - pixel_out[2] = pixel_in[0]; - pixel_out[3] = pixel_in[3]; - } -} - -void ConvertRGBAtoRGB(const unsigned char* rgba, int pixel_width, - unsigned char* rgb) { - for (int x = 0; x < pixel_width; x++) { - const unsigned char* pixel_in = &rgba[x * 4]; - unsigned char* pixel_out = &rgb[x * 3]; - pixel_out[0] = pixel_in[0]; - pixel_out[1] = pixel_in[1]; - pixel_out[2] = pixel_in[2]; - } -} - -} // namespace - -// Encoder -------------------------------------------------------------------- -// -// This section of the code is based on nsPNGEncoder.cpp in Mozilla -// (Copyright 2005 Google Inc.) - -namespace { - -// Passed around as the io_ptr in the png structs so our callbacks know where -// to write data. -struct PngEncoderState { - PngEncoderState(std::vector<unsigned char>* o) : out(o) {} - std::vector<unsigned char>* out; -}; - -// Called by libpng to flush its internal buffer to ours. -void EncoderWriteCallback(png_structp png, png_bytep data, png_size_t size) { - PngEncoderState* state = static_cast<PngEncoderState*>(png_get_io_ptr(png)); - DCHECK(state->out); - - size_t old_size = state->out->size(); - state->out->resize(old_size + size); - memcpy(&(*state->out)[old_size], data, size); -} - -void ConvertBGRAtoRGB(const unsigned char* bgra, int pixel_width, - unsigned char* rgb) { - for (int x = 0; x < pixel_width; x++) { - const unsigned char* pixel_in = &bgra[x * 4]; - unsigned char* pixel_out = &rgb[x * 3]; - pixel_out[0] = pixel_in[2]; - pixel_out[1] = pixel_in[1]; - pixel_out[2] = pixel_in[0]; - } -} - -// Automatically destroys the given write structs on destruction to make -// cleanup and error handling code cleaner. -class PngWriteStructDestroyer { - public: - PngWriteStructDestroyer(png_struct** ps, png_info** pi) : ps_(ps), pi_(pi) { - } - ~PngWriteStructDestroyer() { - png_destroy_write_struct(ps_, pi_); - } - private: - png_struct** ps_; - png_info** pi_; - - DISALLOW_EVIL_CONSTRUCTORS(PngWriteStructDestroyer); -}; - -} // namespace - -// static -bool PNGEncoder::Encode(const unsigned char* input, ColorFormat format, - int w, int h, int row_byte_width, - bool discard_transparency, - std::vector<unsigned char>* output) { - // Run to convert an input row into the output row format, NULL means no - // conversion is necessary. - void (*converter)(const unsigned char* in, int w, unsigned char* out) = NULL; - - int input_color_components, output_color_components; - int png_output_color_type; - switch (format) { - case FORMAT_RGB: - input_color_components = 3; - output_color_components = 3; - png_output_color_type = PNG_COLOR_TYPE_RGB; - discard_transparency = false; - break; - - case FORMAT_RGBA: - input_color_components = 4; - if (discard_transparency) { - output_color_components = 3; - png_output_color_type = PNG_COLOR_TYPE_RGB; - converter = ConvertRGBAtoRGB; - } else { - output_color_components = 4; - png_output_color_type = PNG_COLOR_TYPE_RGB_ALPHA; - converter = NULL; - } - break; - - case FORMAT_BGRA: - input_color_components = 4; - if (discard_transparency) { - output_color_components = 3; - png_output_color_type = PNG_COLOR_TYPE_RGB; - converter = ConvertBGRAtoRGB; - } else { - output_color_components = 4; - png_output_color_type = PNG_COLOR_TYPE_RGB_ALPHA; - converter = ConvertBetweenBGRAandRGBA; - } - break; - - default: - NOTREACHED() << "Unknown pixel format"; - return false; - } - - // Row stride should be at least as long as the length of the data. - DCHECK(input_color_components * w <= row_byte_width); - - png_struct* png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, - png_voidp_NULL, - png_error_ptr_NULL, - png_error_ptr_NULL); - if (!png_ptr) - return false; - png_info* info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) { - png_destroy_write_struct(&png_ptr, NULL); - return false; - } - PngWriteStructDestroyer destroyer(&png_ptr, &info_ptr); - - if (setjmp(png_jmpbuf(png_ptr))) { - // The destroyer will ensure that the structures are cleaned up in this - // case, even though we may get here as a jump from random parts of the - // PNG library called below. - return false; - } - - // Set our callback for libpng to give us the data. - PngEncoderState state(output); - png_set_write_fn(png_ptr, &state, EncoderWriteCallback, NULL); - - png_set_IHDR(png_ptr, info_ptr, w, h, 8, png_output_color_type, - PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, - PNG_FILTER_TYPE_DEFAULT); - png_write_info(png_ptr, info_ptr); - - if (!converter) { - // No conversion needed, give the data directly to libpng. - for (int y = 0; y < h; y ++) - png_write_row(png_ptr, - const_cast<unsigned char*>(&input[y * row_byte_width])); - } else { - // Needs conversion using a separate buffer. - unsigned char* row = new unsigned char[w * output_color_components]; - for (int y = 0; y < h; y ++) { - converter(&input[y * row_byte_width], w, row); - png_write_row(png_ptr, row); - } - delete[] row; - } - - png_write_end(png_ptr, info_ptr); - return true; -} - -// static -bool PNGEncoder::EncodeBGRASkBitmap(const SkBitmap& input, - bool discard_transparency, - std::vector<unsigned char>* output) { - static const int bbp = 4; - - SkAutoLockPixels lock_input(input); - DCHECK(input.empty() || input.bytesPerPixel() == bbp); - - // SkBitmaps are premultiplied, we need to unpremultiply them. - scoped_array<unsigned char> divided( - new unsigned char[input.width() * input.height() * bbp]); - - int i = 0; - for (int y = 0; y < input.height(); y++) { - for (int x = 0; x < input.width(); x++) { - uint32 pixel = input.getAddr32(0, y)[x]; - - int alpha = SkColorGetA(pixel); - if (alpha != 0 && alpha != 255) { - SkColor unmultiplied = SkUnPreMultiply::PMColorToColor(pixel); - divided[i + 0] = SkColorGetR(unmultiplied); - divided[i + 1] = SkColorGetG(unmultiplied); - divided[i + 2] = SkColorGetB(unmultiplied); - divided[i + 3] = alpha; - } else { - divided[i + 0] = SkColorGetR(pixel); - divided[i + 1] = SkColorGetG(pixel); - divided[i + 2] = SkColorGetB(pixel); - divided[i + 3] = alpha; - } - i += bbp; - } - } - - return Encode(divided.get(), - PNGEncoder::FORMAT_RGBA, input.width(), input.height(), - input.width() * bbp, discard_transparency, output); -} |