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 |