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