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

Side by Side Diff: src/pdf/SkPDFBitmap.cpp

Issue 1407063005: SkPDF: images support 32-but-not-N32 colortype (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: 2015-11-04 (Wednesday) 13:25:24 EST Created 5 years, 1 month 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
« no previous file with comments | « gm/all_bitmap_configs.cpp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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, &copy); 168 const SkBitmap& bm = not4444(bitmap, &copy);
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, &copy); 236 const SkBitmap& bm = not4444(bitmap, &copy);
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
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
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 }
OLDNEW
« no previous file with comments | « gm/all_bitmap_configs.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698