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

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-05 (Thursday) 18:17:20 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 // 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, &copy); 173 const SkBitmap& bm = not4444(bitmap, &copy);
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, &copy); 241 const SkBitmap& bm = not4444(bitmap, &copy);
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
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
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 }
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