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 |