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

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: update png 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
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() {
33 if (NULL != 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:
28 virtual Format getFormat() const { 44 SkPNGImageDecoder() {
45 fImageIndex = NULL;
46 }
47 virtual Format getFormat() const SK_OVERRIDE {
29 return kPNG_Format; 48 return kPNG_Format;
30 } 49 }
50 virtual ~SkPNGImageDecoder() {
51 SkDELETE(fImageIndex);
52 }
31 53
32 protected: 54 protected:
33 virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode); 55 #ifdef SK_BUILD_FOR_ANDROID
56 virtual bool onBuildTileIndex(SkStream *stream, int *width, int *height) SK_ OVERRIDE;
57 virtual bool onDecodeRegion(SkBitmap* bitmap, const SkIRect& region) SK_OVER RIDE;
58 #endif
59 virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE;
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
robertphillips 2013/03/13 13:41:29 Isn't the order supposed to be member variables th
djsollen 2013/03/13 16:02:48 That is opposite of android, but you are correct.
69 SkPNGImageIndex* fImageIndex;
70
71 typedef SkImageDecoder INHERITED;
34 }; 72 };
35 73
36 #ifndef png_jmpbuf 74 #ifndef png_jmpbuf
37 # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) 75 # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
38 #endif 76 #endif
39 77
40 #define PNG_BYTES_TO_CHECK 4 78 #define PNG_BYTES_TO_CHECK 4
41 79
42 /* Automatically clean up after throwing an exception */ 80 /* Automatically clean up after throwing an exception */
43 struct PNGAutoClean { 81 struct PNGAutoClean {
44 PNGAutoClean(png_structp p, png_infop i): png_ptr(p), info_ptr(i) {} 82 PNGAutoClean(png_structp p, png_infop i): png_ptr(p), info_ptr(i) {}
45 ~PNGAutoClean() { 83 ~PNGAutoClean() {
46 png_destroy_read_struct(&png_ptr, &info_ptr, NULL); 84 png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
47 } 85 }
48 private: 86 private:
49 png_structp png_ptr; 87 png_structp png_ptr;
50 png_infop info_ptr; 88 png_infop info_ptr;
51 }; 89 };
52 90
53 static void sk_read_fn(png_structp png_ptr, png_bytep data, png_size_t length) { 91 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); 92 SkStream* sk_stream = (SkStream*) png_ptr->io_ptr;
55 size_t bytes = sk_stream->read(data, length); 93 size_t bytes = sk_stream->read(data, length);
56 if (bytes != length) { 94 if (bytes != length) {
57 png_error(png_ptr, "Read Error!"); 95 png_error(png_ptr, "Read Error!");
58 } 96 }
59 } 97 }
60 98
99 #ifdef SK_BUILD_FOR_ANDROID
100 static void sk_seek_fn(png_structp png_ptr, png_uint_32 offset) {
101 SkStream* sk_stream = (SkStream*) png_ptr->io_ptr;
102 sk_stream->rewind();
103 (void)sk_stream->skip(offset);
104 }
105 #endif
106
61 static int sk_read_user_chunk(png_structp png_ptr, png_unknown_chunkp chunk) { 107 static int sk_read_user_chunk(png_structp png_ptr, png_unknown_chunkp chunk) {
62 SkImageDecoder::Peeker* peeker = 108 SkImageDecoder::Peeker* peeker =
63 (SkImageDecoder::Peeker*)png_get_user_chunk_ptr(png_ptr); 109 (SkImageDecoder::Peeker*)png_get_user_chunk_ptr(png_ptr);
64 // peek() returning true means continue decoding 110 // peek() returning true means continue decoding
65 return peeker->peek((const char*)chunk->name, chunk->data, chunk->size) ? 111 return peeker->peek((const char*)chunk->name, chunk->data, chunk->size) ?
66 1 : -1; 112 1 : -1;
67 } 113 }
68 114
69 static void sk_error_fn(png_structp png_ptr, png_const_charp msg) { 115 static void sk_error_fn(png_structp png_ptr, png_const_charp msg) {
70 #if 0 116 SkDEBUGF(("------ png error %s\n", msg));
71 SkDebugf("------ png error %s\n", msg);
72 #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 #ifdef SK_BUILD_FOR_ANDROID
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
258 if (!onDecodeInit(sk_stream, &png_ptr, &info_ptr)) {
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
278 if (!getBitmapConfig(png_ptr, info_ptr, &config, &hasAlpha, &doDither, &theT ranspColor)) {
279 return false;
280 }
281
282 const int sampleSize = this->getSampleSize();
283 SkScaledBitmapSampler sampler(origWidth, origHeight, sampleSize);
284
285 decodedBitmap->lockPixels();
286 void* rowptr = (void*) decodedBitmap->getPixels();
287 bool reuseBitmap = (rowptr != NULL);
288 decodedBitmap->unlockPixels();
289 if (reuseBitmap && (sampler.scaledWidth() != decodedBitmap->width() ||
290 sampler.scaledHeight() != decodedBitmap->height())) {
291 // Dimensions must match
292 return false;
293 }
294
295 if (!reuseBitmap) {
296 decodedBitmap->setConfig(config, sampler.scaledWidth(),
297 sampler.scaledHeight(), 0);
298 }
299 if (SkImageDecoder::kDecodeBounds_Mode == mode) {
300 return true;
301 }
302
303 // from here down we are concerned with colortables and pixels
304
305 // we track if we actually see a non-opaque pixels, since sometimes a PNG se ts its colortype
306 // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We care, since we
307 // draw lots faster if we can flag the bitmap has being opaque
308 bool reallyHasAlpha = false;
309 SkColorTable* colorTable = NULL;
310
311 if (color_type == PNG_COLOR_TYPE_PALETTE) {
312 decodePalette(png_ptr, info_ptr, &hasAlpha, &reallyHasAlpha, &colorTable );
313 }
314
315 SkAutoUnref aur(colorTable);
316
317 if (!reuseBitmap) {
318 if (!this->allocPixelRef(decodedBitmap,
319 SkBitmap::kIndex8_Config == config ? colorTable : NULL)) {
320 return false;
321 }
322 }
323
324 SkAutoLockPixels alp(*decodedBitmap);
325
326 /* Add filler (or alpha) byte (before/after each RGB triplet) */
327 if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_GRAY) {
328 png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
329 }
330
331 /* Turn on interlace handling. REQUIRED if you are not using
332 * png_read_image(). To see how to handle interlacing passes,
333 * see the png_read_row() method below:
334 */
335 const int number_passes = (interlace_type != PNG_INTERLACE_NONE) ?
336 png_set_interlace_handling(png_ptr) : 1;
337
338 /* Optional call to gamma correct and add the background to the palette
339 * and update info structure. REQUIRED if you are expecting libpng to
340 * update the palette for you (ie you selected such a transform above).
341 */
342 png_read_update_info(png_ptr, info_ptr);
343
344 if (SkBitmap::kIndex8_Config == config && 1 == sampleSize) {
robertphillips 2013/03/13 13:41:29 preincrement - ignore if you desire
345 for (int i = 0; i < number_passes; i++) {
346 for (png_uint_32 y = 0; y < origHeight; y++) {
347 uint8_t* bmRow = decodedBitmap->getAddr8(0, y);
348 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
349 }
350 }
351 } else {
352 SkScaledBitmapSampler::SrcConfig sc;
353 int srcBytesPerPixel = 4;
354
355 if (colorTable != NULL) {
356 sc = SkScaledBitmapSampler::kIndex;
357 srcBytesPerPixel = 1;
358 } else if (hasAlpha) {
359 sc = SkScaledBitmapSampler::kRGBA;
360 } else {
361 sc = SkScaledBitmapSampler::kRGBX;
362 }
363
364 /* We have to pass the colortable explicitly, since we may have one
365 even if our decodedBitmap doesn't, due to the request that we
366 upscale png's palette to a direct model
367 */
368 SkAutoLockColors ctLock(colorTable);
369 if (!sampler.begin(decodedBitmap, sc, doDither, ctLock.colors())) {
370 return false;
371 }
372 const int height = decodedBitmap->height();
373
374 if (number_passes > 1) {
375 SkAutoMalloc storage(origWidth * origHeight * srcBytesPerPixel);
376 uint8_t* base = (uint8_t*)storage.get();
robertphillips 2013/03/13 13:41:29 rb -> rowBytes?
djsollen 2013/03/13 16:02:48 Done.
377 size_t rb = origWidth * srcBytesPerPixel;
378
379 for (int i = 0; i < number_passes; i++) {
380 uint8_t* row = base;
381 for (png_uint_32 y = 0; y < origHeight; y++) {
382 uint8_t* bmRow = row;
383 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
384 row += rb;
385 }
386 }
387 // now sample it
388 base += sampler.srcY0() * rb;
389 for (int y = 0; y < height; y++) {
390 reallyHasAlpha |= sampler.next(base);
391 base += sampler.srcDY() * rb;
392 }
393 } else {
394 SkAutoMalloc storage(origWidth * srcBytesPerPixel);
395 uint8_t* srcRow = (uint8_t*)storage.get();
396 skip_src_rows(png_ptr, srcRow, sampler.srcY0());
397
398 for (int y = 0; y < height; y++) {
399 uint8_t* tmp = srcRow;
400 png_read_rows(png_ptr, &tmp, png_bytepp_NULL, 1);
401 reallyHasAlpha |= sampler.next(srcRow);
402 if (y < height - 1) {
403 skip_src_rows(png_ptr, srcRow, sampler.srcDY() - 1);
404 }
405 }
406
407 // skip the rest of the rows (if any)
408 png_uint_32 read = (height - 1) * sampler.srcDY() +
409 sampler.srcY0() + 1;
410 SkASSERT(read <= origHeight);
411 skip_src_rows(png_ptr, srcRow, origHeight - read);
412 }
413 }
414
415 /* read rest of file, and get additional chunks in info_ptr - REQUIRED */
416 png_read_end(png_ptr, info_ptr);
417
418 if (0 != theTranspColor) {
419 reallyHasAlpha |= substituteTranspColor(decodedBitmap, theTranspColor);
420 }
421 decodedBitmap->setIsOpaque(!reallyHasAlpha);
422 if (reuseBitmap) {
423 decodedBitmap->notifyPixelsChanged();
424 }
425 return true;
426 }
427
428
429
430 bool SkPNGImageDecoder::getBitmapConfig(png_structp png_ptr, png_infop info_ptr,
robertphillips 2013/03/13 13:41:29 indent the following two lines?
djsollen 2013/03/13 16:02:48 Done.
431 SkBitmap::Config *configp, bool *hasAlphap, bool *doDitherp,
432 SkPMColor *theTranspColorp) {
433 png_uint_32 origWidth, origHeight;
434 int bit_depth, color_type, interlace_type;
435 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bit_depth,
robertphillips 2013/03/13 13:41:29 indent next line?
djsollen 2013/03/13 16:02:48 Done.
436 &color_type, &interlace_type, int_p_NULL, int_p_NULL);
437
211 // check for sBIT chunk data, in case we should disable dithering because 438 // check for sBIT chunk data, in case we should disable dithering because
212 // our data is not truely 8bits per component 439 // our data is not truely 8bits per component
213 if (doDither) { 440 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 441 #if 0
218 if (has_sbit) { 442 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, 443 info_ptr->sig_bit.green, info_ptr->sig_bit.blue,
220 sig_bit->blue, sig_bit->alpha); 444 info_ptr->sig_bit.alpha);
221 }
222 #endif 445 #endif
223 // 0 seems to indicate no information available 446 // 0 seems to indicate no information available
224 if (has_sbit && pos_le(sig_bit->red, SK_R16_BITS) && 447 if (pos_le(info_ptr->sig_bit.red, SK_R16_BITS) &&
robertphillips 2013/03/13 13:41:29 fix indent?
djsollen 2013/03/13 16:02:48 Done.
225 pos_le(sig_bit->green, SK_G16_BITS) && 448 pos_le(info_ptr->sig_bit.green, SK_G16_BITS) &&
226 pos_le(sig_bit->blue, SK_B16_BITS)) { 449 pos_le(info_ptr->sig_bit.blue, SK_B16_BITS)) {
227 doDither = false; 450 *doDitherp = false;
228 } 451 }
229 } 452 }
230 453
231 if (color_type == PNG_COLOR_TYPE_PALETTE) { 454 if (color_type == PNG_COLOR_TYPE_PALETTE) {
232 bool paletteHasAlpha = hasTransparencyInPalette(png_ptr, info_ptr); 455 bool paletteHasAlpha = hasTransparencyInPalette(png_ptr, info_ptr);
233 config = this->getPrefConfig(kIndex_SrcDepth, paletteHasAlpha); 456 *configp = this->getPrefConfig(kIndex_SrcDepth, paletteHasAlpha);
234 // now see if we can upscale to their requested config 457 // now see if we can upscale to their requested config
235 if (!canUpscalePaletteToConfig(config, paletteHasAlpha)) { 458 if (!canUpscalePaletteToConfig(*configp, paletteHasAlpha)) {
236 config = SkBitmap::kIndex8_Config; 459 *configp = SkBitmap::kIndex8_Config;
237 } 460 }
238 } else { 461 } else {
239 png_color_16p transpColor = NULL; 462 png_color_16p transpColor = NULL;
240 int numTransp = 0; 463 int numTransp = 0;
241 464
242 png_get_tRNS(png_ptr, info_ptr, NULL, &numTransp, &transpColor); 465 png_get_tRNS(png_ptr, info_ptr, NULL, &numTransp, &transpColor);
243 466
244 bool valid = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS); 467 bool valid = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS);
245 468
246 if (valid && numTransp == 1 && transpColor != NULL) { 469 if (valid && numTransp == 1 && transpColor != NULL) {
247 /* Compute our transparent color, which we'll match against later. 470 /* Compute our transparent color, which we'll match against later.
248 We don't really handle 16bit components properly here, since we 471 We don't really handle 16bit components properly here, since we
249 do our compare *after* the values have been knocked down to 8bit 472 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 473 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 474 fix seems to be to see the actual 16bit components, do the
252 compare, and then knock it down to 8bits ourselves. 475 compare, and then knock it down to 8bits ourselves.
253 */ 476 */
254 if (color_type & PNG_COLOR_MASK_COLOR) { 477 if (color_type & PNG_COLOR_MASK_COLOR) {
255 if (16 == bit_depth) { 478 if (16 == bit_depth) {
256 theTranspColor = SkPackARGB32(0xFF, transpColor->red >> 8, 479 *theTranspColorp = SkPackARGB32(0xFF, transpColor->red >> 8,
257 transpColor->green >> 8, transpColor->blue >> 8); 480 transpColor->green >> 8,
481 transpColor->blue >> 8);
258 } else { 482 } else {
259 theTranspColor = SkPackARGB32(0xFF, transpColor->red, 483 *theTranspColorp = SkPackARGB32(0xFF, transpColor->red,
260 transpColor->green, transpColor->blue); 484 transpColor->green,
485 transpColor->blue);
261 } 486 }
262 } else { // gray 487 } else { // gray
263 if (16 == bit_depth) { 488 if (16 == bit_depth) {
264 theTranspColor = SkPackARGB32(0xFF, transpColor->gray >> 8, 489 *theTranspColorp = SkPackARGB32(0xFF, transpColor->gray >> 8 ,
265 transpColor->gray >> 8, transpColor->gray >> 8); 490 transpColor->gray >> 8,
491 transpColor->gray >> 8);
266 } else { 492 } else {
267 theTranspColor = SkPackARGB32(0xFF, transpColor->gray, 493 *theTranspColorp = SkPackARGB32(0xFF, transpColor->gray,
268 transpColor->gray, transpColor->gray); 494 transpColor->gray,
495 transpColor->gray);
269 } 496 }
270 } 497 }
271 } 498 }
272 499
273 if (valid || 500 if (valid ||
274 PNG_COLOR_TYPE_RGB_ALPHA == color_type || 501 PNG_COLOR_TYPE_RGB_ALPHA == color_type ||
275 PNG_COLOR_TYPE_GRAY_ALPHA == color_type) { 502 PNG_COLOR_TYPE_GRAY_ALPHA == color_type) {
276 hasAlpha = true; 503 *hasAlphap = true;
277 } 504 }
278 config = this->getPrefConfig(k32Bit_SrcDepth, hasAlpha); 505 *configp = this->getPrefConfig(k32Bit_SrcDepth, *hasAlphap);
279 // now match the request against our capabilities 506 // now match the request against our capabilities
280 if (hasAlpha) { 507 if (*hasAlphap) {
281 if (config != SkBitmap::kARGB_4444_Config) { 508 if (*configp != SkBitmap::kARGB_4444_Config) {
282 config = SkBitmap::kARGB_8888_Config; 509 *configp = SkBitmap::kARGB_8888_Config;
283 } 510 }
284 } else { 511 } else {
285 if (config != SkBitmap::kRGB_565_Config && 512 if (*configp != SkBitmap::kRGB_565_Config &&
286 config != SkBitmap::kARGB_4444_Config) { 513 *configp != SkBitmap::kARGB_4444_Config) {
287 config = SkBitmap::kARGB_8888_Config; 514 *configp = SkBitmap::kARGB_8888_Config;
288 } 515 }
289 } 516 }
290 } 517 }
291 518
292 // sanity check for size 519 // sanity check for size
293 { 520 {
294 Sk64 size; 521 Sk64 size;
295 size.setMul(origWidth, origHeight); 522 size.setMul(origWidth, origHeight);
296 if (size.isNeg() || !size.is32()) { 523 if (size.isNeg() || !size.is32()) {
297 return false; 524 return false;
298 } 525 }
299 // now check that if we are 4-bytes per pixel, we also don't overflow 526 // now check that if we are 4-bytes per pixel, we also don't overflow
300 if (size.get32() > (0x7FFFFFFF >> 2)) { 527 if (size.get32() > (0x7FFFFFFF >> 2)) {
301 return false; 528 return false;
302 } 529 }
303 } 530 }
304 531
305 if (!this->chooseFromOneChoice(config, origWidth, origHeight)) { 532 return this->chooseFromOneChoice(*configp, origWidth, origHeight);
533 }
534
535 bool SkPNGImageDecoder::decodePalette(png_structp png_ptr, png_infop info_ptr,
536 bool *hasAlphap, bool *reallyHasAlphap,
537 SkColorTable **colorTablep) {
robertphillips 2013/03/13 13:41:29 numPalette, numTrans
djsollen 2013/03/13 16:02:48 Done.
538 int num_palette;
539 png_colorp palette;
540 png_bytep trans;
541 int num_trans;
542 bool reallyHasAlpha = false;
543 SkColorTable* colorTable = NULL;
544
545 png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
546
547 /* BUGGY IMAGE WORKAROUND
548
549 We hit some images (e.g. fruit_.png) who contain bytes that are == color table_count
550 which is a problem since we use the byte as an index. To work around thi s we grow
551 the colortable by 1 (if its < 256) and duplicate the last color into tha t slot.
552 */
553 int colorCount = num_palette + (num_palette < 256);
554
555 colorTable = SkNEW_ARGS(SkColorTable, (colorCount));
556
557 SkPMColor* colorPtr = colorTable->lockColors();
558 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
559 png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL);
560 *hasAlphap = (num_trans > 0);
561 } else {
562 num_trans = 0;
563 colorTable->setFlags(colorTable->getFlags() | SkColorTable::kColorsAreOp aque_Flag);
564 }
565 // check for bad images that might make us crash
566 if (num_trans > num_palette) {
567 num_trans = num_palette;
568 }
569
570 int index = 0;
571 int transLessThanFF = 0;
572
573 for (; index < num_trans; index++) {
574 transLessThanFF |= (int)*trans - 0xFF;
575 *colorPtr++ = SkPreMultiplyARGB(*trans++, palette->red, palette->green, palette->blue);
576 palette++;
577 }
578 reallyHasAlpha |= (transLessThanFF < 0);
579
580 for (; index < num_palette; index++) {
581 *colorPtr++ = SkPackARGB32(0xFF, palette->red, palette->green, palette-> blue);
582 palette++;
583 }
584
585 // see BUGGY IMAGE WORKAROUND comment above
586 if (num_palette < 256) {
587 *colorPtr = colorPtr[-1];
588 }
589 colorTable->unlockColors(true);
590 *colorTablep = colorTable;
591 *reallyHasAlphap = reallyHasAlpha;
592 return true;
593 }
594
595 #ifdef SK_BUILD_FOR_ANDROID
596
597 bool SkPNGImageDecoder::onBuildTileIndex(SkStream* sk_stream, int *width, int *h eight) {
598 png_structp png_ptr;
599 png_infop info_ptr;
600
robertphillips 2013/03/13 13:41:29 !onDecodeInit?
djsollen 2013/03/13 16:02:48 Done.
601 if (onDecodeInit(sk_stream, &png_ptr, &info_ptr) == false) {
602 return false;
603 }
604
605 if (setjmp(png_jmpbuf(png_ptr)) != 0) {
606 png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
607 return false;
608 }
609
robertphillips 2013/03/13 13:41:29 bitDepth, colorType, interlaceType
djsollen 2013/03/13 16:02:48 Done.
610 int bit_depth, color_type, interlace_type;
611 png_uint_32 origWidth, origHeight;
612 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bit_depth,
613 &color_type, &interlace_type, int_p_NULL, int_p_NULL);
614
615 *width = origWidth;
616 *height = origHeight;
617
618 png_build_index(png_ptr);
619
robertphillips 2013/03/13 13:41:29 rm this's on next two lines?
djsollen 2013/03/13 16:02:48 Done.
620 if (this->fImageIndex) {
621 SkDELETE(this->fImageIndex);
622 }
623 this->fImageIndex = new SkPNGImageIndex(png_ptr, info_ptr);
scroggo 2013/03/13 16:04:14 SkNEW_ARGS
624
625 return true;
626 }
627
628 bool SkPNGImageDecoder::onDecodeRegion(SkBitmap* bm, const SkIRect& region) {
robertphillips 2013/03/13 13:41:29 removes this's on next two lines?
djsollen 2013/03/13 16:02:48 Done.
629 png_structp png_ptr = this->fImageIndex->png_ptr;
630 png_infop info_ptr = this->fImageIndex->info_ptr;
631 if (setjmp(png_jmpbuf(png_ptr))) {
632 return false;
633 }
634
635 png_uint_32 origWidth, origHeight;
robertphillips 2013/03/13 13:41:29 bitDepth, colorType, interlaceType
djsollen 2013/03/13 16:02:48 Done.
636 int bit_depth, color_type, interlace_type;
637 png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bit_depth,
638 &color_type, &interlace_type, int_p_NULL, int_p_NULL);
639
640 SkIRect rect = SkIRect::MakeWH(origWidth, origHeight);
641
642 if (!rect.intersect(region)) {
643 // If the requested region is entirely outsides the image, just
644 // returns false
645 return false;
646 }
647
648 SkBitmap::Config config;
649 bool hasAlpha = false;
650 bool doDither = this->getDitherImage();
651 SkPMColor theTranspColor = 0; // 0 tells us not to try to match
652
robertphillips 2013/03/13 13:41:29 !getBitmapConfig?
djsollen 2013/03/13 16:02:48 Done.
653 if (getBitmapConfig(png_ptr, info_ptr, &config, &hasAlpha, &doDither,
654 &theTranspColor) == false) {
306 return false; 655 return false;
307 } 656 }
308 657
309 const int sampleSize = this->getSampleSize(); 658 const int sampleSize = this->getSampleSize();
310 SkScaledBitmapSampler sampler(origWidth, origHeight, sampleSize); 659 SkScaledBitmapSampler sampler(origWidth, rect.height(), sampleSize);
660
robertphillips 2013/03/13 13:41:29 do we actually need the decodedBitmap pointer? Why
djsollen 2013/03/13 16:02:48 Done.
661 SkBitmap *decodedBitmap = new SkBitmap;
662 SkAutoTDelete<SkBitmap> adb(decodedBitmap);
311 663
312 decodedBitmap->setConfig(config, sampler.scaledWidth(), 664 decodedBitmap->setConfig(config, sampler.scaledWidth(),
313 sampler.scaledHeight(), 0); 665 sampler.scaledHeight(), 0);
314 if (SkImageDecoder::kDecodeBounds_Mode == mode) {
315 return true;
316 }
317 666
318 // from here down we are concerned with colortables and pixels 667 // from here down we are concerned with colortables and pixels
319 668
320 // we track if we actually see a non-opaque pixels, since sometimes a PNG se ts its colortype 669 // 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 670 // 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 671 // draw lots faster if we can flag the bitmap has being opaque
323 bool reallyHasAlpha = false; 672 bool reallyHasAlpha = false;
324 SkColorTable* colorTable = NULL; 673 SkColorTable* colorTable = NULL;
325 674
326 if (color_type == PNG_COLOR_TYPE_PALETTE) { 675 if (color_type == PNG_COLOR_TYPE_PALETTE) {
327 int num_palette; 676 decodePalette(png_ptr, info_ptr, &hasAlpha,
robertphillips 2013/03/13 13:41:29 one line?
djsollen 2013/03/13 16:02:48 Done.
djsollen 2013/03/13 16:02:48 Done.
328 png_colorp palette; 677 &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 } 678 }
378 679
379 SkAutoUnref aur(colorTable); 680 SkAutoUnref aur(colorTable);
380 681
381 if (!this->allocPixelRef(decodedBitmap, 682 // Check ahead of time if the swap(dest, src) is possible in crop or not.
382 SkBitmap::kIndex8_Config == config ? 683 // If yes, then we will stick to AllocPixelRef since it's cheaper with the s wap happening.
383 colorTable : NULL)) { 684 // If no, then we will use alloc to allocate pixels to prevent garbage colle ction.
384 return false; 685 int w = rect.width() / sampleSize;
686 int h = rect.height() / sampleSize;
687 bool swapOnly = (rect == region) && (w == decodedBitmap->width()) &&
688 (h == decodedBitmap->height()) &&
robertphillips 2013/03/13 13:41:29 0 - ?
djsollen 2013/03/13 16:02:48 Done.
689 ((0 - rect.x()) / sampleSize == 0) && bm->isNull();
690 if (swapOnly) {
691 if (!this->allocPixelRef(decodedBitmap,
692 SkBitmap::kIndex8_Config == config ? colorTable : NULL)) {
693 return false;
694 }
695 } else {
696 if (!decodedBitmap->allocPixels(
697 NULL, SkBitmap::kIndex8_Config == config ? colorTable : NULL)) {
698 return false;
699 }
385 } 700 }
386
387 SkAutoLockPixels alp(*decodedBitmap); 701 SkAutoLockPixels alp(*decodedBitmap);
388 702
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) */ 703 /* Add filler (or alpha) byte (before/after each RGB triplet) */
397 if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_GRAY) { 704 if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_GRAY) {
398 png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); 705 png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
399 } 706 }
400 707
401 /* Turn on interlace handling. REQUIRED if you are not using 708 /* Turn on interlace handling. REQUIRED if you are not using
402 * png_read_image(). To see how to handle interlacing passes, 709 * png_read_image(). To see how to handle interlacing passes,
403 * see the png_read_row() method below: 710 * see the png_read_row() method below:
404 */ 711 */
405 const int number_passes = interlace_type != PNG_INTERLACE_NONE ? 712 const int number_passes = interlace_type != PNG_INTERLACE_NONE ?
406 png_set_interlace_handling(png_ptr) : 1; 713 png_set_interlace_handling(png_ptr) : 1;
407 714
408 /* Optional call to gamma correct and add the background to the palette 715 /* Optional call to gamma correct and add the background to the palette
409 * and update info structure. REQUIRED if you are expecting libpng to 716 * and update info structure. REQUIRED if you are expecting libpng to
410 * update the palette for you (ie you selected such a transform above). 717 * update the palette for you (ie you selected such a transform above).
411 */ 718 */
719 png_ptr->pass = 0;
412 png_read_update_info(png_ptr, info_ptr); 720 png_read_update_info(png_ptr, info_ptr);
413 721
722 int actualTop = rect.fTop;
723
414 if (SkBitmap::kIndex8_Config == config && 1 == sampleSize) { 724 if (SkBitmap::kIndex8_Config == config && 1 == sampleSize) {
415 for (int i = 0; i < number_passes; i++) { 725 for (int i = 0; i < number_passes; i++) {
726 png_configure_decoder(png_ptr, &actualTop, i);
robertphillips 2013/03/13 13:41:29 pre-increment?
727 for (int j = 0; j < rect.fTop - actualTop; j++) {
728 uint8_t* bmRow = decodedBitmap->getAddr8(0, 0);
729 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
730 }
416 for (png_uint_32 y = 0; y < origHeight; y++) { 731 for (png_uint_32 y = 0; y < origHeight; y++) {
417 uint8_t* bmRow = decodedBitmap->getAddr8(0, y); 732 uint8_t* bmRow = decodedBitmap->getAddr8(0, y);
418 png_read_rows(png_ptr, &bmRow, NULL, 1); 733 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
419 } 734 }
420 } 735 }
421 } else { 736 } else {
422 SkScaledBitmapSampler::SrcConfig sc; 737 SkScaledBitmapSampler::SrcConfig sc;
423 int srcBytesPerPixel = 4; 738 int srcBytesPerPixel = 4;
424 739
425 if (colorTable != NULL) { 740 if (colorTable != NULL) {
426 sc = SkScaledBitmapSampler::kIndex; 741 sc = SkScaledBitmapSampler::kIndex;
427 srcBytesPerPixel = 1; 742 srcBytesPerPixel = 1;
428 } else if (hasAlpha) { 743 } else if (hasAlpha) {
(...skipping 11 matching lines...) Expand all
440 return false; 755 return false;
441 } 756 }
442 const int height = decodedBitmap->height(); 757 const int height = decodedBitmap->height();
443 758
444 if (number_passes > 1) { 759 if (number_passes > 1) {
445 SkAutoMalloc storage(origWidth * origHeight * srcBytesPerPixel); 760 SkAutoMalloc storage(origWidth * origHeight * srcBytesPerPixel);
446 uint8_t* base = (uint8_t*)storage.get(); 761 uint8_t* base = (uint8_t*)storage.get();
447 size_t rb = origWidth * srcBytesPerPixel; 762 size_t rb = origWidth * srcBytesPerPixel;
448 763
449 for (int i = 0; i < number_passes; i++) { 764 for (int i = 0; i < number_passes; i++) {
765 png_configure_decoder(png_ptr, &actualTop, i);
766 for (int j = 0; j < rect.fTop - actualTop; j++) {
767 uint8_t* bmRow = (uint8_t*)decodedBitmap->getPixels();
768 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
769 }
450 uint8_t* row = base; 770 uint8_t* row = base;
451 for (png_uint_32 y = 0; y < origHeight; y++) { 771 for (int32_t y = 0; y < rect.height(); y++) {
452 uint8_t* bmRow = row; 772 uint8_t* bmRow = row;
453 png_read_rows(png_ptr, &bmRow, NULL, 1); 773 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
454 row += rb; 774 row += rb;
455 } 775 }
456 } 776 }
457 // now sample it 777 // now sample it
458 base += sampler.srcY0() * rb; 778 base += sampler.srcY0() * rb;
459 for (int y = 0; y < height; y++) { 779 for (int y = 0; y < height; y++) {
460 reallyHasAlpha |= sampler.next(base); 780 reallyHasAlpha |= sampler.next(base);
461 base += sampler.srcDY() * rb; 781 base += sampler.srcDY() * rb;
462 } 782 }
463 } else { 783 } else {
464 SkAutoMalloc storage(origWidth * srcBytesPerPixel); 784 SkAutoMalloc storage(origWidth * srcBytesPerPixel);
465 uint8_t* srcRow = (uint8_t*)storage.get(); 785 uint8_t* srcRow = (uint8_t*)storage.get();
786
787 png_configure_decoder(png_ptr, &actualTop, 0);
466 skip_src_rows(png_ptr, srcRow, sampler.srcY0()); 788 skip_src_rows(png_ptr, srcRow, sampler.srcY0());
467 789
790 for (int i = 0; i < rect.fTop - actualTop; i++) {
791 uint8_t* bmRow = (uint8_t*)decodedBitmap->getPixels();
792 png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
793 }
468 for (int y = 0; y < height; y++) { 794 for (int y = 0; y < height; y++) {
469 uint8_t* tmp = srcRow; 795 uint8_t* tmp = srcRow;
470 png_read_rows(png_ptr, &tmp, NULL, 1); 796 png_read_rows(png_ptr, &tmp, png_bytepp_NULL, 1);
471 reallyHasAlpha |= sampler.next(srcRow); 797 reallyHasAlpha |= sampler.next(srcRow);
472 if (y < height - 1) { 798 if (y < height - 1) {
473 skip_src_rows(png_ptr, srcRow, sampler.srcDY() - 1); 799 skip_src_rows(png_ptr, srcRow, sampler.srcDY() - 1);
474 } 800 }
475 } 801 }
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 } 802 }
483 } 803 }
484 804 if (swapOnly) {
485 /* read rest of file, and get additional chunks in info_ptr - REQUIRED */ 805 bm->swap(*decodedBitmap);
486 png_read_end(png_ptr, info_ptr); 806 } else {
807 cropBitmap(bm, decodedBitmap, sampleSize, region.x(), region.y(),
808 region.width(), region.height(), 0, rect.y());
809 }
487 810
488 if (0 != theTranspColor) { 811 if (0 != theTranspColor) {
489 reallyHasAlpha |= substituteTranspColor(decodedBitmap, theTranspColor); 812 reallyHasAlpha |= substituteTranspColor(decodedBitmap, theTranspColor);
490 } 813 }
491 decodedBitmap->setIsOpaque(!reallyHasAlpha); 814 decodedBitmap->setIsOpaque(!reallyHasAlpha);
492 return true; 815 return true;
493 } 816 }
817 #endif
494 818
495 /////////////////////////////////////////////////////////////////////////////// 819 ///////////////////////////////////////////////////////////////////////////////
496 820
497 #include "SkColorPriv.h" 821 #include "SkColorPriv.h"
498 #include "SkUnPreMultiply.h" 822 #include "SkUnPreMultiply.h"
499 823
500 static void sk_write_fn(png_structp png_ptr, png_bytep data, png_size_t len) { 824 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); 825 SkWStream* sk_stream = (SkWStream*)png_ptr->io_ptr;
502 if (!sk_stream->write(data, len)) { 826 if (!sk_stream->write(data, len)) {
503 png_error(png_ptr, "sk_write_fn Error!"); 827 png_error(png_ptr, "sk_write_fn Error!");
504 } 828 }
505 } 829 }
506 830
507 static transform_scanline_proc choose_proc(SkBitmap::Config config, 831 static transform_scanline_proc choose_proc(SkBitmap::Config config,
508 bool hasAlpha) { 832 bool hasAlpha) {
509 // we don't care about search on alpha if we're kIndex8, since only the 833 // 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 834 // colortable packing cares about that distinction, not the pixels
511 if (SkBitmap::kIndex8_Config == config) { 835 if (SkBitmap::kIndex8_Config == config) {
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
602 SkPMColor c = *colors++; 926 SkPMColor c = *colors++;
603 palette[i].red = SkGetPackedR32(c); 927 palette[i].red = SkGetPackedR32(c);
604 palette[i].green = SkGetPackedG32(c); 928 palette[i].green = SkGetPackedG32(c);
605 palette[i].blue = SkGetPackedB32(c); 929 palette[i].blue = SkGetPackedB32(c);
606 } 930 }
607 return num_trans; 931 return num_trans;
608 } 932 }
609 933
610 class SkPNGImageEncoder : public SkImageEncoder { 934 class SkPNGImageEncoder : public SkImageEncoder {
611 protected: 935 protected:
612 virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality); 936 virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) SK _OVERRIDE;
613 private: 937 private:
614 bool doEncode(SkWStream* stream, const SkBitmap& bm, 938 bool doEncode(SkWStream* stream, const SkBitmap& bm,
615 const bool& hasAlpha, int colorType, 939 const bool& hasAlpha, int colorType,
616 int bitDepth, SkBitmap::Config config, 940 int bitDepth, SkBitmap::Config config,
617 png_color_8& sig_bit); 941 png_color_8& sig_bit);
942
943 typedef SkImageEncoder INHERITED;
618 }; 944 };
619 945
620 bool SkPNGImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bitmap, 946 bool SkPNGImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bitmap,
621 int /*quality*/) { 947 int /*quality*/) {
622 SkBitmap::Config config = bitmap.getConfig(); 948 SkBitmap::Config config = bitmap.getConfig();
623 949
624 const bool hasAlpha = !bitmap.isOpaque(); 950 const bool hasAlpha = !bitmap.isOpaque();
625 int colorType = PNG_COLOR_MASK_COLOR; 951 int colorType = PNG_COLOR_MASK_COLOR;
626 int bitDepth = 8; // default for color 952 int bitDepth = 8; // default for color
627 png_color_8 sig_bit; 953 png_color_8 sig_bit;
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
690 png_infop info_ptr; 1016 png_infop info_ptr;
691 1017
692 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, sk_error_fn, 1018 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, sk_error_fn,
693 NULL); 1019 NULL);
694 if (NULL == png_ptr) { 1020 if (NULL == png_ptr) {
695 return false; 1021 return false;
696 } 1022 }
697 1023
698 info_ptr = png_create_info_struct(png_ptr); 1024 info_ptr = png_create_info_struct(png_ptr);
699 if (NULL == info_ptr) { 1025 if (NULL == info_ptr) {
700 png_destroy_write_struct(&png_ptr, NULL); 1026 png_destroy_write_struct(&png_ptr, png_infopp_NULL);
701 return false; 1027 return false;
702 } 1028 }
703 1029
704 /* Set error handling. REQUIRED if you aren't supplying your own 1030 /* Set error handling. REQUIRED if you aren't supplying your own
705 * error handling functions in the png_create_write_struct() call. 1031 * error handling functions in the png_create_write_struct() call.
706 */ 1032 */
707 if (setjmp(png_jmpbuf(png_ptr))) { 1033 if (setjmp(png_jmpbuf(png_ptr))) {
708 png_destroy_write_struct(&png_ptr, &info_ptr); 1034 png_destroy_write_struct(&png_ptr, &info_ptr);
709 return false; 1035 return false;
710 } 1036 }
711 1037
712 png_set_write_fn(png_ptr, (void*)stream, sk_write_fn, NULL); 1038 png_set_write_fn(png_ptr, (void*)stream, sk_write_fn, png_flush_ptr_NULL);
713 1039
714 /* Set the image information here. Width and height are up to 2^31, 1040 /* 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 1041 * 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, 1042 * 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, 1043 * 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 1044 * 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 1045 * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
720 * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED 1046 * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
721 */ 1047 */
722 1048
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
779 } 1105 }
780 return NULL; 1106 return NULL;
781 } 1107 }
782 1108
783 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { 1109 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) {
784 return (SkImageEncoder::kPNG_Type == t) ? SkNEW(SkPNGImageEncoder) : NULL; 1110 return (SkImageEncoder::kPNG_Type == t) ? SkNEW(SkPNGImageEncoder) : NULL;
785 } 1111 }
786 1112
787 static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(sk_libpng_efacto ry); 1113 static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(sk_libpng_efacto ry);
788 static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(sk_libpng_dfactory); 1114 static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(sk_libpng_dfactory);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698