Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkColorPriv.h" | 8 #include "SkColorPriv.h" |
| 9 #include "SkData.h" | 9 #include "SkData.h" |
| 10 #include "SkDeflate.h" | 10 #include "SkDeflate.h" |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 52 // write a single byte to a stream n times. | 52 // write a single byte to a stream n times. |
| 53 static void fill_stream(SkWStream* out, char value, size_t n) { | 53 static void fill_stream(SkWStream* out, char value, size_t n) { |
| 54 char buffer[4096]; | 54 char buffer[4096]; |
| 55 memset(buffer, value, sizeof(buffer)); | 55 memset(buffer, value, sizeof(buffer)); |
| 56 for (size_t i = 0; i < n / sizeof(buffer); ++i) { | 56 for (size_t i = 0; i < n / sizeof(buffer); ++i) { |
| 57 out->write(buffer, sizeof(buffer)); | 57 out->write(buffer, sizeof(buffer)); |
| 58 } | 58 } |
| 59 out->write(buffer, n % sizeof(buffer)); | 59 out->write(buffer, n % sizeof(buffer)); |
| 60 } | 60 } |
| 61 | 61 |
| 62 inline bool SkIsBGRA(SkColorType ct) { | |
|
tomhudson
2015/11/05 22:32:11
nit: static or anonymous namespace for these?
hal.canary
2015/11/05 23:22:13
Done.
| |
| 63 SkASSERT(kBGRA_8888_SkColorType == ct || kRGBA_8888_SkColorType == ct); | |
| 64 return kBGRA_8888_SkColorType == ct; | |
| 65 } | |
| 66 | |
| 67 inline U8CPU SkGetA32Component(uint32_t value, SkColorType ct) { | |
| 68 return (value >> (SkIsBGRA(ct) ? SK_BGRA_A32_SHIFT : SK_RGBA_A32_SHIFT)) & 0 xFF; | |
| 69 } | |
| 70 inline U8CPU SkGetR32Component(uint32_t value, SkColorType ct) { | |
| 71 return (value >> (SkIsBGRA(ct) ? SK_BGRA_R32_SHIFT : SK_RGBA_R32_SHIFT)) & 0 xFF; | |
| 72 } | |
| 73 inline U8CPU SkGetG32Component(uint32_t value, SkColorType ct) { | |
| 74 return (value >> (SkIsBGRA(ct) ? SK_BGRA_G32_SHIFT : SK_RGBA_G32_SHIFT)) & 0 xFF; | |
| 75 } | |
| 76 inline U8CPU SkGetB32Component(uint32_t value, SkColorType ct) { | |
| 77 return (value >> (SkIsBGRA(ct) ? SK_BGRA_B32_SHIFT : SK_RGBA_B32_SHIFT)) & 0 xFF; | |
| 78 } | |
| 79 | |
| 80 | |
| 62 // unpremultiply and extract R, G, B components. | 81 // unpremultiply and extract R, G, B components. |
| 63 static void pmcolor_to_rgb24(SkPMColor pmColor, uint8_t* rgb) { | 82 static void pmcolor_to_rgb24(uint32_t color, uint8_t* rgb, SkColorType ct) { |
| 64 uint32_t s = SkUnPreMultiply::GetScale(SkGetPackedA32(pmColor)); | 83 uint32_t s = SkUnPreMultiply::GetScale(SkGetA32Component(color, ct)); |
| 65 rgb[0] = SkUnPreMultiply::ApplyScale(s, SkGetPackedR32(pmColor)); | 84 rgb[0] = SkUnPreMultiply::ApplyScale(s, SkGetR32Component(color, ct)); |
| 66 rgb[1] = SkUnPreMultiply::ApplyScale(s, SkGetPackedG32(pmColor)); | 85 rgb[1] = SkUnPreMultiply::ApplyScale(s, SkGetG32Component(color, ct)); |
| 67 rgb[2] = SkUnPreMultiply::ApplyScale(s, SkGetPackedB32(pmColor)); | 86 rgb[2] = SkUnPreMultiply::ApplyScale(s, SkGetB32Component(color, ct)); |
| 68 } | 87 } |
| 69 | 88 |
| 70 /* It is necessary to average the color component of transparent | 89 /* It is necessary to average the color component of transparent |
| 71 pixels with their surrounding neighbors since the PDF renderer may | 90 pixels with their surrounding neighbors since the PDF renderer may |
| 72 separately re-sample the alpha and color channels when the image is | 91 separately re-sample the alpha and color channels when the image is |
| 73 not displayed at its native resolution. Since an alpha of zero | 92 not displayed at its native resolution. Since an alpha of zero |
| 74 gives no information about the color component, the pathological | 93 gives no information about the color component, the pathological |
| 75 case is a white image with sharp transparency bounds - the color | 94 case is a white image with sharp transparency bounds - the color |
| 76 channel goes to black, and the should-be-transparent pixels are | 95 channel goes to black, and the should-be-transparent pixels are |
| 77 rendered as grey because of the separate soft mask and color | 96 rendered as grey because of the separate soft mask and color |
| 78 resizing. e.g.: gm/bitmappremul.cpp */ | 97 resizing. e.g.: gm/bitmappremul.cpp */ |
| 79 static void get_neighbor_avg_color(const SkBitmap& bm, | 98 static void get_neighbor_avg_color(const SkBitmap& bm, |
| 80 int xOrig, | 99 int xOrig, |
| 81 int yOrig, | 100 int yOrig, |
| 82 uint8_t rgb[3]) { | 101 uint8_t rgb[3], |
| 83 SkASSERT(kN32_SkColorType == bm.colorType()); | 102 SkColorType ct) { |
| 84 unsigned a = 0, r = 0, g = 0, b = 0; | 103 unsigned a = 0, r = 0, g = 0, b = 0; |
| 85 // Clamp the range to the edge of the bitmap. | 104 // Clamp the range to the edge of the bitmap. |
| 86 int ymin = SkTMax(0, yOrig - 1); | 105 int ymin = SkTMax(0, yOrig - 1); |
| 87 int ymax = SkTMin(yOrig + 1, bm.height() - 1); | 106 int ymax = SkTMin(yOrig + 1, bm.height() - 1); |
| 88 int xmin = SkTMax(0, xOrig - 1); | 107 int xmin = SkTMax(0, xOrig - 1); |
| 89 int xmax = SkTMin(xOrig + 1, bm.width() - 1); | 108 int xmax = SkTMin(xOrig + 1, bm.width() - 1); |
| 90 for (int y = ymin; y <= ymax; ++y) { | 109 for (int y = ymin; y <= ymax; ++y) { |
| 91 SkPMColor* scanline = bm.getAddr32(0, y); | 110 uint32_t* scanline = bm.getAddr32(0, y); |
| 92 for (int x = xmin; x <= xmax; ++x) { | 111 for (int x = xmin; x <= xmax; ++x) { |
| 93 SkPMColor pmColor = scanline[x]; | 112 uint32_t color = scanline[x]; |
| 94 a += SkGetPackedA32(pmColor); | 113 a += SkGetA32Component(color, ct); |
| 95 r += SkGetPackedR32(pmColor); | 114 r += SkGetR32Component(color, ct); |
| 96 g += SkGetPackedG32(pmColor); | 115 g += SkGetG32Component(color, ct); |
| 97 b += SkGetPackedB32(pmColor); | 116 b += SkGetB32Component(color, ct); |
| 98 } | 117 } |
| 99 } | 118 } |
| 100 if (a > 0) { | 119 if (a > 0) { |
| 101 rgb[0] = SkToU8(255 * r / a); | 120 rgb[0] = SkToU8(255 * r / a); |
| 102 rgb[1] = SkToU8(255 * g / a); | 121 rgb[1] = SkToU8(255 * g / a); |
| 103 rgb[2] = SkToU8(255 * b / a); | 122 rgb[2] = SkToU8(255 * b / a); |
| 104 } else { | 123 } else { |
| 105 rgb[0] = rgb[1] = rgb[2] = 0; | 124 rgb[0] = rgb[1] = rgb[2] = 0; |
| 106 } | 125 } |
| 107 } | 126 } |
| 108 | 127 |
| 109 static size_t pixel_count(const SkBitmap& bm) { | 128 static size_t pixel_count(const SkBitmap& bm) { |
| 110 return SkToSizeT(bm.width()) * SkToSizeT(bm.height()); | 129 return SkToSizeT(bm.width()) * SkToSizeT(bm.height()); |
| 111 } | 130 } |
| 112 | 131 |
| 113 static const SkBitmap& not4444(const SkBitmap& input, SkBitmap* copy) { | 132 static const SkBitmap& not4444(const SkBitmap& input, SkBitmap* copy) { |
| 114 if (input.colorType() != kARGB_4444_SkColorType) { | 133 if (input.colorType() != kARGB_4444_SkColorType) { |
| 115 return input; | 134 return input; |
| 116 } | 135 } |
| 117 // ARGB_4444 is rarely used, so we can do a wasteful tmp copy. | 136 // ARGB_4444 is rarely used, so we can do a wasteful tmp copy. |
| 118 SkAssertResult(input.copyTo(copy, kN32_SkColorType)); | 137 SkAssertResult(input.copyTo(copy, kN32_SkColorType)); |
| 119 copy->setImmutable(); | 138 copy->setImmutable(); |
| 120 return *copy; | 139 return *copy; |
| 121 } | 140 } |
| 122 | 141 |
| 123 static size_t pdf_color_component_count(SkColorType ct) { | 142 static size_t pdf_color_component_count(SkColorType ct) { |
| 124 switch (ct) { | 143 switch (ct) { |
| 125 case kN32_SkColorType: | |
| 126 case kRGB_565_SkColorType: | 144 case kRGB_565_SkColorType: |
| 127 case kARGB_4444_SkColorType: | 145 case kARGB_4444_SkColorType: |
| 146 case kRGBA_8888_SkColorType: | |
| 147 case kBGRA_8888_SkColorType: | |
| 128 return 3; | 148 return 3; |
| 129 case kAlpha_8_SkColorType: | 149 case kAlpha_8_SkColorType: |
| 130 case kIndex_8_SkColorType: | 150 case kIndex_8_SkColorType: |
| 131 case kGray_8_SkColorType: | 151 case kGray_8_SkColorType: |
| 132 return 1; | 152 return 1; |
| 133 case kUnknown_SkColorType: | 153 case kUnknown_SkColorType: |
| 134 default: | 154 default: |
| 135 SkDEBUGFAIL("unexpected color type"); | 155 SkDEBUGFAIL("unexpected color type"); |
| 136 return 0; | 156 return 0; |
| 137 } | 157 } |
| 138 } | 158 } |
| 139 | 159 |
| 140 static void bitmap_to_pdf_pixels(const SkBitmap& bitmap, SkWStream* out) { | 160 static void bitmap_to_pdf_pixels(const SkBitmap& bitmap, SkWStream* out) { |
| 141 if (!bitmap.getPixels()) { | 161 if (!bitmap.getPixels()) { |
| 142 size_t size = pixel_count(bitmap) * | 162 size_t size = pixel_count(bitmap) * |
| 143 pdf_color_component_count(bitmap.colorType()); | 163 pdf_color_component_count(bitmap.colorType()); |
| 144 fill_stream(out, '\x00', size); | 164 fill_stream(out, '\x00', size); |
| 145 return; | 165 return; |
| 146 } | 166 } |
| 147 SkBitmap copy; | 167 SkBitmap copy; |
| 148 const SkBitmap& bm = not4444(bitmap, ©); | 168 const SkBitmap& bm = not4444(bitmap, ©); |
| 149 SkAutoLockPixels autoLockPixels(bm); | 169 SkAutoLockPixels autoLockPixels(bm); |
| 150 switch (bm.colorType()) { | 170 SkColorType colorType = bm.colorType(); |
| 151 case kN32_SkColorType: { | 171 switch (colorType) { |
| 152 SkASSERT(3 == pdf_color_component_count(bitmap.colorType())); | 172 case kRGBA_8888_SkColorType: |
| 173 case kBGRA_8888_SkColorType: { | |
| 174 SkASSERT(3 == pdf_color_component_count(colorType)); | |
| 153 SkAutoTMalloc<uint8_t> scanline(3 * bm.width()); | 175 SkAutoTMalloc<uint8_t> scanline(3 * bm.width()); |
| 154 for (int y = 0; y < bm.height(); ++y) { | 176 for (int y = 0; y < bm.height(); ++y) { |
| 155 const SkPMColor* src = bm.getAddr32(0, y); | 177 const uint32_t* src = bm.getAddr32(0, y); |
| 156 uint8_t* dst = scanline.get(); | 178 uint8_t* dst = scanline.get(); |
| 157 for (int x = 0; x < bm.width(); ++x) { | 179 for (int x = 0; x < bm.width(); ++x) { |
| 158 SkPMColor color = *src++; | 180 uint32_t color = *src++; |
| 159 U8CPU alpha = SkGetPackedA32(color); | 181 U8CPU alpha = SkGetA32Component(color, colorType); |
| 160 if (alpha != SK_AlphaTRANSPARENT) { | 182 if (alpha != SK_AlphaTRANSPARENT) { |
| 161 pmcolor_to_rgb24(color, dst); | 183 pmcolor_to_rgb24(color, dst, colorType); |
| 162 } else { | 184 } else { |
| 163 get_neighbor_avg_color(bm, x, y, dst); | 185 get_neighbor_avg_color(bm, x, y, dst, colorType); |
| 164 } | 186 } |
| 165 dst += 3; | 187 dst += 3; |
| 166 } | 188 } |
| 167 out->write(scanline.get(), 3 * bm.width()); | 189 out->write(scanline.get(), 3 * bm.width()); |
| 168 } | 190 } |
| 169 return; | 191 return; |
| 170 } | 192 } |
| 171 case kRGB_565_SkColorType: { | 193 case kRGB_565_SkColorType: { |
| 172 SkASSERT(3 == pdf_color_component_count(bitmap.colorType())); | 194 SkASSERT(3 == pdf_color_component_count(colorType)); |
| 173 SkAutoTMalloc<uint8_t> scanline(3 * bm.width()); | 195 SkAutoTMalloc<uint8_t> scanline(3 * bm.width()); |
| 174 for (int y = 0; y < bm.height(); ++y) { | 196 for (int y = 0; y < bm.height(); ++y) { |
| 175 const uint16_t* src = bm.getAddr16(0, y); | 197 const uint16_t* src = bm.getAddr16(0, y); |
| 176 uint8_t* dst = scanline.get(); | 198 uint8_t* dst = scanline.get(); |
| 177 for (int x = 0; x < bm.width(); ++x) { | 199 for (int x = 0; x < bm.width(); ++x) { |
| 178 U16CPU color565 = *src++; | 200 U16CPU color565 = *src++; |
| 179 *dst++ = SkPacked16ToR32(color565); | 201 *dst++ = SkPacked16ToR32(color565); |
| 180 *dst++ = SkPacked16ToG32(color565); | 202 *dst++ = SkPacked16ToG32(color565); |
| 181 *dst++ = SkPacked16ToB32(color565); | 203 *dst++ = SkPacked16ToB32(color565); |
| 182 } | 204 } |
| 183 out->write(scanline.get(), 3 * bm.width()); | 205 out->write(scanline.get(), 3 * bm.width()); |
| 184 } | 206 } |
| 185 return; | 207 return; |
| 186 } | 208 } |
| 187 case kAlpha_8_SkColorType: | 209 case kAlpha_8_SkColorType: |
| 188 SkASSERT(1 == pdf_color_component_count(bitmap.colorType())); | 210 SkASSERT(1 == pdf_color_component_count(colorType)); |
| 189 fill_stream(out, '\x00', pixel_count(bm)); | 211 fill_stream(out, '\x00', pixel_count(bm)); |
| 190 return; | 212 return; |
| 191 case kGray_8_SkColorType: | 213 case kGray_8_SkColorType: |
| 192 case kIndex_8_SkColorType: | 214 case kIndex_8_SkColorType: |
| 193 SkASSERT(1 == pdf_color_component_count(bitmap.colorType())); | 215 SkASSERT(1 == pdf_color_component_count(colorType)); |
| 194 // these two formats need no transformation to serialize. | 216 // these two formats need no transformation to serialize. |
| 195 for (int y = 0; y < bm.height(); ++y) { | 217 for (int y = 0; y < bm.height(); ++y) { |
| 196 out->write(bm.getAddr8(0, y), bm.width()); | 218 out->write(bm.getAddr8(0, y), bm.width()); |
| 197 } | 219 } |
| 198 return; | 220 return; |
| 199 case kUnknown_SkColorType: | 221 case kUnknown_SkColorType: |
| 200 case kARGB_4444_SkColorType: | 222 case kARGB_4444_SkColorType: |
| 201 default: | 223 default: |
| 202 SkDEBUGFAIL("unexpected color type"); | 224 SkDEBUGFAIL("unexpected color type"); |
| 203 } | 225 } |
| 204 } | 226 } |
| 205 | 227 |
| 206 //////////////////////////////////////////////////////////////////////////////// | 228 //////////////////////////////////////////////////////////////////////////////// |
| 207 | 229 |
| 208 static void bitmap_alpha_to_a8(const SkBitmap& bitmap, SkWStream* out) { | 230 static void bitmap_alpha_to_a8(const SkBitmap& bitmap, SkWStream* out) { |
| 209 if (!bitmap.getPixels()) { | 231 if (!bitmap.getPixels()) { |
| 210 fill_stream(out, '\xFF', pixel_count(bitmap)); | 232 fill_stream(out, '\xFF', pixel_count(bitmap)); |
| 211 return; | 233 return; |
| 212 } | 234 } |
| 213 SkBitmap copy; | 235 SkBitmap copy; |
| 214 const SkBitmap& bm = not4444(bitmap, ©); | 236 const SkBitmap& bm = not4444(bitmap, ©); |
| 215 SkAutoLockPixels autoLockPixels(bm); | 237 SkAutoLockPixels autoLockPixels(bm); |
| 216 switch (bm.colorType()) { | 238 SkColorType colorType = bm.colorType(); |
| 217 case kN32_SkColorType: { | 239 switch (colorType) { |
| 240 case kRGBA_8888_SkColorType: | |
| 241 case kBGRA_8888_SkColorType: { | |
| 218 SkAutoTMalloc<uint8_t> scanline(bm.width()); | 242 SkAutoTMalloc<uint8_t> scanline(bm.width()); |
| 219 for (int y = 0; y < bm.height(); ++y) { | 243 for (int y = 0; y < bm.height(); ++y) { |
| 220 uint8_t* dst = scanline.get(); | 244 uint8_t* dst = scanline.get(); |
| 221 const SkPMColor* src = bm.getAddr32(0, y); | 245 const SkPMColor* src = bm.getAddr32(0, y); |
| 222 for (int x = 0; x < bm.width(); ++x) { | 246 for (int x = 0; x < bm.width(); ++x) { |
| 223 *dst++ = SkGetPackedA32(*src++); | 247 *dst++ = SkGetA32Component(*src++, colorType); |
| 224 } | 248 } |
| 225 out->write(scanline.get(), bm.width()); | 249 out->write(scanline.get(), bm.width()); |
| 226 } | 250 } |
| 227 return; | 251 return; |
| 228 } | 252 } |
| 229 case kAlpha_8_SkColorType: | 253 case kAlpha_8_SkColorType: |
| 230 for (int y = 0; y < bm.height(); ++y) { | 254 for (int y = 0; y < bm.height(); ++y) { |
| 231 out->write(bm.getAddr8(0, y), bm.width()); | 255 out->write(bm.getAddr8(0, y), bm.width()); |
| 232 } | 256 } |
| 233 return; | 257 return; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 273 } | 297 } |
| 274 result->appendInt(table->count() - 1); // maximum color index. | 298 result->appendInt(table->count() - 1); // maximum color index. |
| 275 | 299 |
| 276 // Potentially, this could be represented in fewer bytes with a stream. | 300 // Potentially, this could be represented in fewer bytes with a stream. |
| 277 // Max size as a string is 1.5k. | 301 // Max size as a string is 1.5k. |
| 278 char tableArray[256 * 3]; | 302 char tableArray[256 * 3]; |
| 279 SkASSERT(3u * table->count() <= SK_ARRAY_COUNT(tableArray)); | 303 SkASSERT(3u * table->count() <= SK_ARRAY_COUNT(tableArray)); |
| 280 uint8_t* tablePtr = reinterpret_cast<uint8_t*>(tableArray); | 304 uint8_t* tablePtr = reinterpret_cast<uint8_t*>(tableArray); |
| 281 const SkPMColor* colors = table->readColors(); | 305 const SkPMColor* colors = table->readColors(); |
| 282 for (int i = 0; i < table->count(); i++) { | 306 for (int i = 0; i < table->count(); i++) { |
| 283 pmcolor_to_rgb24(colors[i], tablePtr); | 307 pmcolor_to_rgb24(colors[i], tablePtr, kN32_SkColorType); |
| 284 tablePtr += 3; | 308 tablePtr += 3; |
| 285 } | 309 } |
| 286 SkString tableString(tableArray, 3 * table->count()); | 310 SkString tableString(tableArray, 3 * table->count()); |
| 287 result->appendString(tableString); | 311 result->appendString(tableString); |
| 288 return result; | 312 return result; |
| 289 } | 313 } |
| 290 | 314 |
| 291 static void emit_image_xobject(SkWStream* stream, | 315 static void emit_image_xobject(SkWStream* stream, |
| 292 const SkImage* image, | 316 const SkImage* image, |
| 293 bool alpha, | 317 bool alpha, |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 444 return new PDFJpegBitmap(info.fSize, data, yuv); | 468 return new PDFJpegBitmap(info.fSize, data, yuv); |
| 445 } | 469 } |
| 446 } | 470 } |
| 447 SkPDFObject* smask = | 471 SkPDFObject* smask = |
| 448 image_compute_is_opaque(image) ? nullptr : new PDFAlphaBitmap(image) ; | 472 image_compute_is_opaque(image) ? nullptr : new PDFAlphaBitmap(image) ; |
| 449 #ifdef SK_PDF_IMAGE_STATS | 473 #ifdef SK_PDF_IMAGE_STATS |
| 450 gRegularImageObjects.fetch_add(1); | 474 gRegularImageObjects.fetch_add(1); |
| 451 #endif | 475 #endif |
| 452 return new PDFDefaultBitmap(image, smask); | 476 return new PDFDefaultBitmap(image, smask); |
| 453 } | 477 } |
| OLD | NEW |