Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(903)

Unified Diff: sky/tools/imagediff/image_diff_png.cc

Issue 801443002: Add image_diff from the chromium repo. (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « sky/tools/imagediff/image_diff_png.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sky/tools/imagediff/image_diff_png.cc
diff --git a/ui/gfx/codec/png_codec.cc b/sky/tools/imagediff/image_diff_png.cc
similarity index 53%
copy from ui/gfx/codec/png_codec.cc
copy to sky/tools/imagediff/image_diff_png.cc
index 068a193b334cb7317a4a7eff673c7b4336bb0475..e9d98c8c907a421d4c1d1a884a428dbe1c4294a0 100644
--- a/ui/gfx/codec/png_codec.cc
+++ b/sky/tools/imagediff/image_diff_png.cc
@@ -1,23 +1,46 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2013 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 "ui/gfx/codec/png_codec.h"
+#include "sky/tools/imagediff/image_diff_png.h"
+
+#include <stdlib.h>
+#include <string.h>
#include "base/logging.h"
-#include "base/strings/string_util.h"
+#include "build/build_config.h"
#include "third_party/libpng/png.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "third_party/skia/include/core/SkColorPriv.h"
-#include "third_party/skia/include/core/SkUnPreMultiply.h"
#include "third_party/zlib/zlib.h"
-#include "ui/gfx/size.h"
-#include "ui/gfx/skia_util.h"
-namespace gfx {
+namespace image_diff_png {
+// This is a duplicate of ui/gfx/codec/png_codec.cc, after removing code related
+// to Skia, that we can use when running layout tests with minimal dependencies.
namespace {
+enum ColorFormat {
+ // 3 bytes per pixel (packed), in RGB order regardless of endianness.
+ // This is the native JPEG format.
+ FORMAT_RGB,
+
+ // 4 bytes per pixel, in RGBA order in memory regardless of endianness.
+ FORMAT_RGBA,
+
+ // 4 bytes per pixel, in BGRA order in memory regardless of endianness.
+ // This is the default Windows DIB order.
+ FORMAT_BGRA,
+
+ // 4 bytes per pixel, in pre-multiplied kARGB_8888_Config format. For use
+ // with directly writing to a skia bitmap.
+ FORMAT_SkBitmap
+};
+
+// Represents a comment in the tEXt ancillary chunk of the png.
+struct Comment {
+ std::string key;
+ std::string text;
+};
+
// Converts BGRA->RGBA and RGBA->BGRA.
void ConvertBetweenBGRAandRGBA(const unsigned char* input, int pixel_width,
unsigned char* output, bool* is_opaque) {
@@ -33,35 +56,15 @@ void ConvertBetweenBGRAandRGBA(const unsigned char* input, int pixel_width,
void ConvertRGBAtoRGB(const unsigned char* rgba, int pixel_width,
unsigned char* rgb, bool* is_opaque) {
- for (int x = 0; x < pixel_width; x++)
- memcpy(&rgb[x * 3], &rgba[x * 4], 3);
-}
-
-void ConvertSkiaToRGB(const unsigned char* skia, int pixel_width,
- unsigned char* rgb, bool* is_opaque) {
for (int x = 0; x < pixel_width; x++) {
- const uint32_t pixel_in = *reinterpret_cast<const uint32_t*>(&skia[x * 4]);
+ const unsigned char* pixel_in = &rgba[x * 4];
unsigned char* pixel_out = &rgb[x * 3];
-
- int alpha = SkGetPackedA32(pixel_in);
- if (alpha != 0 && alpha != 255) {
- SkColor unmultiplied = SkUnPreMultiply::PMColorToColor(pixel_in);
- pixel_out[0] = SkColorGetR(unmultiplied);
- pixel_out[1] = SkColorGetG(unmultiplied);
- pixel_out[2] = SkColorGetB(unmultiplied);
- } else {
- pixel_out[0] = SkGetPackedR32(pixel_in);
- pixel_out[1] = SkGetPackedG32(pixel_in);
- pixel_out[2] = SkGetPackedB32(pixel_in);
- }
+ pixel_out[0] = pixel_in[0];
+ pixel_out[1] = pixel_in[1];
+ pixel_out[2] = pixel_in[2];
}
}
-void ConvertSkiaToRGBA(const unsigned char* skia, int pixel_width,
- unsigned char* rgba, bool* is_opaque) {
- gfx::ConvertSkiaToRGBA(skia, pixel_width, rgba);
-}
-
} // namespace
// Decoder --------------------------------------------------------------------
@@ -79,77 +82,61 @@ const double kInverseGamma = 1.0 / kDefaultGamma;
class PngDecoderState {
public:
// Output is a vector<unsigned char>.
- PngDecoderState(PNGCodec::ColorFormat ofmt, std::vector<unsigned char>* o)
+ PngDecoderState(ColorFormat ofmt, std::vector<unsigned char>* o)
: output_format(ofmt),
output_channels(0),
- bitmap(NULL),
is_opaque(true),
output(o),
+ row_converter(NULL),
width(0),
height(0),
done(false) {
}
- // Output is an SkBitmap.
- explicit PngDecoderState(SkBitmap* skbitmap)
- : output_format(PNGCodec::FORMAT_SkBitmap),
- output_channels(0),
- bitmap(skbitmap),
- is_opaque(true),
- output(NULL),
- width(0),
- height(0),
- done(false) {
- }
-
- PNGCodec::ColorFormat output_format;
+ ColorFormat output_format;
int output_channels;
- // An incoming SkBitmap to write to. If NULL, we write to output instead.
- SkBitmap* bitmap;
-
// Used during the reading of an SkBitmap. Defaults to true until we see a
// pixel with anything other than an alpha of 255.
bool is_opaque;
- // The other way to decode output, where we write into an intermediary buffer
- // instead of directly to an SkBitmap.
+ // An intermediary buffer for decode output.
std::vector<unsigned char>* output;
+ // Called to convert a row from the library to the correct output format.
+ // When NULL, no conversion is necessary.
+ void (*row_converter)(const unsigned char* in, int w, unsigned char* out,
+ bool* is_opaque);
+
// Size of the image, set in the info callback.
int width;
int height;
// Set to true when we've found the end of the data.
bool done;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(PngDecoderState);
};
-// User transform (passed to libpng) which converts a row decoded by libpng to
-// Skia format. Expects the row to have 4 channels, otherwise there won't be
-// enough room in |data|.
-void ConvertRGBARowToSkia(png_structp png_ptr,
- png_row_infop row_info,
- png_bytep data) {
- const int channels = row_info->channels;
- DCHECK_EQ(channels, 4);
-
- PngDecoderState* state =
- static_cast<PngDecoderState*>(png_get_user_transform_ptr(png_ptr));
- DCHECK(state) << "LibPNG user transform pointer is NULL";
-
- unsigned char* const end = data + row_info->rowbytes;
- for (unsigned char* p = data; p < end; p += channels) {
- uint32_t* sk_pixel = reinterpret_cast<uint32_t*>(p);
- const unsigned char alpha = p[channels - 1];
- if (alpha != 255) {
- state->is_opaque = false;
- *sk_pixel = SkPreMultiplyARGB(alpha, p[0], p[1], p[2]);
- } else {
- *sk_pixel = SkPackARGB32(alpha, p[0], p[1], p[2]);
- }
+void ConvertRGBtoRGBA(const unsigned char* rgb, int pixel_width,
+ unsigned char* rgba, bool* is_opaque) {
+ for (int x = 0; x < pixel_width; x++) {
+ const unsigned char* pixel_in = &rgb[x * 3];
+ unsigned char* pixel_out = &rgba[x * 4];
+ pixel_out[0] = pixel_in[0];
+ pixel_out[1] = pixel_in[1];
+ pixel_out[2] = pixel_in[2];
+ pixel_out[3] = 0xff;
+ }
+}
+
+void ConvertRGBtoBGRA(const unsigned char* rgb, int pixel_width,
+ unsigned char* bgra, bool* is_opaque) {
+ for (int x = 0; x < pixel_width; x++) {
+ const unsigned char* pixel_in = &rgb[x * 3];
+ unsigned char* pixel_out = &bgra[x * 4];
+ pixel_out[0] = pixel_in[2];
+ pixel_out[1] = pixel_in[1];
+ pixel_out[2] = pixel_in[0];
+ pixel_out[3] = 0xff;
}
}
@@ -160,7 +147,7 @@ void DecodeInfoCallback(png_struct* png_ptr, png_info* info_ptr) {
png_get_progressive_ptr(png_ptr));
int bit_depth, color_type, interlace_type, compression_type;
- int filter_type;
+ int filter_type, channels;
png_uint_32 w, h;
png_get_IHDR(png_ptr, info_ptr, &w, &h, &bit_depth, &color_type,
&interlace_type, &compression_type, &filter_type);
@@ -177,68 +164,19 @@ void DecodeInfoCallback(png_struct* png_ptr, png_info* info_ptr) {
state->width = static_cast<int>(w);
state->height = static_cast<int>(h);
- // The following png_set_* calls have to be done in the order dictated by
- // the libpng docs. Please take care if you have to move any of them. This
- // is also why certain things are done outside of the switch, even though
- // they look like they belong there.
-
// Expand to ensure we use 24-bit for RGB and 32-bit for RGBA.
if (color_type == PNG_COLOR_TYPE_PALETTE ||
(color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8))
png_set_expand(png_ptr);
- // The '!= 0' is for silencing a Windows compiler warning.
- bool input_has_alpha = ((color_type & PNG_COLOR_MASK_ALPHA) != 0);
-
// Transparency for paletted images.
- if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
+ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
png_set_expand(png_ptr);
- input_has_alpha = true;
- }
// Convert 16-bit to 8-bit.
if (bit_depth == 16)
png_set_strip_16(png_ptr);
- // Pick our row format converter necessary for this data.
- if (!input_has_alpha) {
- switch (state->output_format) {
- case PNGCodec::FORMAT_RGB:
- state->output_channels = 3;
- break;
- case PNGCodec::FORMAT_RGBA:
- state->output_channels = 4;
- png_set_add_alpha(png_ptr, 0xFF, PNG_FILLER_AFTER);
- break;
- case PNGCodec::FORMAT_BGRA:
- state->output_channels = 4;
- png_set_bgr(png_ptr);
- png_set_add_alpha(png_ptr, 0xFF, PNG_FILLER_AFTER);
- break;
- case PNGCodec::FORMAT_SkBitmap:
- state->output_channels = 4;
- png_set_add_alpha(png_ptr, 0xFF, PNG_FILLER_AFTER);
- break;
- }
- } else {
- switch (state->output_format) {
- case PNGCodec::FORMAT_RGB:
- state->output_channels = 3;
- png_set_strip_alpha(png_ptr);
- break;
- case PNGCodec::FORMAT_RGBA:
- state->output_channels = 4;
- break;
- case PNGCodec::FORMAT_BGRA:
- state->output_channels = 4;
- png_set_bgr(png_ptr);
- break;
- case PNGCodec::FORMAT_SkBitmap:
- state->output_channels = 4;
- break;
- }
- }
-
// Expand grayscale to RGB.
if (color_type == PNG_COLOR_TYPE_GRAY ||
color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
@@ -256,49 +194,79 @@ void DecodeInfoCallback(png_struct* png_ptr, png_info* info_ptr) {
png_set_gamma(png_ptr, kDefaultGamma, kInverseGamma);
}
- // Setting the user transforms here (as opposed to inside the switch above)
- // because all png_set_* calls need to be done in the specific order
- // mandated by libpng.
- if (state->output_format == PNGCodec::FORMAT_SkBitmap) {
- png_set_read_user_transform_fn(png_ptr, ConvertRGBARowToSkia);
- png_set_user_transform_info(png_ptr, state, 0, 0);
- }
-
// Tell libpng to send us rows for interlaced pngs.
if (interlace_type == PNG_INTERLACE_ADAM7)
png_set_interlace_handling(png_ptr);
+ // Update our info now
png_read_update_info(png_ptr, info_ptr);
+ channels = png_get_channels(png_ptr, info_ptr);
- if (state->bitmap) {
- state->bitmap->allocN32Pixels(state->width, state->height);
- } else if (state->output) {
- state->output->resize(
- state->width * state->output_channels * state->height);
+ // Pick our row format converter necessary for this data.
+ if (channels == 3) {
+ switch (state->output_format) {
+ case FORMAT_RGB:
+ state->row_converter = NULL; // no conversion necessary
+ state->output_channels = 3;
+ break;
+ case FORMAT_RGBA:
+ state->row_converter = &ConvertRGBtoRGBA;
+ state->output_channels = 4;
+ break;
+ case FORMAT_BGRA:
+ state->row_converter = &ConvertRGBtoBGRA;
+ state->output_channels = 4;
+ break;
+ default:
+ NOTREACHED() << "Unknown output format";
+ break;
+ }
+ } else if (channels == 4) {
+ switch (state->output_format) {
+ case FORMAT_RGB:
+ state->row_converter = &ConvertRGBAtoRGB;
+ state->output_channels = 3;
+ break;
+ case FORMAT_RGBA:
+ state->row_converter = NULL; // no conversion necessary
+ state->output_channels = 4;
+ break;
+ case FORMAT_BGRA:
+ state->row_converter = &ConvertBetweenBGRAandRGBA;
+ state->output_channels = 4;
+ break;
+ default:
+ NOTREACHED() << "Unknown output format";
+ break;
+ }
+ } else {
+ NOTREACHED() << "Unknown input channels";
+ longjmp(png_jmpbuf(png_ptr), 1);
}
+
+ state->output->resize(
+ state->width * state->output_channels * state->height);
}
void DecodeRowCallback(png_struct* png_ptr, png_byte* new_row,
png_uint_32 row_num, int pass) {
- if (!new_row)
- return; // Interlaced image; row didn't change this pass.
-
PngDecoderState* state = static_cast<PngDecoderState*>(
png_get_progressive_ptr(png_ptr));
+ DCHECK(pass == 0);
if (static_cast<int>(row_num) > state->height) {
NOTREACHED() << "Invalid row";
return;
}
unsigned char* base = NULL;
- if (state->bitmap)
- base = reinterpret_cast<unsigned char*>(state->bitmap->getAddr32(0, 0));
- else if (state->output)
- base = &state->output->front();
+ base = &state->output->front();
unsigned char* dest = &base[state->width * state->output_channels * row_num];
- png_progressive_combine_row(png_ptr, dest, new_row);
+ if (state->row_converter)
+ state->row_converter(new_row, state->width, dest, &state->is_opaque);
+ else
+ memcpy(dest, new_row, state->width * state->output_channels);
}
void DecodeEndCallback(png_struct* png_ptr, png_info* info) {
@@ -322,25 +290,6 @@ class PngReadStructDestroyer {
private:
png_struct** ps_;
png_info** pi_;
- DISALLOW_COPY_AND_ASSIGN(PngReadStructDestroyer);
-};
-
-// Automatically destroys the given write structs on destruction to make
-// cleanup and error handling code cleaner.
-class PngWriteStructDestroyer {
- public:
- explicit PngWriteStructDestroyer(png_struct** ps) : ps_(ps), pi_(0) {
- }
- ~PngWriteStructDestroyer() {
- png_destroy_write_struct(ps_, pi_);
- }
- void SetInfoStruct(png_info** pi) {
- pi_ = pi;
- }
- private:
- png_struct** ps_;
- png_info** pi_;
- DISALLOW_COPY_AND_ASSIGN(PngWriteStructDestroyer);
};
bool BuildPNGStruct(const unsigned char* input, size_t input_size,
@@ -365,31 +314,10 @@ bool BuildPNGStruct(const unsigned char* input, size_t input_size,
return true;
}
-// Libpng user error and warning functions which allows us to print libpng
-// errors and warnings using Chrome's logging facilities instead of stderr.
-
-void LogLibPNGDecodeError(png_structp png_ptr, png_const_charp error_msg) {
- DLOG(ERROR) << "libpng decode error: " << error_msg;
- longjmp(png_jmpbuf(png_ptr), 1);
-}
-
-void LogLibPNGDecodeWarning(png_structp png_ptr, png_const_charp warning_msg) {
- DLOG(ERROR) << "libpng decode warning: " << warning_msg;
-}
-
-void LogLibPNGEncodeError(png_structp png_ptr, png_const_charp error_msg) {
- DLOG(ERROR) << "libpng encode error: " << error_msg;
- longjmp(png_jmpbuf(png_ptr), 1);
-}
-
-void LogLibPNGEncodeWarning(png_structp png_ptr, png_const_charp warning_msg) {
- DLOG(ERROR) << "libpng encode warning: " << warning_msg;
-}
-
} // namespace
// static
-bool PNGCodec::Decode(const unsigned char* input, size_t input_size,
+bool Decode(const unsigned char* input, size_t input_size,
ColorFormat format, std::vector<unsigned char>* output,
int* w, int* h) {
png_struct* png_ptr = NULL;
@@ -407,7 +335,6 @@ bool PNGCodec::Decode(const unsigned char* input, size_t input_size,
PngDecoderState state(format, output);
- png_set_error_fn(png_ptr, NULL, LogLibPNGDecodeError, LogLibPNGDecodeWarning);
png_set_progressive_read_fn(png_ptr, &state, &DecodeInfoCallback,
&DecodeRowCallback, &DecodeEndCallback);
png_process_data(png_ptr,
@@ -427,43 +354,6 @@ bool PNGCodec::Decode(const unsigned char* input, size_t input_size,
return true;
}
-// static
-bool PNGCodec::Decode(const unsigned char* input, size_t input_size,
- SkBitmap* bitmap) {
- DCHECK(bitmap);
- png_struct* png_ptr = NULL;
- png_info* info_ptr = NULL;
- if (!BuildPNGStruct(input, input_size, &png_ptr, &info_ptr))
- return false;
-
- PngReadStructDestroyer 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;
- }
-
- PngDecoderState state(bitmap);
-
- png_set_progressive_read_fn(png_ptr, &state, &DecodeInfoCallback,
- &DecodeRowCallback, &DecodeEndCallback);
- png_process_data(png_ptr,
- info_ptr,
- const_cast<unsigned char*>(input),
- input_size);
-
- if (!state.done) {
- return false;
- }
-
- // Set the bitmap's opaqueness based on what we saw.
- bitmap->setAlphaType(state.is_opaque ?
- kOpaque_SkAlphaType : kPremul_SkAlphaType);
-
- return true;
-}
-
// Encoder --------------------------------------------------------------------
//
// This section of the code is based on nsPNGEncoder.cpp in Mozilla
@@ -505,9 +395,18 @@ void ConvertBGRAtoRGB(const unsigned char* bgra, int pixel_width,
}
#ifdef PNG_TEXT_SUPPORTED
+
+inline char* strdup(const char* str) {
+#if defined(OS_WIN)
+ return _strdup(str);
+#else
+ return ::strdup(str);
+#endif
+}
+
class CommentWriter {
public:
- explicit CommentWriter(const std::vector<PNGCodec::Comment>& comments)
+ explicit CommentWriter(const std::vector<Comment>& comments)
: comments_(comments),
png_text_(new png_text[comments.size()]) {
for (size_t i = 0; i < comments.size(); ++i)
@@ -535,12 +434,12 @@ class CommentWriter {
}
private:
- void AddComment(size_t pos, const PNGCodec::Comment& comment) {
+ void AddComment(size_t pos, const Comment& comment) {
png_text_[pos].compression = PNG_TEXT_COMPRESSION_NONE;
// A PNG comment's key can only be 79 characters long.
DCHECK(comment.key.length() < 79);
- png_text_[pos].key = base::strdup(comment.key.substr(0, 78).c_str());
- png_text_[pos].text = base::strdup(comment.text.c_str());
+ png_text_[pos].key = strdup(comment.key.substr(0, 78).c_str());
+ png_text_[pos].text = strdup(comment.text.c_str());
png_text_[pos].text_length = comment.text.length();
#ifdef PNG_iTXt_SUPPORTED
png_text_[pos].itxt_length = 0;
@@ -549,9 +448,7 @@ class CommentWriter {
#endif
}
- DISALLOW_COPY_AND_ASSIGN(CommentWriter);
-
- const std::vector<PNGCodec::Comment> comments_;
+ const std::vector<Comment> comments_;
png_text* png_text_;
};
#endif // PNG_TEXT_SUPPORTED
@@ -570,7 +467,7 @@ bool DoLibpngWrite(png_struct* png_ptr, png_info* info_ptr,
const unsigned char* input, int compression_level,
int png_output_color_type, int output_color_components,
FormatConverter converter,
- const std::vector<PNGCodec::Comment>& comments) {
+ const std::vector<Comment>& comments) {
#ifdef PNG_TEXT_SUPPORTED
CommentWriter comment_writer(comments);
#endif
@@ -588,7 +485,6 @@ bool DoLibpngWrite(png_struct* png_ptr, png_info* info_ptr,
// Set our callback for libpng to give us the data.
png_set_write_fn(png_ptr, state, EncoderWriteCallback, FakeFlushCallback);
- png_set_error_fn(png_ptr, NULL, LogLibPNGEncodeError, LogLibPNGEncodeWarning);
png_set_IHDR(png_ptr, info_ptr, width, height, 8, png_output_color_type,
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
@@ -623,12 +519,14 @@ bool DoLibpngWrite(png_struct* png_ptr, png_info* info_ptr,
return true;
}
-bool EncodeWithCompressionLevel(const unsigned char* input,
- PNGCodec::ColorFormat format,
- const Size& size,
+} // namespace
+
+// static
+bool EncodeWithCompressionLevel(const unsigned char* input, ColorFormat format,
+ const int width, const int height,
int row_byte_width,
bool discard_transparency,
- const std::vector<PNGCodec::Comment>& comments,
+ const std::vector<Comment>& comments,
int compression_level,
std::vector<unsigned char>* output) {
// Run to convert an input row into the output row format, NULL means no
@@ -638,13 +536,14 @@ bool EncodeWithCompressionLevel(const unsigned char* input,
int input_color_components, output_color_components;
int png_output_color_type;
switch (format) {
- case PNGCodec::FORMAT_RGB:
+ case FORMAT_RGB:
input_color_components = 3;
output_color_components = 3;
png_output_color_type = PNG_COLOR_TYPE_RGB;
+ discard_transparency = false;
break;
- case PNGCodec::FORMAT_RGBA:
+ case FORMAT_RGBA:
input_color_components = 4;
if (discard_transparency) {
output_color_components = 3;
@@ -657,7 +556,7 @@ bool EncodeWithCompressionLevel(const unsigned char* input,
}
break;
- case PNGCodec::FORMAT_BGRA:
+ case FORMAT_BGRA:
input_color_components = 4;
if (discard_transparency) {
output_color_components = 3;
@@ -670,141 +569,75 @@ bool EncodeWithCompressionLevel(const unsigned char* input,
}
break;
- case PNGCodec::FORMAT_SkBitmap:
- // Compare row_byte_width and size.width() to detect the format of
- // SkBitmap. kA8_Config (1bpp) and kARGB_8888_Config (4bpp) are the two
- // supported formats.
- if (row_byte_width < 4 * size.width()) {
- // Not 4bpp, so must be 1bpp.
- // Ignore discard_transparency - it doesn't make sense in this context,
- // since alpha is the only thing we have and it needs to be used for
- // color intensity.
- input_color_components = 1;
- output_color_components = 1;
- png_output_color_type = PNG_COLOR_TYPE_GRAY;
- // |converter| is left as null
- } else {
- input_color_components = 4;
- if (discard_transparency) {
- output_color_components = 3;
- png_output_color_type = PNG_COLOR_TYPE_RGB;
- converter = ConvertSkiaToRGB;
- } else {
- output_color_components = 4;
- png_output_color_type = PNG_COLOR_TYPE_RGB_ALPHA;
- converter = ConvertSkiaToRGBA;
- }
- }
- 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 * size.width() <= row_byte_width);
+ DCHECK(input_color_components * width <= row_byte_width);
png_struct* png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
NULL, NULL, NULL);
if (!png_ptr)
return false;
- PngWriteStructDestroyer destroyer(&png_ptr);
png_info* info_ptr = png_create_info_struct(png_ptr);
- if (!info_ptr)
+ if (!info_ptr) {
+ png_destroy_write_struct(&png_ptr, NULL);
return false;
- destroyer.SetInfoStruct(&info_ptr);
-
- output->clear();
+ }
PngEncoderState state(output);
bool success = DoLibpngWrite(png_ptr, info_ptr, &state,
- size.width(), size.height(), row_byte_width,
+ width, height, row_byte_width,
input, compression_level, png_output_color_type,
output_color_components, converter, comments);
+ png_destroy_write_struct(&png_ptr, &info_ptr);
return success;
}
-bool InternalEncodeSkBitmap(const SkBitmap& input,
- bool discard_transparency,
- int compression_level,
- std::vector<unsigned char>* output) {
- if (input.empty() || input.isNull())
- return false;
- int bpp = input.bytesPerPixel();
- DCHECK(bpp == 1 || bpp == 4); // We support kA8_Config and kARGB_8888_Config.
-
- SkAutoLockPixels lock_input(input);
- unsigned char* inputAddr = bpp == 1 ?
- reinterpret_cast<unsigned char*>(input.getAddr8(0, 0)) :
- reinterpret_cast<unsigned char*>(input.getAddr32(0, 0)); // bpp = 4
- return EncodeWithCompressionLevel(
- inputAddr,
- PNGCodec::FORMAT_SkBitmap,
- Size(input.width(), input.height()),
- static_cast<int>(input.rowBytes()),
- discard_transparency,
- std::vector<PNGCodec::Comment>(),
- compression_level,
- output);
-}
-
-
-} // namespace
-
// static
-bool PNGCodec::Encode(const unsigned char* input,
- ColorFormat format,
- const Size& size,
- int row_byte_width,
- bool discard_transparency,
- const std::vector<Comment>& comments,
- std::vector<unsigned char>* output) {
- return EncodeWithCompressionLevel(input,
- format,
- size,
+bool Encode(const unsigned char* input, ColorFormat format,
+ const int width, const int height, int row_byte_width,
+ bool discard_transparency,
+ const std::vector<Comment>& comments,
+ std::vector<unsigned char>* output) {
+ return EncodeWithCompressionLevel(input, format, width, height,
row_byte_width,
discard_transparency,
- comments,
- Z_DEFAULT_COMPRESSION,
+ comments, Z_DEFAULT_COMPRESSION,
output);
}
-// static
-bool PNGCodec::EncodeBGRASkBitmap(const SkBitmap& input,
- bool discard_transparency,
- std::vector<unsigned char>* output) {
- return InternalEncodeSkBitmap(input,
- discard_transparency,
- Z_DEFAULT_COMPRESSION,
- output);
-}
-
-// static
-bool PNGCodec::EncodeA8SkBitmap(const SkBitmap& input,
- std::vector<unsigned char>* output) {
- return InternalEncodeSkBitmap(input,
- false,
- Z_DEFAULT_COMPRESSION,
- output);
-}
-
-// static
-bool PNGCodec::FastEncodeBGRASkBitmap(const SkBitmap& input,
- bool discard_transparency,
- std::vector<unsigned char>* output) {
- return InternalEncodeSkBitmap(input,
- discard_transparency,
- Z_BEST_SPEED,
- output);
+// Decode a PNG into an RGBA pixel array.
+bool DecodePNG(const unsigned char* input, size_t input_size,
+ std::vector<unsigned char>* output,
+ int* width, int* height) {
+ return Decode(input, input_size, FORMAT_RGBA, output, width, height);
}
-PNGCodec::Comment::Comment(const std::string& k, const std::string& t)
- : key(k), text(t) {
+// Encode an RGBA pixel array into a PNG.
+bool EncodeRGBAPNG(const unsigned char* input,
+ int width,
+ int height,
+ int row_byte_width,
+ std::vector<unsigned char>* output) {
+ return Encode(input, FORMAT_RGBA,
+ width, height, row_byte_width, false,
+ std::vector<Comment>(), output);
}
-PNGCodec::Comment::~Comment() {
+// Encode an BGRA pixel array into a PNG.
+bool EncodeBGRAPNG(const unsigned char* input,
+ int width,
+ int height,
+ int row_byte_width,
+ bool discard_transparency,
+ std::vector<unsigned char>* output) {
+ return Encode(input, FORMAT_BGRA,
+ width, height, row_byte_width, discard_transparency,
+ std::vector<Comment>(), output);
}
-} // namespace gfx
+} // image_diff_png
« no previous file with comments | « sky/tools/imagediff/image_diff_png.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698