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

Unified Diff: ui/gfx/codec/png_codec.cc

Issue 11028064: Resize images for hi-dpi based on a custom PNG chunk added by GRIT r78, and roll GRIT r78 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: comments Created 8 years, 2 months 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
Index: ui/gfx/codec/png_codec.cc
diff --git a/ui/gfx/codec/png_codec.cc b/ui/gfx/codec/png_codec.cc
index 474fbc9f3999b9464a990aaef0f255080c0e2a6e..82ffcd2b28e2840820ac65d78deee8527c0a6cfe 100644
--- a/ui/gfx/codec/png_codec.cc
+++ b/ui/gfx/codec/png_codec.cc
@@ -94,6 +94,8 @@ const double kMaxGamma = 21474.83; // Maximum gamma accepted by png library.
const double kDefaultGamma = 2.2;
const double kInverseGamma = 1.0 / kDefaultGamma;
+const png_byte kPngScaleChunk[5] = { 'c', 's', 'C', 'l', 0 };
+
class PngDecoderState {
public:
// Output is a vector<unsigned char>.
@@ -105,6 +107,7 @@ class PngDecoderState {
output(o),
width(0),
height(0),
+ fell_back_to_1x(false),
done(false) {
}
@@ -117,6 +120,7 @@ class PngDecoderState {
output(NULL),
width(0),
height(0),
+ fell_back_to_1x(false),
done(false) {
}
@@ -138,6 +142,10 @@ class PngDecoderState {
int width;
int height;
+ // True if a csCl chunk is present, indicating that GRIT didn't find an image
+ // at the proper scale and fell back to 100%.
+ bool fell_back_to_1x;
+
// Set to true when we've found the end of the data.
bool done;
@@ -330,6 +338,18 @@ void DecodeEndCallback(png_struct* png_ptr, png_info* info) {
state->done = true;
}
+int DecodeUserChunkCallback(png_struct* png_ptr, png_unknown_chunk* chunk) {
+ PngDecoderState* state = static_cast<PngDecoderState*>(
+ png_get_user_chunk_ptr(png_ptr));
+ // We instructed libpng to call us only for csCl chunks.
+ DCHECK(memcmp(chunk->name, kPngScaleChunk, 5) == 0);
+ if (chunk->size == 0) {
+ state->fell_back_to_1x = true;
+ return 1; // processed
+ }
+ return 0; // unrecognized
+}
+
// Automatically destroys the given read structs on destruction to make
// cleanup and error handling code cleaner.
class PngReadStructDestroyer {
@@ -406,12 +426,8 @@ 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,
- ColorFormat format, std::vector<unsigned char>* output,
- int* w, int* h) {
+bool DecodeInternal(const unsigned char* input, size_t input_size,
+ PngDecoderState* state) {
png_struct* png_ptr = NULL;
png_info* info_ptr = NULL;
if (!BuildPNGStruct(input, input_size, &png_ptr, &info_ptr))
@@ -425,23 +441,29 @@ bool PNGCodec::Decode(const unsigned char* input, size_t input_size,
return false;
}
- 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,
- info_ptr,
- const_cast<unsigned char*>(input),
- input_size);
-
- if (!state.done) {
- // Fed it all the data but the library didn't think we got all the data, so
- // this file must be truncated.
+ png_set_progressive_read_fn(png_ptr, state, DecodeInfoCallback,
+ DecodeRowCallback, DecodeEndCallback);
+ png_set_keep_unknown_chunks(png_ptr, 3, const_cast<png_byte*>(kPngScaleChunk),
+ 1); // keep only csCl
+ png_set_read_user_chunk_fn(png_ptr, state, DecodeUserChunkCallback);
+ png_process_data(png_ptr, info_ptr,
+ const_cast<unsigned char*>(input), input_size);
+ return state->done;
+}
+
+} // namespace
+
+
+// static
+bool PNGCodec::Decode(const unsigned char* input, size_t input_size,
+ ColorFormat format, std::vector<unsigned char>* output,
+ int* w, int* h) {
+ PngDecoderState state(format, output);
+ if (!DecodeInternal(input, input_size, &state)) {
output->clear();
return false;
}
-
*w = state.width;
*h = state.height;
return true;
@@ -449,41 +471,24 @@ bool PNGCodec::Decode(const unsigned char* input, size_t input_size,
// static
bool PNGCodec::Decode(const unsigned char* input, size_t input_size,
- SkBitmap* bitmap) {
+ SkBitmap* bitmap, bool* fell_back_to_1x) {
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) {
+ if (!DecodeInternal(input, input_size, &state))
return false;
- }
-
- // Set the bitmap's opaqueness based on what we saw.
bitmap->setIsOpaque(state.is_opaque);
-
+ if (fell_back_to_1x)
+ *fell_back_to_1x = state.fell_back_to_1x;
return true;
}
// static
+bool PNGCodec::Decode(const unsigned char* input, size_t input_size,
+ SkBitmap* bitmap) {
+ return Decode(input, input_size, bitmap, NULL);
+}
+
+// static
SkBitmap* PNGCodec::CreateSkBitmapFromBGRAFormat(
std::vector<unsigned char>& bgra, int width, int height) {
SkBitmap* bitmap = new SkBitmap();

Powered by Google App Engine
This is Rietveld 408576698