Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/gfx/codec/png_codec.h" | 5 #include "ui/gfx/codec/png_codec.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
| 9 #include "base/string_util.h" | 9 #include "base/string_util.h" |
| 10 #include "ui/gfx/size.h" | 10 #include "ui/gfx/size.h" |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 47 unsigned char* rgb, bool* is_opaque) { | 47 unsigned char* rgb, bool* is_opaque) { |
| 48 for (int x = 0; x < pixel_width; x++) { | 48 for (int x = 0; x < pixel_width; x++) { |
| 49 const unsigned char* pixel_in = &rgba[x * 4]; | 49 const unsigned char* pixel_in = &rgba[x * 4]; |
| 50 unsigned char* pixel_out = &rgb[x * 3]; | 50 unsigned char* pixel_out = &rgb[x * 3]; |
| 51 pixel_out[0] = pixel_in[0]; | 51 pixel_out[0] = pixel_in[0]; |
| 52 pixel_out[1] = pixel_in[1]; | 52 pixel_out[1] = pixel_in[1]; |
| 53 pixel_out[2] = pixel_in[2]; | 53 pixel_out[2] = pixel_in[2]; |
| 54 } | 54 } |
| 55 } | 55 } |
| 56 | 56 |
| 57 void ConvertRGBtoSkia(const unsigned char* rgb, int pixel_width, | |
| 58 unsigned char* rgba, bool* is_opaque) { | |
| 59 for (int x = 0; x < pixel_width; x++) { | |
| 60 const unsigned char* pixel_in = &rgb[x * 3]; | |
| 61 uint32_t* pixel_out = reinterpret_cast<uint32_t*>(&rgba[x * 4]); | |
| 62 *pixel_out = SkPackARGB32(0xFF, pixel_in[0], pixel_in[1], pixel_in[2]); | |
| 63 } | |
| 64 } | |
| 65 | |
| 66 void ConvertRGBAtoSkia(const unsigned char* rgb, int pixel_width, | |
| 67 unsigned char* rgba, bool* is_opaque) { | |
| 68 int total_length = pixel_width * 4; | |
| 69 for (int x = 0; x < total_length; x += 4) { | |
| 70 const unsigned char* pixel_in = &rgb[x]; | |
| 71 uint32_t* pixel_out = reinterpret_cast<uint32_t*>(&rgba[x]); | |
| 72 | |
| 73 unsigned char alpha = pixel_in[3]; | |
| 74 if (alpha != 255) { | |
| 75 *is_opaque = false; | |
| 76 *pixel_out = SkPreMultiplyARGB(alpha, | |
| 77 pixel_in[0], pixel_in[1], pixel_in[2]); | |
| 78 } else { | |
| 79 *pixel_out = SkPackARGB32(alpha, | |
| 80 pixel_in[0], pixel_in[1], pixel_in[2]); | |
| 81 } | |
| 82 } | |
| 83 } | |
| 84 | |
| 85 void ConvertSkiatoRGB(const unsigned char* skia, int pixel_width, | 57 void ConvertSkiatoRGB(const unsigned char* skia, int pixel_width, |
| 86 unsigned char* rgb, bool* is_opaque) { | 58 unsigned char* rgb, bool* is_opaque) { |
| 87 for (int x = 0; x < pixel_width; x++) { | 59 for (int x = 0; x < pixel_width; x++) { |
| 88 const uint32_t pixel_in = *reinterpret_cast<const uint32_t*>(&skia[x * 4]); | 60 const uint32_t pixel_in = *reinterpret_cast<const uint32_t*>(&skia[x * 4]); |
| 89 unsigned char* pixel_out = &rgb[x * 3]; | 61 unsigned char* pixel_out = &rgb[x * 3]; |
| 90 | 62 |
| 91 int alpha = SkGetPackedA32(pixel_in); | 63 int alpha = SkGetPackedA32(pixel_in); |
| 92 if (alpha != 0 && alpha != 255) { | 64 if (alpha != 0 && alpha != 255) { |
| 93 SkColor unmultiplied = SkUnPreMultiply::PMColorToColor(pixel_in); | 65 SkColor unmultiplied = SkUnPreMultiply::PMColorToColor(pixel_in); |
| 94 pixel_out[0] = SkColorGetR(unmultiplied); | 66 pixel_out[0] = SkColorGetR(unmultiplied); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 141 | 113 |
| 142 class PngDecoderState { | 114 class PngDecoderState { |
| 143 public: | 115 public: |
| 144 // Output is a vector<unsigned char>. | 116 // Output is a vector<unsigned char>. |
| 145 PngDecoderState(PNGCodec::ColorFormat ofmt, std::vector<unsigned char>* o) | 117 PngDecoderState(PNGCodec::ColorFormat ofmt, std::vector<unsigned char>* o) |
| 146 : output_format(ofmt), | 118 : output_format(ofmt), |
| 147 output_channels(0), | 119 output_channels(0), |
| 148 bitmap(NULL), | 120 bitmap(NULL), |
| 149 is_opaque(true), | 121 is_opaque(true), |
| 150 output(o), | 122 output(o), |
| 151 row_converter(NULL), | |
| 152 width(0), | 123 width(0), |
| 153 height(0), | 124 height(0), |
| 154 done(false) { | 125 done(false) { |
| 155 } | 126 } |
| 156 | 127 |
| 157 // Output is an SkBitmap. | 128 // Output is an SkBitmap. |
| 158 explicit PngDecoderState(SkBitmap* skbitmap) | 129 explicit PngDecoderState(SkBitmap* skbitmap) |
| 159 : output_format(PNGCodec::FORMAT_SkBitmap), | 130 : output_format(PNGCodec::FORMAT_SkBitmap), |
| 160 output_channels(0), | 131 output_channels(0), |
| 161 bitmap(skbitmap), | 132 bitmap(skbitmap), |
| 162 is_opaque(true), | 133 is_opaque(true), |
| 163 output(NULL), | 134 output(NULL), |
| 164 row_converter(NULL), | |
| 165 width(0), | 135 width(0), |
| 166 height(0), | 136 height(0), |
| 167 done(false) { | 137 done(false) { |
| 168 } | 138 } |
| 169 | 139 |
| 170 PNGCodec::ColorFormat output_format; | 140 PNGCodec::ColorFormat output_format; |
| 171 int output_channels; | 141 int output_channels; |
| 172 | 142 |
| 173 // An incoming SkBitmap to write to. If NULL, we write to output instead. | 143 // An incoming SkBitmap to write to. If NULL, we write to output instead. |
| 174 SkBitmap* bitmap; | 144 SkBitmap* bitmap; |
| 175 | 145 |
| 176 // Used during the reading of an SkBitmap. Defaults to true until we see a | 146 // Used during the reading of an SkBitmap. Defaults to true until we see a |
| 177 // pixel with anything other than an alpha of 255. | 147 // pixel with anything other than an alpha of 255. |
| 178 bool is_opaque; | 148 bool is_opaque; |
| 179 | 149 |
| 180 // The other way to decode output, where we write into an intermediary buffer | 150 // The other way to decode output, where we write into an intermediary buffer |
| 181 // instead of directly to an SkBitmap. | 151 // instead of directly to an SkBitmap. |
| 182 std::vector<unsigned char>* output; | 152 std::vector<unsigned char>* output; |
| 183 | 153 |
| 184 // Called to convert a row from the library to the correct output format. | |
| 185 // When NULL, no conversion is necessary. | |
| 186 void (*row_converter)(const unsigned char* in, int w, unsigned char* out, | |
| 187 bool* is_opaque); | |
| 188 | |
| 189 // Size of the image, set in the info callback. | 154 // Size of the image, set in the info callback. |
| 190 int width; | 155 int width; |
| 191 int height; | 156 int height; |
| 192 | 157 |
| 193 // Set to true when we've found the end of the data. | 158 // Set to true when we've found the end of the data. |
| 194 bool done; | 159 bool done; |
| 195 | 160 |
| 196 private: | 161 private: |
| 197 DISALLOW_COPY_AND_ASSIGN(PngDecoderState); | 162 DISALLOW_COPY_AND_ASSIGN(PngDecoderState); |
| 198 }; | 163 }; |
| 199 | 164 |
| 200 void ConvertRGBtoRGBA(const unsigned char* rgb, int pixel_width, | 165 // User transform (passed to libpng) which converts a row decoded by libpng to |
| 201 unsigned char* rgba, bool* is_opaque) { | 166 // Skia format. Expects the row to have 4 channels, otherwise there won't be |
| 202 for (int x = 0; x < pixel_width; x++) { | 167 // enough room in |data|. |
| 203 const unsigned char* pixel_in = &rgb[x * 3]; | 168 void ConvertRGBARowToSkia(png_structp png_ptr, |
| 204 unsigned char* pixel_out = &rgba[x * 4]; | 169 png_row_infop row_info, |
| 205 pixel_out[0] = pixel_in[0]; | 170 png_bytep data) { |
| 206 pixel_out[1] = pixel_in[1]; | 171 const int channels = row_info->channels; |
| 207 pixel_out[2] = pixel_in[2]; | 172 DCHECK_EQ(channels, 4); |
| 208 pixel_out[3] = 0xff; | 173 |
| 174 PngDecoderState* state = | |
| 175 static_cast<PngDecoderState*>(png_get_user_transform_ptr(png_ptr)); | |
| 176 DCHECK(state) << "LibPNG user transform pointer is NULL"; | |
| 177 | |
| 178 unsigned char* const end = data + row_info->rowbytes; | |
| 179 for (unsigned char* p = data; p < end; p += channels) { | |
| 180 uint32_t* sk_pixel = reinterpret_cast<uint32_t*>(p); | |
| 181 const unsigned char alpha = p[channels - 1]; | |
| 182 if (alpha != 255) { | |
| 183 state->is_opaque = false; | |
| 184 *sk_pixel = SkPreMultiplyARGB(alpha, p[0], p[1], p[2]); | |
| 185 } else { | |
| 186 *sk_pixel = SkPackARGB32(alpha, p[0], p[1], p[2]); | |
| 187 } | |
| 209 } | 188 } |
| 210 } | 189 } |
| 211 | 190 |
| 212 void ConvertRGBtoBGRA(const unsigned char* rgb, int pixel_width, | |
| 213 unsigned char* bgra, bool* is_opaque) { | |
| 214 for (int x = 0; x < pixel_width; x++) { | |
| 215 const unsigned char* pixel_in = &rgb[x * 3]; | |
| 216 unsigned char* pixel_out = &bgra[x * 4]; | |
| 217 pixel_out[0] = pixel_in[2]; | |
| 218 pixel_out[1] = pixel_in[1]; | |
| 219 pixel_out[2] = pixel_in[0]; | |
| 220 pixel_out[3] = 0xff; | |
| 221 } | |
| 222 } | |
| 223 | |
| 224 // Called when the png header has been read. This code is based on the WebKit | 191 // Called when the png header has been read. This code is based on the WebKit |
| 225 // PNGImageDecoder | 192 // PNGImageDecoder |
| 226 void DecodeInfoCallback(png_struct* png_ptr, png_info* info_ptr) { | 193 void DecodeInfoCallback(png_struct* png_ptr, png_info* info_ptr) { |
| 227 PngDecoderState* state = static_cast<PngDecoderState*>( | 194 PngDecoderState* state = static_cast<PngDecoderState*>( |
| 228 png_get_progressive_ptr(png_ptr)); | 195 png_get_progressive_ptr(png_ptr)); |
| 229 | 196 |
| 230 int bit_depth, color_type, interlace_type, compression_type; | 197 int bit_depth, color_type, interlace_type, compression_type; |
| 231 int filter_type, channels; | 198 int filter_type; |
| 232 png_uint_32 w, h; | 199 png_uint_32 w, h; |
| 233 png_get_IHDR(png_ptr, info_ptr, &w, &h, &bit_depth, &color_type, | 200 png_get_IHDR(png_ptr, info_ptr, &w, &h, &bit_depth, &color_type, |
| 234 &interlace_type, &compression_type, &filter_type); | 201 &interlace_type, &compression_type, &filter_type); |
| 235 | 202 |
| 236 // Bounds check. When the image is unreasonably big, we'll error out and | 203 // Bounds check. When the image is unreasonably big, we'll error out and |
| 237 // end up back at the setjmp call when we set up decoding. "Unreasonably big" | 204 // end up back at the setjmp call when we set up decoding. "Unreasonably big" |
| 238 // means "big enough that w * h * 32bpp might overflow an int"; we choose this | 205 // means "big enough that w * h * 32bpp might overflow an int"; we choose this |
| 239 // threshold to match WebKit and because a number of places in code assume | 206 // threshold to match WebKit and because a number of places in code assume |
| 240 // that an image's size (in bytes) fits in a (signed) int. | 207 // that an image's size (in bytes) fits in a (signed) int. |
| 241 unsigned long long total_size = | 208 unsigned long long total_size = |
| 242 static_cast<unsigned long long>(w) * static_cast<unsigned long long>(h); | 209 static_cast<unsigned long long>(w) * static_cast<unsigned long long>(h); |
| 243 if (total_size > ((1 << 29) - 1)) | 210 if (total_size > ((1 << 29) - 1)) |
| 244 longjmp(png_jmpbuf(png_ptr), 1); | 211 longjmp(png_jmpbuf(png_ptr), 1); |
| 245 state->width = static_cast<int>(w); | 212 state->width = static_cast<int>(w); |
| 246 state->height = static_cast<int>(h); | 213 state->height = static_cast<int>(h); |
| 247 | 214 |
| 215 // The following png_set_* calls have to be done in the order dictated by | |
| 216 // the libpng docs. This is why certain things are done outside of the | |
| 217 // switch, even though they look like they belong there. | |
| 218 | |
| 248 // Expand to ensure we use 24-bit for RGB and 32-bit for RGBA. | 219 // Expand to ensure we use 24-bit for RGB and 32-bit for RGBA. |
| 249 if (color_type == PNG_COLOR_TYPE_PALETTE || | 220 if (color_type == PNG_COLOR_TYPE_PALETTE || |
| 250 (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)) | 221 (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)) |
| 251 png_set_expand(png_ptr); | 222 png_set_expand(png_ptr); |
| 252 | 223 |
| 224 bool input_has_alpha = (color_type & PNG_COLOR_MASK_ALPHA); | |
| 225 | |
| 253 // Transparency for paletted images. | 226 // Transparency for paletted images. |
| 254 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) | 227 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { |
| 255 png_set_expand(png_ptr); | 228 png_set_expand(png_ptr); |
| 229 input_has_alpha = true; | |
| 230 } | |
| 256 | 231 |
| 257 // Convert 16-bit to 8-bit. | 232 // Convert 16-bit to 8-bit. |
| 258 if (bit_depth == 16) | 233 if (bit_depth == 16) |
| 259 png_set_strip_16(png_ptr); | 234 png_set_strip_16(png_ptr); |
| 260 | 235 |
| 236 // See comment about png_set_* call ordering, above. | |
| 237 if (state->output_format == PNGCodec::FORMAT_BGRA) | |
| 238 png_set_bgr(png_ptr); | |
|
tony
2012/03/06 19:55:30
Why do we call this? Does it replace ConvertRGBtoB
Francois
2012/03/07 07:40:10
That's correct. I've moved this into the switch st
| |
| 239 | |
| 240 // Pick our row format converter necessary for this data. | |
| 241 if (!input_has_alpha) { | |
| 242 switch (state->output_format) { | |
| 243 case PNGCodec::FORMAT_RGB: | |
| 244 state->output_channels = 3; | |
| 245 break; | |
| 246 case PNGCodec::FORMAT_RGBA: | |
| 247 state->output_channels = 4; | |
| 248 png_set_add_alpha(png_ptr, 0xFF, PNG_FILLER_AFTER); | |
| 249 break; | |
| 250 case PNGCodec::FORMAT_BGRA: | |
| 251 state->output_channels = 4; | |
| 252 png_set_add_alpha(png_ptr, 0xFF, PNG_FILLER_AFTER); | |
| 253 break; | |
| 254 case PNGCodec::FORMAT_SkBitmap: | |
| 255 state->output_channels = 4; | |
| 256 png_set_add_alpha(png_ptr, 0xFF, PNG_FILLER_AFTER); | |
| 257 break; | |
| 258 default: | |
| 259 NOTREACHED() << "Unknown output format"; | |
|
tony
2012/03/06 19:55:30
Please remove the default case. The compiler will
Francois
2012/03/07 07:40:10
Done.
| |
| 260 break; | |
| 261 } | |
| 262 } else { | |
| 263 switch (state->output_format) { | |
| 264 case PNGCodec::FORMAT_RGB: | |
| 265 png_set_strip_alpha(png_ptr); | |
| 266 state->output_channels = 3; | |
| 267 break; | |
| 268 case PNGCodec::FORMAT_RGBA: | |
| 269 state->output_channels = 4; | |
| 270 break; | |
| 271 case PNGCodec::FORMAT_BGRA: | |
| 272 state->output_channels = 4; | |
|
tony
2012/03/06 19:55:30
I assume that ConvertBetweenBGRAandRGBA is not nee
Francois
2012/03/07 07:40:10
Correct.
| |
| 273 break; | |
| 274 case PNGCodec::FORMAT_SkBitmap: | |
| 275 state->output_channels = 4; | |
| 276 break; | |
| 277 default: | |
| 278 NOTREACHED() << "Unknown output format"; | |
|
tony
2012/03/06 19:55:30
Please remove the default case. The compiler will
Francois
2012/03/07 07:40:10
Done.
| |
| 279 break; | |
| 280 } | |
| 281 } | |
| 282 | |
| 261 // Expand grayscale to RGB. | 283 // Expand grayscale to RGB. |
| 262 if (color_type == PNG_COLOR_TYPE_GRAY || | 284 if (color_type == PNG_COLOR_TYPE_GRAY || |
| 263 color_type == PNG_COLOR_TYPE_GRAY_ALPHA) | 285 color_type == PNG_COLOR_TYPE_GRAY_ALPHA) |
| 264 png_set_gray_to_rgb(png_ptr); | 286 png_set_gray_to_rgb(png_ptr); |
| 265 | 287 |
| 266 // Deal with gamma and keep it under our control. | 288 // Deal with gamma and keep it under our control. |
| 267 double gamma; | 289 double gamma; |
| 268 if (png_get_gAMA(png_ptr, info_ptr, &gamma)) { | 290 if (png_get_gAMA(png_ptr, info_ptr, &gamma)) { |
| 269 if (gamma <= 0.0 || gamma > kMaxGamma) { | 291 if (gamma <= 0.0 || gamma > kMaxGamma) { |
| 270 gamma = kInverseGamma; | 292 gamma = kInverseGamma; |
| 271 png_set_gAMA(png_ptr, info_ptr, gamma); | 293 png_set_gAMA(png_ptr, info_ptr, gamma); |
| 272 } | 294 } |
| 273 png_set_gamma(png_ptr, kDefaultGamma, gamma); | 295 png_set_gamma(png_ptr, kDefaultGamma, gamma); |
| 274 } else { | 296 } else { |
| 275 png_set_gamma(png_ptr, kDefaultGamma, kInverseGamma); | 297 png_set_gamma(png_ptr, kDefaultGamma, kInverseGamma); |
| 276 } | 298 } |
| 277 | 299 |
| 300 // See comment about png_set_* call ordering, above. | |
| 301 if (state->output_format == PNGCodec::FORMAT_SkBitmap) { | |
| 302 png_set_read_user_transform_fn(png_ptr, ConvertRGBARowToSkia); | |
| 303 png_set_user_transform_info(png_ptr, state, 0, 0); | |
|
tony
2012/03/06 19:55:30
Can you make the comment explicit? E.g., png_set_
Francois
2012/03/07 07:40:10
Done.
| |
| 304 } | |
| 305 | |
| 278 // Tell libpng to send us rows for interlaced pngs. | 306 // Tell libpng to send us rows for interlaced pngs. |
| 279 if (interlace_type == PNG_INTERLACE_ADAM7) | 307 if (interlace_type == PNG_INTERLACE_ADAM7) |
| 280 png_set_interlace_handling(png_ptr); | 308 png_set_interlace_handling(png_ptr); |
| 281 | 309 |
| 282 // Update our info now | |
| 283 png_read_update_info(png_ptr, info_ptr); | 310 png_read_update_info(png_ptr, info_ptr); |
| 284 channels = png_get_channels(png_ptr, info_ptr); | |
| 285 | |
| 286 // Pick our row format converter necessary for this data. | |
| 287 if (channels == 3) { | |
| 288 switch (state->output_format) { | |
| 289 case PNGCodec::FORMAT_RGB: | |
| 290 state->row_converter = NULL; // no conversion necessary | |
| 291 state->output_channels = 3; | |
| 292 break; | |
| 293 case PNGCodec::FORMAT_RGBA: | |
| 294 state->row_converter = &ConvertRGBtoRGBA; | |
| 295 state->output_channels = 4; | |
| 296 break; | |
| 297 case PNGCodec::FORMAT_BGRA: | |
| 298 state->row_converter = &ConvertRGBtoBGRA; | |
| 299 state->output_channels = 4; | |
| 300 break; | |
| 301 case PNGCodec::FORMAT_SkBitmap: | |
| 302 state->row_converter = &ConvertRGBtoSkia; | |
| 303 state->output_channels = 4; | |
| 304 break; | |
| 305 default: | |
| 306 NOTREACHED() << "Unknown output format"; | |
| 307 break; | |
| 308 } | |
| 309 } else if (channels == 4) { | |
| 310 switch (state->output_format) { | |
| 311 case PNGCodec::FORMAT_RGB: | |
| 312 state->row_converter = &ConvertRGBAtoRGB; | |
| 313 state->output_channels = 3; | |
| 314 break; | |
| 315 case PNGCodec::FORMAT_RGBA: | |
| 316 state->row_converter = NULL; // no conversion necessary | |
| 317 state->output_channels = 4; | |
| 318 break; | |
| 319 case PNGCodec::FORMAT_BGRA: | |
| 320 state->row_converter = &ConvertBetweenBGRAandRGBA; | |
| 321 state->output_channels = 4; | |
| 322 break; | |
| 323 case PNGCodec::FORMAT_SkBitmap: | |
| 324 state->row_converter = &ConvertRGBAtoSkia; | |
| 325 state->output_channels = 4; | |
| 326 break; | |
| 327 default: | |
| 328 NOTREACHED() << "Unknown output format"; | |
| 329 break; | |
| 330 } | |
| 331 } else { | |
| 332 NOTREACHED() << "Unknown input channels"; | |
| 333 longjmp(png_jmpbuf(png_ptr), 1); | |
| 334 } | |
| 335 | 311 |
| 336 if (state->bitmap) { | 312 if (state->bitmap) { |
| 337 state->bitmap->setConfig(SkBitmap::kARGB_8888_Config, | 313 state->bitmap->setConfig(SkBitmap::kARGB_8888_Config, |
| 338 state->width, state->height); | 314 state->width, state->height); |
| 339 state->bitmap->allocPixels(); | 315 state->bitmap->allocPixels(); |
| 340 } else if (state->output) { | 316 } else if (state->output) { |
| 341 state->output->resize( | 317 state->output->resize( |
| 342 state->width * state->output_channels * state->height); | 318 state->width * state->output_channels * state->height); |
| 343 } | 319 } |
| 344 } | 320 } |
| 345 | 321 |
| 346 void DecodeRowCallback(png_struct* png_ptr, png_byte* new_row, | 322 void DecodeRowCallback(png_struct* png_ptr, png_byte* new_row, |
| 347 png_uint_32 row_num, int pass) { | 323 png_uint_32 row_num, int pass) { |
| 324 if (!new_row) | |
| 325 return; // Interlaced image; row didn't change this pass. | |
| 326 | |
| 348 PngDecoderState* state = static_cast<PngDecoderState*>( | 327 PngDecoderState* state = static_cast<PngDecoderState*>( |
| 349 png_get_progressive_ptr(png_ptr)); | 328 png_get_progressive_ptr(png_ptr)); |
| 350 | 329 |
| 351 DCHECK(pass == 0) << "We didn't turn on interlace handling, but libpng is " | |
| 352 "giving us interlaced data."; | |
| 353 if (static_cast<int>(row_num) > state->height) { | 330 if (static_cast<int>(row_num) > state->height) { |
| 354 NOTREACHED() << "Invalid row"; | 331 NOTREACHED() << "Invalid row"; |
| 355 return; | 332 return; |
| 356 } | 333 } |
| 357 | 334 |
| 358 unsigned char* base = NULL; | 335 unsigned char* base = NULL; |
| 359 if (state->bitmap) | 336 if (state->bitmap) |
| 360 base = reinterpret_cast<unsigned char*>(state->bitmap->getAddr32(0, 0)); | 337 base = reinterpret_cast<unsigned char*>(state->bitmap->getAddr32(0, 0)); |
| 361 else if (state->output) | 338 else if (state->output) |
| 362 base = &state->output->front(); | 339 base = &state->output->front(); |
| 363 | 340 |
| 364 unsigned char* dest = &base[state->width * state->output_channels * row_num]; | 341 unsigned char* dest = &base[state->width * state->output_channels * row_num]; |
| 365 if (state->row_converter) | 342 png_progressive_combine_row(png_ptr, dest, new_row); |
|
tony
2012/03/06 19:55:30
This is what add interlaced png support, right?
Francois
2012/03/07 07:40:10
Yes, this is the core change that was required for
| |
| 366 state->row_converter(new_row, state->width, dest, &state->is_opaque); | |
| 367 else | |
| 368 memcpy(dest, new_row, state->width * state->output_channels); | |
| 369 } | 343 } |
| 370 | 344 |
| 371 void DecodeEndCallback(png_struct* png_ptr, png_info* info) { | 345 void DecodeEndCallback(png_struct* png_ptr, png_info* info) { |
| 372 PngDecoderState* state = static_cast<PngDecoderState*>( | 346 PngDecoderState* state = static_cast<PngDecoderState*>( |
| 373 png_get_progressive_ptr(png_ptr)); | 347 png_get_progressive_ptr(png_ptr)); |
| 374 | 348 |
| 375 // Mark the image as complete, this will tell the Decode function that we | 349 // Mark the image as complete, this will tell the Decode function that we |
| 376 // have successfully found the end of the data. | 350 // have successfully found the end of the data. |
| 377 state->done = true; | 351 state->done = true; |
| 378 } | 352 } |
| (...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 785 } | 759 } |
| 786 | 760 |
| 787 PNGCodec::Comment::Comment(const std::string& k, const std::string& t) | 761 PNGCodec::Comment::Comment(const std::string& k, const std::string& t) |
| 788 : key(k), text(t) { | 762 : key(k), text(t) { |
| 789 } | 763 } |
| 790 | 764 |
| 791 PNGCodec::Comment::~Comment() { | 765 PNGCodec::Comment::~Comment() { |
| 792 } | 766 } |
| 793 | 767 |
| 794 } // namespace gfx | 768 } // namespace gfx |
| OLD | NEW |