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

Side by Side Diff: src/images/SkImageDecoder_libpng.cpp

Issue 12604006: Upstream Android modifications to the image encoders/decoders. (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Created 7 years, 9 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 1
2 /* 2 /*
3 * Copyright 2006 The Android Open Source Project 3 * Copyright 2006 The Android Open Source Project
4 * 4 *
5 * Use of this source code is governed by a BSD-style license that can be 5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file. 6 * found in the LICENSE file.
7 */ 7 */
8 8
9 9
10 #include "SkImageDecoder.h" 10 #include "SkImageDecoder.h"
11 #include "SkImageEncoder.h" 11 #include "SkImageEncoder.h"
12 #include "SkColor.h" 12 #include "SkColor.h"
13 #include "SkColorPriv.h" 13 #include "SkColorPriv.h"
14 #include "SkDither.h" 14 #include "SkDither.h"
15 #include "SkMath.h" 15 #include "SkMath.h"
16 #include "SkScaledBitmapSampler.h" 16 #include "SkScaledBitmapSampler.h"
17 #include "SkStream.h" 17 #include "SkStream.h"
18 #include "SkTemplates.h" 18 #include "SkTemplates.h"
19 #include "SkUtils.h" 19 #include "SkUtils.h"
20 #include "transform_scanline.h" 20 #include "transform_scanline.h"
21 21
22 extern "C" { 22 extern "C" {
23 #include "png.h" 23 #include "png.h"
24 } 24 }
25 25
robertphillips 2013/03/11 18:25:55 comment? Can this be nested in SkPNGImageDecoder?
26 class SkPNGImageIndex {
27 public:
28 SkPNGImageIndex(png_structp png_ptr, png_infop info_ptr) {
29 this->png_ptr = png_ptr;
30 this->info_ptr = info_ptr;
31 }
32 ~SkPNGImageIndex() {
robertphillips 2013/03/11 18:25:55 NULL !=
djsollen 2013/03/11 19:43:24 Done.
33 if (png_ptr) {
34 png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
35 }
36 }
37
38 png_structp png_ptr;
39 png_infop info_ptr;
40 };
41
26 class SkPNGImageDecoder : public SkImageDecoder { 42 class SkPNGImageDecoder : public SkImageDecoder {
27 public: 43 public:
44 SkPNGImageDecoder() {
45 fImageIndex = NULL;
46 }
28 virtual Format getFormat() const { 47 virtual Format getFormat() const {
29 return kPNG_Format; 48 return kPNG_Format;
30 } 49 }
50 virtual ~SkPNGImageDecoder() {
51 SkDELETE(fImageIndex);
52 }
31 53
32 protected: 54 protected:
55 #if defined(SK_BUILD_FOR_ANDROID) && !defined(SK_BUILD_FOR_ANDROID_NDK)
robertphillips 2013/03/11 18:25:55 OVERRIDES?
djsollen 2013/03/11 19:43:24 Done.
56 virtual bool onBuildTileIndex(SkStream *stream, int *width, int *height);
robertphillips 2013/03/11 18:25:55 _const_ SkIRect& region?
djsollen 2013/03/11 19:43:24 Done.
57 virtual bool onDecodeRegion(SkBitmap* bitmap, SkIRect& region);
58 #endif
33 virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode); 59 virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode);
60
61 private:
62 bool onDecodeInit(SkStream* stream, png_structp *png_ptrp, png_infop *info_p trp);
63 bool decodePalette(png_structp png_ptr, png_infop info_ptr, bool *hasAlphap,
64 bool *reallyHasAlphap, SkColorTable **colorTablep);
65 bool getBitmapConfig(png_structp png_ptr, png_infop info_ptr,
66 SkBitmap::Config *config, bool *hasAlpha,
67 bool *doDither, SkPMColor *theTranspColor);
68
69 SkPNGImageIndex* fImageIndex;
robertphillips 2013/03/11 18:25:55 INHERITED?
34 }; 70 };
35 71
36 #ifndef png_jmpbuf 72 #ifndef png_jmpbuf
37 # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) 73 # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
38 #endif 74 #endif
39 75
40 #define PNG_BYTES_TO_CHECK 4 76 #define PNG_BYTES_TO_CHECK 4
41 77
42 /* Automatically clean up after throwing an exception */ 78 /* Automatically clean up after throwing an exception */
43 struct PNGAutoClean { 79 struct PNGAutoClean {
44 PNGAutoClean(png_structp p, png_infop i): png_ptr(p), info_ptr(i) {} 80 PNGAutoClean(png_structp p, png_infop i): png_ptr(p), info_ptr(i) {}
45 ~PNGAutoClean() { 81 ~PNGAutoClean() {
46 png_destroy_read_struct(&png_ptr, &info_ptr, NULL); 82 png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
47 } 83 }
48 private: 84 private:
49 png_structp png_ptr; 85 png_structp png_ptr;
50 png_infop info_ptr; 86 png_infop info_ptr;
51 }; 87 };
52 88
53 static void sk_read_fn(png_structp png_ptr, png_bytep data, png_size_t length) { 89 static void sk_read_fn(png_structp png_ptr, png_bytep data, png_size_t length) {
54 SkStream* sk_stream = (SkStream*)png_get_io_ptr(png_ptr); 90 SkStream* sk_stream = (SkStream*) png_ptr->io_ptr;
55 size_t bytes = sk_stream->read(data, length); 91 size_t bytes = sk_stream->read(data, length);
56 if (bytes != length) { 92 if (bytes != length) {
57 png_error(png_ptr, "Read Error!"); 93 png_error(png_ptr, "Read Error!");
58 } 94 }
59 } 95 }
60 96
97 #if defined(SK_BUILD_FOR_ANDROID) && !defined(SK_BUILD_FOR_ANDROID_NDK)
98 static void sk_seek_fn(png_structp png_ptr, png_uint_32 offset) {
99 SkStream* sk_stream = (SkStream*) png_ptr->io_ptr;
100 sk_stream->rewind();
101 (void)sk_stream->skip(offset);
102 }
103 #endif
104
61 static int sk_read_user_chunk(png_structp png_ptr, png_unknown_chunkp chunk) { 105 static int sk_read_user_chunk(png_structp png_ptr, png_unknown_chunkp chunk) {
62 SkImageDecoder::Peeker* peeker = 106 SkImageDecoder::Peeker* peeker =
63 (SkImageDecoder::Peeker*)png_get_user_chunk_ptr(png_ptr); 107 (SkImageDecoder::Peeker*)png_get_user_chunk_ptr(png_ptr);
64 // peek() returning true means continue decoding 108 // peek() returning true means continue decoding
65 return peeker->peek((const char*)chunk->name, chunk->data, chunk->size) ? 109 return peeker->peek((const char*)chunk->name, chunk->data, chunk->size) ?
66 1 : -1; 110 1 : -1;
67 } 111 }
68 112
69 static void sk_error_fn(png_structp png_ptr, png_const_charp msg) { 113 static void sk_error_fn(png_structp png_ptr, png_const_charp msg) {
70 #if 0 114 #if 0
71 SkDebugf("------ png error %s\n", msg); 115 SkDebugf("------ png error %s\n", msg);
72 #endif 116 #endif
73 longjmp(png_jmpbuf(png_ptr), 1); 117 longjmp(png_jmpbuf(png_ptr), 1);
74 } 118 }
75 119
76 static void skip_src_rows(png_structp png_ptr, uint8_t storage[], int count) { 120 static void skip_src_rows(png_structp png_ptr, uint8_t storage[], int count) {
77 for (int i = 0; i < count; i++) { 121 for (int i = 0; i < count; i++) {
78 uint8_t* tmp = storage; 122 uint8_t* tmp = storage;
79 png_read_rows(png_ptr, &tmp, NULL, 1); 123 png_read_rows(png_ptr, &tmp, png_bytepp_NULL, 1);
80 } 124 }
81 } 125 }
82 126
83 static bool pos_le(int value, int max) { 127 static bool pos_le(int value, int max) {
84 return value > 0 && value <= max; 128 return value > 0 && value <= max;
85 } 129 }
86 130
87 static bool substituteTranspColor(SkBitmap* bm, SkPMColor match) { 131 static bool substituteTranspColor(SkBitmap* bm, SkPMColor match) {
88 SkASSERT(bm->config() == SkBitmap::kARGB_8888_Config); 132 SkASSERT(bm->config() == SkBitmap::kARGB_8888_Config);
89 133
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 png_bytep trans; 165 png_bytep trans;
122 int num_trans; 166 int num_trans;
123 167
124 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { 168 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
125 png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL); 169 png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL);
126 return num_trans > 0; 170 return num_trans > 0;
127 } 171 }
128 return false; 172 return false;
129 } 173 }
130 174
131 bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap, 175 bool SkPNGImageDecoder::onDecodeInit(SkStream* sk_stream, png_structp *png_ptrp,
132 Mode mode) { 176 png_infop *info_ptrp) {
133 // SkAutoTrace apr("SkPNGImageDecoder::onDecode");
134
135 /* Create and initialize the png_struct with the desired error handler 177 /* Create and initialize the png_struct with the desired error handler
136 * functions. If you want to use the default stderr and longjump method, 178 * functions. If you want to use the default stderr and longjump method,
137 * you can supply NULL for the last three parameters. We also supply the 179 * you can supply NULL for the last three parameters. We also supply the
138 * the compiler header file version, so that we know if the application 180 * the compiler header file version, so that we know if the application
139 * was compiled with a compatible version of the library. */ 181 * was compiled with a compatible version of the library. */
140 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 182 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
141 NULL, sk_error_fn, NULL); 183 NULL, sk_error_fn, NULL);
142 // png_voidp user_error_ptr, user_error_fn, user_warning_fn); 184 // png_voidp user_error_ptr, user_error_fn, user_warning_fn);
143 if (png_ptr == NULL) { 185 if (png_ptr == NULL) {
144 return false; 186 return false;
145 } 187 }
188 *png_ptrp = png_ptr;
146 189
147 /* Allocate/initialize the memory for image information. */ 190 /* Allocate/initialize the memory for image information. */
148 png_infop info_ptr = png_create_info_struct(png_ptr); 191 png_infop info_ptr = png_create_info_struct(png_ptr);
149 if (info_ptr == NULL) { 192 if (info_ptr == NULL) {
150 png_destroy_read_struct(&png_ptr, NULL, NULL); 193 png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
151 return false; 194 return false;
152 } 195 }
153 196 *info_ptrp = info_ptr;
154 PNGAutoClean autoClean(png_ptr, info_ptr);
155 197
156 /* Set error handling if you are using the setjmp/longjmp method (this is 198 /* Set error handling if you are using the setjmp/longjmp method (this is
157 * the normal method of doing things with libpng). REQUIRED unless you 199 * the normal method of doing things with libpng). REQUIRED unless you
158 * set up your own error handlers in the png_create_read_struct() earlier. 200 * set up your own error handlers in the png_create_read_struct() earlier.
159 */ 201 */
160 if (setjmp(png_jmpbuf(png_ptr))) { 202 if (setjmp(png_jmpbuf(png_ptr))) {
161 return false; 203 return false;
162 } 204 }
163 205
164 /* If you are using replacement read functions, instead of calling 206 /* If you are using replacement read functions, instead of calling
165 * png_init_io() here you would call: 207 * png_init_io() here you would call:
166 */ 208 */
167 png_set_read_fn(png_ptr, (void *)sk_stream, sk_read_fn); 209 png_set_read_fn(png_ptr, (void *)sk_stream, sk_read_fn);
210 #if defined(SK_BUILD_FOR_ANDROID) && !defined(SK_BUILD_FOR_ANDROID_NDK)
211 png_set_seek_fn(png_ptr, sk_seek_fn);
212 #endif
168 /* where user_io_ptr is a structure you want available to the callbacks */ 213 /* where user_io_ptr is a structure you want available to the callbacks */
169 /* If we have already read some of the signature */ 214 /* If we have already read some of the signature */
170 // png_set_sig_bytes(png_ptr, 0 /* sig_read */ ); 215 // png_set_sig_bytes(png_ptr, 0 /* sig_read */ );
171 216
172 // hookup our peeker so we can see any user-chunks the caller may be interes ted in 217 // hookup our peeker so we can see any user-chunks the caller may be interes ted in
173 png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_ALWAYS, (png_byte*)"", 0); 218 png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_ALWAYS, (png_byte*)"", 0);
174 if (this->getPeeker()) { 219 if (this->getPeeker()) {
175 png_set_read_user_chunk_fn(png_ptr, (png_voidp)this->getPeeker(), sk_rea d_user_chunk); 220 png_set_read_user_chunk_fn(png_ptr, (png_voidp)this->getPeeker(), sk_rea d_user_chunk);
176 } 221 }
177 222
178 /* The call to png_read_info() gives us all of the information from the 223 /* The call to png_read_info() gives us all of the information from the
179 * PNG file before the first IDAT (image data chunk). */ 224 * PNG file before the first IDAT (image data chunk). */
180 png_read_info(png_ptr, info_ptr); 225 png_read_info(png_ptr, info_ptr);
181 png_uint_32 origWidth, origHeight; 226 png_uint_32 origWidth, origHeight;
182 int bit_depth, color_type, interlace_type; 227 int bit_depth, color_type, interlace_type;
183 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bit_depth, &color_ type, 228 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bit_depth,
184 &interlace_type, NULL, NULL); 229 &color_type, &interlace_type, int_p_NULL, int_p_NULL);
185 230
186 /* tell libpng to strip 16 bit/color files down to 8 bits/color */ 231 /* tell libpng to strip 16 bit/color files down to 8 bits/color */
187 if (bit_depth == 16) { 232 if (bit_depth == 16) {
188 png_set_strip_16(png_ptr); 233 png_set_strip_16(png_ptr);
189 } 234 }
190 /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single 235 /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single
191 * byte into separate bytes (useful for paletted and grayscale images). */ 236 * byte into separate bytes (useful for paletted and grayscale images). */
192 if (bit_depth < 8) { 237 if (bit_depth < 8) {
193 png_set_packing(png_ptr); 238 png_set_packing(png_ptr);
194 } 239 }
195 /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */ 240 /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */
196 if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { 241 if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
197 png_set_expand_gray_1_2_4_to_8(png_ptr); 242 png_set_gray_1_2_4_to_8(png_ptr);
198 } 243 }
199 244
200 /* Make a grayscale image into RGB. */ 245 /* Make a grayscale image into RGB. */
201 if (color_type == PNG_COLOR_TYPE_GRAY || 246 if (color_type == PNG_COLOR_TYPE_GRAY ||
202 color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { 247 color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
203 png_set_gray_to_rgb(png_ptr); 248 png_set_gray_to_rgb(png_ptr);
204 } 249 }
250 return true;
251 }
252
253 bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap,
254 Mode mode) {
255 png_structp png_ptr;
256 png_infop info_ptr;
257
robertphillips 2013/03/11 18:25:55 !onDecodeInit?
djsollen 2013/03/11 19:43:24 Done.
258 if (onDecodeInit(sk_stream, &png_ptr, &info_ptr) == false) {
259 return false;
260 }
261
262 if (setjmp(png_jmpbuf(png_ptr))) {
263 return false;
264 }
265
266 PNGAutoClean autoClean(png_ptr, info_ptr);
267
268 png_uint_32 origWidth, origHeight;
269 int bit_depth, color_type, interlace_type;
270 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bit_depth,
271 &color_type, &interlace_type, int_p_NULL, int_p_NULL);
205 272
206 SkBitmap::Config config; 273 SkBitmap::Config config;
207 bool hasAlpha = false; 274 bool hasAlpha = false;
208 bool doDither = this->getDitherImage(); 275 bool doDither = this->getDitherImage();
209 SkPMColor theTranspColor = 0; // 0 tells us not to try to match 276 SkPMColor theTranspColor = 0; // 0 tells us not to try to match
210 277
robertphillips 2013/03/11 18:25:55 !getBitmapConfig?
djsollen 2013/03/11 19:43:24 Done.
278 if (getBitmapConfig(png_ptr, info_ptr, &config, &hasAlpha, &doDither,
279 &theTranspColor) == false) {
280 return false;
281 }
282
283 const int sampleSize = this->getSampleSize();
284 SkScaledBitmapSampler sampler(origWidth, origHeight, sampleSize);
285
286 decodedBitmap->lockPixels();
287 void* rowptr = (void*) decodedBitmap->getPixels();
288 bool reuseBitmap = (rowptr != NULL);
289 decodedBitmap->unlockPixels();
290 if (reuseBitmap && (sampler.scaledWidth() != decodedBitmap->width() ||
robertphillips 2013/03/11 18:25:55 intend the next line some more?
djsollen 2013/03/11 19:43:24 Done.
291 sampler.scaledHeight() != decodedBitmap->height())) {
292 // Dimensions must match
293 return false;
294 }
295
296 if (!reuseBitmap) {
297 decodedBitmap->setConfig(config, sampler.scaledWidth(),
298 sampler.scaledHeight(), 0);
299 }
300 if (SkImageDecoder::kDecodeBounds_Mode == mode) {
301 return true;
302 }
303
304 // from here down we are concerned with colortables and pixels
305
306 // we track if we actually see a non-opaque pixels, since sometimes a PNG se ts its colortype
307 // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We care, since we
308 // draw lots faster if we can flag the bitmap has being opaque
309 bool reallyHasAlpha = false;
310 SkColorTable* colorTable = NULL;
311
312 if (color_type == PNG_COLOR_TYPE_PALETTE) {
313 decodePalette(png_ptr, info_ptr, &hasAlpha, &reallyHasAlpha, &colorTable );
314 }
315
316 SkAutoUnref aur(colorTable);
317
318 if (!reuseBitmap) {
319 if (!this->allocPixelRef(decodedBitmap,
320 SkBitmap::kIndex8_Config == config ?
robertphillips 2013/03/11 18:25:55 move this next line up to the end of the prior lin
djsollen 2013/03/11 19:43:24 Done.
321 colorTable : NULL)) {
322 return false;
323 }
324 }
325
326 SkAutoLockPixels alp(*decodedBitmap);
327
328 /* Add filler (or alpha) byte (before/after each RGB triplet) */
329 if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_GRAY) {
330 png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
331 }
332
333 /* Turn on interlace handling. REQUIRED if you are not using
robertphillips 2013/03/11 18:25:55 indent these next lines 1 char?
djsollen 2013/03/11 19:43:24 Done.
334 * png_read_image(). To see how to handle interlacing passes,
335 * see the png_read_row() method below:
336 */
337 const int number_passes = (interlace_type != PNG_INTERLACE_NONE) ?
338 png_set_interlace_handling(png_ptr) : 1;
339
340 /* Optional call to gamma correct and add the background to the palette
341 * and update info structure. REQUIRED if you are expecting libpng to
342 * update the palette for you (ie you selected such a transform above).
343 */
344 png_read_update_info(png_ptr, info_ptr);
345
346 if (SkBitmap::kIndex8_Config == config && 1 == sampleSize) {
347 for (int i = 0; i < number_passes; i++) {
348 for (png_uint_32 y = 0; y < origHeight; y++) {
349 uint8_t* bmRow = decodedBitmap->getAddr8(0, y);
350 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
351 }
352 }
353 } else {
354 SkScaledBitmapSampler::SrcConfig sc;
355 int srcBytesPerPixel = 4;
356
357 if (colorTable != NULL) {
358 sc = SkScaledBitmapSampler::kIndex;
359 srcBytesPerPixel = 1;
360 } else if (hasAlpha) {
361 sc = SkScaledBitmapSampler::kRGBA;
362 } else {
363 sc = SkScaledBitmapSampler::kRGBX;
364 }
365
366 /* We have to pass the colortable explicitly, since we may have one
367 even if our decodedBitmap doesn't, due to the request that we
368 upscale png's palette to a direct model
369 */
370 SkAutoLockColors ctLock(colorTable);
371 if (!sampler.begin(decodedBitmap, sc, doDither, ctLock.colors())) {
372 return false;
373 }
374 const int height = decodedBitmap->height();
375
376 if (number_passes > 1) {
377 SkAutoMalloc storage(origWidth * origHeight * srcBytesPerPixel);
378 uint8_t* base = (uint8_t*)storage.get();
379 size_t rb = origWidth * srcBytesPerPixel;
380
381 for (int i = 0; i < number_passes; i++) {
382 uint8_t* row = base;
383 for (png_uint_32 y = 0; y < origHeight; y++) {
384 uint8_t* bmRow = row;
385 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
386 row += rb;
387 }
388 }
389 // now sample it
390 base += sampler.srcY0() * rb;
391 for (int y = 0; y < height; y++) {
392 reallyHasAlpha |= sampler.next(base);
393 base += sampler.srcDY() * rb;
394 }
395 } else {
396 SkAutoMalloc storage(origWidth * srcBytesPerPixel);
397 uint8_t* srcRow = (uint8_t*)storage.get();
398 skip_src_rows(png_ptr, srcRow, sampler.srcY0());
399
400 for (int y = 0; y < height; y++) {
401 uint8_t* tmp = srcRow;
402 png_read_rows(png_ptr, &tmp, png_bytepp_NULL, 1);
403 reallyHasAlpha |= sampler.next(srcRow);
404 if (y < height - 1) {
405 skip_src_rows(png_ptr, srcRow, sampler.srcDY() - 1);
406 }
407 }
408
409 // skip the rest of the rows (if any)
410 png_uint_32 read = (height - 1) * sampler.srcDY() +
411 sampler.srcY0() + 1;
412 SkASSERT(read <= origHeight);
413 skip_src_rows(png_ptr, srcRow, origHeight - read);
414 }
415 }
416
417 /* read rest of file, and get additional chunks in info_ptr - REQUIRED */
418 png_read_end(png_ptr, info_ptr);
419
420 if (0 != theTranspColor) {
421 reallyHasAlpha |= substituteTranspColor(decodedBitmap, theTranspColor);
422 }
423 decodedBitmap->setIsOpaque(!reallyHasAlpha);
424 if (reuseBitmap) {
425 decodedBitmap->notifyPixelsChanged();
426 }
427 return true;
428 }
429
430
431
432 bool SkPNGImageDecoder::getBitmapConfig(png_structp png_ptr, png_infop info_ptr,
433 SkBitmap::Config *configp, bool *hasAlphap, bool *doDitherp,
434 SkPMColor *theTranspColorp) {
435 png_uint_32 origWidth, origHeight;
436 int bit_depth, color_type, interlace_type;
437 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bit_depth,
438 &color_type, &interlace_type, int_p_NULL, int_p_NULL);
439
211 // check for sBIT chunk data, in case we should disable dithering because 440 // check for sBIT chunk data, in case we should disable dithering because
212 // our data is not truely 8bits per component 441 // our data is not truely 8bits per component
213 if (doDither) { 442 if (*doDitherp) {
214 png_color_8p sig_bit = NULL;
215 bool has_sbit = PNG_INFO_sBIT == png_get_sBIT(png_ptr, info_ptr,
216 &sig_bit);
217 #if 0 443 #if 0
218 if (has_sbit) { 444 SkDebugf("----- sBIT %d %d %d %d\n", info_ptr->sig_bit.red,
219 SkDebugf("----- sBIT %d %d %d %d\n", sig_bit->red, sig_bit->green, 445 info_ptr->sig_bit.green, info_ptr->sig_bit.blue,
220 sig_bit->blue, sig_bit->alpha); 446 info_ptr->sig_bit.alpha);
221 }
222 #endif 447 #endif
223 // 0 seems to indicate no information available 448 // 0 seems to indicate no information available
224 if (has_sbit && pos_le(sig_bit->red, SK_R16_BITS) && 449 if (pos_le(info_ptr->sig_bit.red, SK_R16_BITS) &&
225 pos_le(sig_bit->green, SK_G16_BITS) && 450 pos_le(info_ptr->sig_bit.green, SK_G16_BITS) &&
226 pos_le(sig_bit->blue, SK_B16_BITS)) { 451 pos_le(info_ptr->sig_bit.blue, SK_B16_BITS)) {
227 doDither = false; 452 *doDitherp = false;
228 } 453 }
229 } 454 }
230 455
231 if (color_type == PNG_COLOR_TYPE_PALETTE) { 456 if (color_type == PNG_COLOR_TYPE_PALETTE) {
232 bool paletteHasAlpha = hasTransparencyInPalette(png_ptr, info_ptr); 457 bool paletteHasAlpha = hasTransparencyInPalette(png_ptr, info_ptr);
233 config = this->getPrefConfig(kIndex_SrcDepth, paletteHasAlpha); 458 *configp = this->getPrefConfig(kIndex_SrcDepth, paletteHasAlpha);
234 // now see if we can upscale to their requested config 459 // now see if we can upscale to their requested config
235 if (!canUpscalePaletteToConfig(config, paletteHasAlpha)) { 460 if (!canUpscalePaletteToConfig(*configp, paletteHasAlpha)) {
236 config = SkBitmap::kIndex8_Config; 461 *configp = SkBitmap::kIndex8_Config;
237 } 462 }
238 } else { 463 } else {
239 png_color_16p transpColor = NULL; 464 png_color_16p transpColor = NULL;
240 int numTransp = 0; 465 int numTransp = 0;
241 466
242 png_get_tRNS(png_ptr, info_ptr, NULL, &numTransp, &transpColor); 467 png_get_tRNS(png_ptr, info_ptr, NULL, &numTransp, &transpColor);
243 468
244 bool valid = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS); 469 bool valid = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS);
245 470
246 if (valid && numTransp == 1 && transpColor != NULL) { 471 if (valid && numTransp == 1 && transpColor != NULL) {
247 /* Compute our transparent color, which we'll match against later. 472 /* Compute our transparent color, which we'll match against later.
248 We don't really handle 16bit components properly here, since we 473 We don't really handle 16bit components properly here, since we
249 do our compare *after* the values have been knocked down to 8bit 474 do our compare *after* the values have been knocked down to 8bit
250 which means we will find more matches than we should. The real 475 which means we will find more matches than we should. The real
251 fix seems to be to see the actual 16bit components, do the 476 fix seems to be to see the actual 16bit components, do the
252 compare, and then knock it down to 8bits ourselves. 477 compare, and then knock it down to 8bits ourselves.
253 */ 478 */
254 if (color_type & PNG_COLOR_MASK_COLOR) { 479 if (color_type & PNG_COLOR_MASK_COLOR) {
255 if (16 == bit_depth) { 480 if (16 == bit_depth) {
256 theTranspColor = SkPackARGB32(0xFF, transpColor->red >> 8, 481 *theTranspColorp = SkPackARGB32(0xFF, transpColor->red >> 8,
257 transpColor->green >> 8, transpColor->blue >> 8); 482 transpColor->green >> 8,
483 transpColor->blue >> 8);
258 } else { 484 } else {
259 theTranspColor = SkPackARGB32(0xFF, transpColor->red, 485 *theTranspColorp = SkPackARGB32(0xFF, transpColor->red,
260 transpColor->green, transpColor->blue); 486 transpColor->green,
487 transpColor->blue);
261 } 488 }
262 } else { // gray 489 } else { // gray
263 if (16 == bit_depth) { 490 if (16 == bit_depth) {
264 theTranspColor = SkPackARGB32(0xFF, transpColor->gray >> 8, 491 *theTranspColorp = SkPackARGB32(0xFF, transpColor->gray >> 8 ,
265 transpColor->gray >> 8, transpColor->gray >> 8); 492 transpColor->gray >> 8,
493 transpColor->gray >> 8);
266 } else { 494 } else {
267 theTranspColor = SkPackARGB32(0xFF, transpColor->gray, 495 *theTranspColorp = SkPackARGB32(0xFF, transpColor->gray,
268 transpColor->gray, transpColor->gray); 496 transpColor->gray,
497 transpColor->gray);
269 } 498 }
270 } 499 }
271 } 500 }
272 501
273 if (valid || 502 if (valid ||
274 PNG_COLOR_TYPE_RGB_ALPHA == color_type || 503 PNG_COLOR_TYPE_RGB_ALPHA == color_type ||
275 PNG_COLOR_TYPE_GRAY_ALPHA == color_type) { 504 PNG_COLOR_TYPE_GRAY_ALPHA == color_type) {
276 hasAlpha = true; 505 *hasAlphap = true;
277 } 506 }
278 config = this->getPrefConfig(k32Bit_SrcDepth, hasAlpha); 507 *configp = this->getPrefConfig(k32Bit_SrcDepth, *hasAlphap);
279 // now match the request against our capabilities 508 // now match the request against our capabilities
280 if (hasAlpha) { 509 if (*hasAlphap) {
281 if (config != SkBitmap::kARGB_4444_Config) { 510 if (*configp != SkBitmap::kARGB_4444_Config) {
282 config = SkBitmap::kARGB_8888_Config; 511 *configp = SkBitmap::kARGB_8888_Config;
283 } 512 }
284 } else { 513 } else {
285 if (config != SkBitmap::kRGB_565_Config && 514 if (*configp != SkBitmap::kRGB_565_Config &&
286 config != SkBitmap::kARGB_4444_Config) { 515 *configp != SkBitmap::kARGB_4444_Config) {
287 config = SkBitmap::kARGB_8888_Config; 516 *configp = SkBitmap::kARGB_8888_Config;
288 } 517 }
289 } 518 }
290 } 519 }
291 520
292 // sanity check for size 521 // sanity check for size
293 { 522 {
294 Sk64 size; 523 Sk64 size;
295 size.setMul(origWidth, origHeight); 524 size.setMul(origWidth, origHeight);
296 if (size.isNeg() || !size.is32()) { 525 if (size.isNeg() || !size.is32()) {
297 return false; 526 return false;
298 } 527 }
299 // now check that if we are 4-bytes per pixel, we also don't overflow 528 // now check that if we are 4-bytes per pixel, we also don't overflow
300 if (size.get32() > (0x7FFFFFFF >> 2)) { 529 if (size.get32() > (0x7FFFFFFF >> 2)) {
301 return false; 530 return false;
302 } 531 }
303 } 532 }
304 533
robertphillips 2013/03/11 18:25:55 just "return this->chooseFromOneChoise ..."?
djsollen 2013/03/11 19:43:24 Done.
305 if (!this->chooseFromOneChoice(config, origWidth, origHeight)) { 534 if (!this->chooseFromOneChoice(*configp, origWidth, origHeight)) {
535 return false;
536 }
537 return true;
538 }
539
540 bool SkPNGImageDecoder::decodePalette(png_structp png_ptr, png_infop info_ptr,
541 bool *hasAlphap, bool *reallyHasAlphap,
542 SkColorTable **colorTablep) {
543 int num_palette;
544 png_colorp palette;
545 png_bytep trans;
546 int num_trans;
547 bool reallyHasAlpha = false;
548 SkColorTable* colorTable = NULL;
549
550 png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
551
552 /* BUGGY IMAGE WORKAROUND
553
554 We hit some images (e.g. fruit_.png) who contain bytes that are == color table_count
555 which is a problem since we use the byte as an index. To work around thi s we grow
556 the colortable by 1 (if its < 256) and duplicate the last color into tha t slot.
557 */
558 int colorCount = num_palette + (num_palette < 256);
559
560 colorTable = SkNEW_ARGS(SkColorTable, (colorCount));
561
562 SkPMColor* colorPtr = colorTable->lockColors();
563 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
564 png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL);
565 *hasAlphap = (num_trans > 0);
566 } else {
567 num_trans = 0;
568 colorTable->setFlags(colorTable->getFlags() | SkColorTable::kColorsAreOp aque_Flag);
569 }
570 // check for bad images that might make us crash
571 if (num_trans > num_palette) {
572 num_trans = num_palette;
573 }
574
575 int index = 0;
576 int transLessThanFF = 0;
577
578 for (; index < num_trans; index++) {
579 transLessThanFF |= (int)*trans - 0xFF;
580 *colorPtr++ = SkPreMultiplyARGB(*trans++, palette->red, palette->green, palette->blue);
581 palette++;
582 }
583 reallyHasAlpha |= (transLessThanFF < 0);
584
585 for (; index < num_palette; index++) {
586 *colorPtr++ = SkPackARGB32(0xFF, palette->red, palette->green, palette-> blue);
587 palette++;
588 }
589
590 // see BUGGY IMAGE WORKAROUND comment above
591 if (num_palette < 256) {
592 *colorPtr = colorPtr[-1];
593 }
594 colorTable->unlockColors(true);
595 *colorTablep = colorTable;
596 *reallyHasAlphap = reallyHasAlpha;
597 return true;
598 }
599
600 #if defined(SK_BUILD_FOR_ANDROID) && !defined(SK_BUILD_FOR_ANDROID_NDK)
601
602 bool SkPNGImageDecoder::onBuildTileIndex(SkStream* sk_stream, int *width, int *h eight) {
603 png_structp png_ptr;
604 png_infop info_ptr;
605
606 if (onDecodeInit(sk_stream, &png_ptr, &info_ptr) == false) {
607 return false;
608 }
609
610 if (setjmp(png_jmpbuf(png_ptr)) != 0) {
611 png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
612 return false;
613 }
614
615 int bit_depth, color_type, interlace_type;
616 png_uint_32 origWidth, origHeight;
617 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bit_depth,
618 &color_type, &interlace_type, int_p_NULL, int_p_NULL);
619
620 *width = origWidth;
621 *height = origHeight;
622
623 png_build_index(png_ptr);
624 this->fImageIndex = new SkPNGImageIndex(png_ptr, info_ptr);
625
626 return true;
627 }
628
629 bool SkPNGImageDecoder::onDecodeRegion(SkBitmap* bm, SkIRect& region) {
630 png_structp png_ptr = this->fImageIndex->png_ptr;
631 png_infop info_ptr = this->fImageIndex->info_ptr;
632 if (setjmp(png_jmpbuf(png_ptr))) {
633 return false;
634 }
635
636 png_uint_32 origWidth, origHeight;
637 int bit_depth, color_type, interlace_type;
638 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bit_depth,
639 &color_type, &interlace_type, int_p_NULL, int_p_NULL);
640
641 SkIRect rect = SkIRect::MakeWH(origWidth, origHeight);
642
643 if (!rect.intersect(region)) {
644 // If the requested region is entirely outsides the image, just
645 // returns false
646 return false;
647 }
648
649 SkBitmap::Config config;
650 bool hasAlpha = false;
651 bool doDither = this->getDitherImage();
652 SkPMColor theTranspColor = 0; // 0 tells us not to try to match
653
654 if (getBitmapConfig(png_ptr, info_ptr, &config, &hasAlpha, &doDither,
655 &theTranspColor) == false) {
306 return false; 656 return false;
307 } 657 }
308 658
309 const int sampleSize = this->getSampleSize(); 659 const int sampleSize = this->getSampleSize();
310 SkScaledBitmapSampler sampler(origWidth, origHeight, sampleSize); 660 SkScaledBitmapSampler sampler(origWidth, rect.height(), sampleSize);
661
662 SkBitmap *decodedBitmap = new SkBitmap;
663 SkAutoTDelete<SkBitmap> adb(decodedBitmap);
311 664
312 decodedBitmap->setConfig(config, sampler.scaledWidth(), 665 decodedBitmap->setConfig(config, sampler.scaledWidth(),
313 sampler.scaledHeight(), 0); 666 sampler.scaledHeight(), 0);
314 if (SkImageDecoder::kDecodeBounds_Mode == mode) {
315 return true;
316 }
317 667
318 // from here down we are concerned with colortables and pixels 668 // from here down we are concerned with colortables and pixels
319 669
320 // we track if we actually see a non-opaque pixels, since sometimes a PNG se ts its colortype 670 // we track if we actually see a non-opaque pixels, since sometimes a PNG se ts its colortype
321 // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We care, since we 671 // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We care, since we
322 // draw lots faster if we can flag the bitmap has being opaque 672 // draw lots faster if we can flag the bitmap has being opaque
323 bool reallyHasAlpha = false; 673 bool reallyHasAlpha = false;
324 SkColorTable* colorTable = NULL; 674 SkColorTable* colorTable = NULL;
325 675
326 if (color_type == PNG_COLOR_TYPE_PALETTE) { 676 if (color_type == PNG_COLOR_TYPE_PALETTE) {
327 int num_palette; 677 decodePalette(png_ptr, info_ptr, &hasAlpha,
328 png_colorp palette; 678 &reallyHasAlpha, &colorTable);
329 png_bytep trans;
330 int num_trans;
331
332 png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
333
334 /* BUGGY IMAGE WORKAROUND
335
336 We hit some images (e.g. fruit_.png) who contain bytes that are == c olortable_count
337 which is a problem since we use the byte as an index. To work around this we grow
338 the colortable by 1 (if its < 256) and duplicate the last color into that slot.
339 */
340 int colorCount = num_palette + (num_palette < 256);
341
342 colorTable = SkNEW_ARGS(SkColorTable, (colorCount));
343
344 SkPMColor* colorPtr = colorTable->lockColors();
345 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
346 png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL);
347 hasAlpha = (num_trans > 0);
348 } else {
349 num_trans = 0;
350 colorTable->setFlags(colorTable->getFlags() | SkColorTable::kColorsA reOpaque_Flag);
351 }
352 // check for bad images that might make us crash
353 if (num_trans > num_palette) {
354 num_trans = num_palette;
355 }
356
357 int index = 0;
358 int transLessThanFF = 0;
359
360 for (; index < num_trans; index++) {
361 transLessThanFF |= (int)*trans - 0xFF;
362 *colorPtr++ = SkPreMultiplyARGB(*trans++, palette->red, palette->gre en, palette->blue);
363 palette++;
364 }
365 reallyHasAlpha |= (transLessThanFF < 0);
366
367 for (; index < num_palette; index++) {
368 *colorPtr++ = SkPackARGB32(0xFF, palette->red, palette->green, palet te->blue);
369 palette++;
370 }
371
372 // see BUGGY IMAGE WORKAROUND comment above
373 if (num_palette < 256) {
374 *colorPtr = colorPtr[-1];
375 }
376 colorTable->unlockColors(true);
377 } 679 }
378 680
379 SkAutoUnref aur(colorTable); 681 SkAutoUnref aur(colorTable);
380 682
381 if (!this->allocPixelRef(decodedBitmap, 683 // Check ahead of time if the swap(dest, src) is possible in crop or not.
382 SkBitmap::kIndex8_Config == config ? 684 // If yes, then we will stick to AllocPixelRef since it's cheaper with the s wap happening.
383 colorTable : NULL)) { 685 // If no, then we will use alloc to allocate pixels to prevent garbage colle ction.
384 return false; 686 int w = rect.width() / sampleSize;
687 int h = rect.height() / sampleSize;
688 bool swapOnly = (rect == region) && (w == decodedBitmap->width()) &&
689 (h == decodedBitmap->height()) &&
690 ((0 - rect.x()) / sampleSize == 0) && bm->isNull();
691 if (swapOnly) {
692 if (!this->allocPixelRef(decodedBitmap,
693 SkBitmap::kIndex8_Config == config ? colorTable : NULL)) {
694 return false;
695 }
696 } else {
697 if (!decodedBitmap->allocPixels(
698 NULL, SkBitmap::kIndex8_Config == config ? colorTable : NULL)) {
699 return false;
700 }
385 } 701 }
386
387 SkAutoLockPixels alp(*decodedBitmap); 702 SkAutoLockPixels alp(*decodedBitmap);
388 703
389 /* swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */
390 // if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
391 // ; // png_set_swap_alpha(png_ptr);
392
393 /* swap bytes of 16 bit files to least significant byte first */
394 // png_set_swap(png_ptr);
395
396 /* Add filler (or alpha) byte (before/after each RGB triplet) */ 704 /* Add filler (or alpha) byte (before/after each RGB triplet) */
397 if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_GRAY) { 705 if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_GRAY) {
398 png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); 706 png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
399 } 707 }
400 708
401 /* Turn on interlace handling. REQUIRED if you are not using 709 /* Turn on interlace handling. REQUIRED if you are not using
402 * png_read_image(). To see how to handle interlacing passes, 710 * png_read_image(). To see how to handle interlacing passes,
403 * see the png_read_row() method below: 711 * see the png_read_row() method below:
404 */ 712 */
405 const int number_passes = interlace_type != PNG_INTERLACE_NONE ? 713 const int number_passes = interlace_type != PNG_INTERLACE_NONE ?
406 png_set_interlace_handling(png_ptr) : 1; 714 png_set_interlace_handling(png_ptr) : 1;
407 715
408 /* Optional call to gamma correct and add the background to the palette 716 /* Optional call to gamma correct and add the background to the palette
409 * and update info structure. REQUIRED if you are expecting libpng to 717 * and update info structure. REQUIRED if you are expecting libpng to
410 * update the palette for you (ie you selected such a transform above). 718 * update the palette for you (ie you selected such a transform above).
411 */ 719 */
720 png_ptr->pass = 0;
412 png_read_update_info(png_ptr, info_ptr); 721 png_read_update_info(png_ptr, info_ptr);
413 722
723 int actualTop = rect.fTop;
724
414 if (SkBitmap::kIndex8_Config == config && 1 == sampleSize) { 725 if (SkBitmap::kIndex8_Config == config && 1 == sampleSize) {
415 for (int i = 0; i < number_passes; i++) { 726 for (int i = 0; i < number_passes; i++) {
727 png_configure_decoder(png_ptr, &actualTop, i);
728 for (int j = 0; j < rect.fTop - actualTop; j++) {
729 uint8_t* bmRow = decodedBitmap->getAddr8(0, 0);
730 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
731 }
416 for (png_uint_32 y = 0; y < origHeight; y++) { 732 for (png_uint_32 y = 0; y < origHeight; y++) {
417 uint8_t* bmRow = decodedBitmap->getAddr8(0, y); 733 uint8_t* bmRow = decodedBitmap->getAddr8(0, y);
418 png_read_rows(png_ptr, &bmRow, NULL, 1); 734 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
419 } 735 }
420 } 736 }
421 } else { 737 } else {
422 SkScaledBitmapSampler::SrcConfig sc; 738 SkScaledBitmapSampler::SrcConfig sc;
423 int srcBytesPerPixel = 4; 739 int srcBytesPerPixel = 4;
424 740
425 if (colorTable != NULL) { 741 if (colorTable != NULL) {
426 sc = SkScaledBitmapSampler::kIndex; 742 sc = SkScaledBitmapSampler::kIndex;
427 srcBytesPerPixel = 1; 743 srcBytesPerPixel = 1;
428 } else if (hasAlpha) { 744 } else if (hasAlpha) {
(...skipping 11 matching lines...) Expand all
440 return false; 756 return false;
441 } 757 }
442 const int height = decodedBitmap->height(); 758 const int height = decodedBitmap->height();
443 759
444 if (number_passes > 1) { 760 if (number_passes > 1) {
445 SkAutoMalloc storage(origWidth * origHeight * srcBytesPerPixel); 761 SkAutoMalloc storage(origWidth * origHeight * srcBytesPerPixel);
446 uint8_t* base = (uint8_t*)storage.get(); 762 uint8_t* base = (uint8_t*)storage.get();
447 size_t rb = origWidth * srcBytesPerPixel; 763 size_t rb = origWidth * srcBytesPerPixel;
448 764
449 for (int i = 0; i < number_passes; i++) { 765 for (int i = 0; i < number_passes; i++) {
766 png_configure_decoder(png_ptr, &actualTop, i);
767 for (int j = 0; j < rect.fTop - actualTop; j++) {
768 uint8_t* bmRow = (uint8_t*)decodedBitmap->getPixels();
769 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
770 }
450 uint8_t* row = base; 771 uint8_t* row = base;
451 for (png_uint_32 y = 0; y < origHeight; y++) { 772 for (int32_t y = 0; y < rect.height(); y++) {
452 uint8_t* bmRow = row; 773 uint8_t* bmRow = row;
453 png_read_rows(png_ptr, &bmRow, NULL, 1); 774 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
454 row += rb; 775 row += rb;
455 } 776 }
456 } 777 }
457 // now sample it 778 // now sample it
458 base += sampler.srcY0() * rb; 779 base += sampler.srcY0() * rb;
459 for (int y = 0; y < height; y++) { 780 for (int y = 0; y < height; y++) {
460 reallyHasAlpha |= sampler.next(base); 781 reallyHasAlpha |= sampler.next(base);
461 base += sampler.srcDY() * rb; 782 base += sampler.srcDY() * rb;
462 } 783 }
463 } else { 784 } else {
464 SkAutoMalloc storage(origWidth * srcBytesPerPixel); 785 SkAutoMalloc storage(origWidth * srcBytesPerPixel);
465 uint8_t* srcRow = (uint8_t*)storage.get(); 786 uint8_t* srcRow = (uint8_t*)storage.get();
787
788 png_configure_decoder(png_ptr, &actualTop, 0);
466 skip_src_rows(png_ptr, srcRow, sampler.srcY0()); 789 skip_src_rows(png_ptr, srcRow, sampler.srcY0());
467 790
791 for (int i = 0; i < rect.fTop - actualTop; i++) {
792 uint8_t* bmRow = (uint8_t*)decodedBitmap->getPixels();
793 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
794 }
468 for (int y = 0; y < height; y++) { 795 for (int y = 0; y < height; y++) {
469 uint8_t* tmp = srcRow; 796 uint8_t* tmp = srcRow;
470 png_read_rows(png_ptr, &tmp, NULL, 1); 797 png_read_rows(png_ptr, &tmp, png_bytepp_NULL, 1);
471 reallyHasAlpha |= sampler.next(srcRow); 798 reallyHasAlpha |= sampler.next(srcRow);
472 if (y < height - 1) { 799 if (y < height - 1) {
473 skip_src_rows(png_ptr, srcRow, sampler.srcDY() - 1); 800 skip_src_rows(png_ptr, srcRow, sampler.srcDY() - 1);
474 } 801 }
475 } 802 }
476
477 // skip the rest of the rows (if any)
478 png_uint_32 read = (height - 1) * sampler.srcDY() +
479 sampler.srcY0() + 1;
480 SkASSERT(read <= origHeight);
481 skip_src_rows(png_ptr, srcRow, origHeight - read);
482 } 803 }
483 } 804 }
484 805 if (swapOnly) {
485 /* read rest of file, and get additional chunks in info_ptr - REQUIRED */ 806 bm->swap(*decodedBitmap);
486 png_read_end(png_ptr, info_ptr); 807 } else {
808 cropBitmap(bm, decodedBitmap, sampleSize, region.x(), region.y(),
809 region.width(), region.height(), 0, rect.y());
810 }
487 811
488 if (0 != theTranspColor) { 812 if (0 != theTranspColor) {
489 reallyHasAlpha |= substituteTranspColor(decodedBitmap, theTranspColor); 813 reallyHasAlpha |= substituteTranspColor(decodedBitmap, theTranspColor);
490 } 814 }
491 decodedBitmap->setIsOpaque(!reallyHasAlpha); 815 decodedBitmap->setIsOpaque(!reallyHasAlpha);
492 return true; 816 return true;
493 } 817 }
818 #endif
494 819
495 /////////////////////////////////////////////////////////////////////////////// 820 ///////////////////////////////////////////////////////////////////////////////
496 821
497 #include "SkColorPriv.h" 822 #include "SkColorPriv.h"
498 #include "SkUnPreMultiply.h" 823 #include "SkUnPreMultiply.h"
499 824
500 static void sk_write_fn(png_structp png_ptr, png_bytep data, png_size_t len) { 825 static void sk_write_fn(png_structp png_ptr, png_bytep data, png_size_t len) {
501 SkWStream* sk_stream = (SkWStream*)png_get_io_ptr(png_ptr); 826 SkWStream* sk_stream = (SkWStream*)png_ptr->io_ptr;
502 if (!sk_stream->write(data, len)) { 827 if (!sk_stream->write(data, len)) {
503 png_error(png_ptr, "sk_write_fn Error!"); 828 png_error(png_ptr, "sk_write_fn Error!");
504 } 829 }
505 } 830 }
506 831
507 static transform_scanline_proc choose_proc(SkBitmap::Config config, 832 static transform_scanline_proc choose_proc(SkBitmap::Config config,
508 bool hasAlpha) { 833 bool hasAlpha) {
509 // we don't care about search on alpha if we're kIndex8, since only the 834 // we don't care about search on alpha if we're kIndex8, since only the
510 // colortable packing cares about that distinction, not the pixels 835 // colortable packing cares about that distinction, not the pixels
511 if (SkBitmap::kIndex8_Config == config) { 836 if (SkBitmap::kIndex8_Config == config) {
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
690 png_infop info_ptr; 1015 png_infop info_ptr;
691 1016
692 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, sk_error_fn, 1017 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, sk_error_fn,
693 NULL); 1018 NULL);
694 if (NULL == png_ptr) { 1019 if (NULL == png_ptr) {
695 return false; 1020 return false;
696 } 1021 }
697 1022
698 info_ptr = png_create_info_struct(png_ptr); 1023 info_ptr = png_create_info_struct(png_ptr);
699 if (NULL == info_ptr) { 1024 if (NULL == info_ptr) {
700 png_destroy_write_struct(&png_ptr, NULL); 1025 png_destroy_write_struct(&png_ptr, png_infopp_NULL);
701 return false; 1026 return false;
702 } 1027 }
703 1028
704 /* Set error handling. REQUIRED if you aren't supplying your own 1029 /* Set error handling. REQUIRED if you aren't supplying your own
705 * error handling functions in the png_create_write_struct() call. 1030 * error handling functions in the png_create_write_struct() call.
706 */ 1031 */
707 if (setjmp(png_jmpbuf(png_ptr))) { 1032 if (setjmp(png_jmpbuf(png_ptr))) {
708 png_destroy_write_struct(&png_ptr, &info_ptr); 1033 png_destroy_write_struct(&png_ptr, &info_ptr);
709 return false; 1034 return false;
710 } 1035 }
711 1036
712 png_set_write_fn(png_ptr, (void*)stream, sk_write_fn, NULL); 1037 png_set_write_fn(png_ptr, (void*)stream, sk_write_fn, png_flush_ptr_NULL);
713 1038
714 /* Set the image information here. Width and height are up to 2^31, 1039 /* Set the image information here. Width and height are up to 2^31,
715 * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on 1040 * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
716 * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY, 1041 * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
717 * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB, 1042 * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
718 * or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or 1043 * or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or
719 * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST 1044 * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
720 * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED 1045 * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
721 */ 1046 */
722 1047
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
779 } 1104 }
780 return NULL; 1105 return NULL;
781 } 1106 }
782 1107
783 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { 1108 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) {
784 return (SkImageEncoder::kPNG_Type == t) ? SkNEW(SkPNGImageEncoder) : NULL; 1109 return (SkImageEncoder::kPNG_Type == t) ? SkNEW(SkPNGImageEncoder) : NULL;
785 } 1110 }
786 1111
787 static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(sk_libpng_efacto ry); 1112 static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(sk_libpng_efacto ry);
788 static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(sk_libpng_dfactory); 1113 static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(sk_libpng_dfactory);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698