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

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

Issue 22329003: Unpremultiply SkBitmaps for PDF output (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: More cleanup Created 7 years, 4 months 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 | Annotate | Revision Log
« no previous file with comments | « gyp/gmslides.gypi ('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 2010 The Android Open Source Project 2 * Copyright 2010 The Android Open Source Project
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 "SkPDFImage.h" 8 #include "SkPDFImage.h"
9 9
10 #include "SkBitmap.h" 10 #include "SkBitmap.h"
11 #include "SkColor.h" 11 #include "SkColor.h"
12 #include "SkColorPriv.h" 12 #include "SkColorPriv.h"
13 #include "SkPDFCatalog.h" 13 #include "SkPDFCatalog.h"
14 #include "SkRect.h" 14 #include "SkRect.h"
15 #include "SkStream.h" 15 #include "SkStream.h"
16 #include "SkString.h" 16 #include "SkString.h"
17 #include "SkUnPreMultiply.h" 17 #include "SkUnPreMultiply.h"
18 18
19 namespace { 19 namespace {
20 20
21 /**
22 * Unpremultiply an ARGB color, keeping the output in the same format
23 * as the input.
24 */
25 static void pack_argb8888(uint32_t src, uint8_t* dst) {
26 dst[0] = SkGetPackedR32(src);
27 dst[1] = SkGetPackedG32(src);
28 dst[2] = SkGetPackedB32(src);
29 }
30
31 static void pack_argb4444(uint16_t src0, uint16_t src1, uint8_t* dst) {
32 dst[0] = (SkGetPackedR4444(src0) << 4) |
33 SkGetPackedG4444(src0);
34 dst[1] = (SkGetPackedB4444(src0) << 4) |
35 SkGetPackedR4444(src1);
36 dst[2] = (SkGetPackedG4444(src1) << 4) |
37 SkGetPackedB4444(src1);
38 }
39
40 static void unpremultiply_and_pack_argb8888(uint8_t alpha, uint32_t src,
41 uint8_t* dst) {
42 SkUnPreMultiply::Scale scale = SkUnPreMultiply::GetScale(alpha);
43
44 dst[0] = SkUnPreMultiply::ApplyScale(scale, SkGetPackedR32(src));
45 dst[1] = SkUnPreMultiply::ApplyScale(scale, SkGetPackedG32(src));
46 dst[2] = SkUnPreMultiply::ApplyScale(scale, SkGetPackedB32(src));
47 }
48
49 static void unpremultiply_and_pack_argb4444(uint8_t alpha0, uint8_t alpha1,
50 uint16_t src0, uint16_t src1,
51 uint8_t* dst) {
52 // Convert alpha from 4 bit to 8 bit, consistent with SkPixel4444ToPixel32
53 alpha0 = alpha0 | (alpha0 << 4);
54 alpha1 = alpha1 | (alpha1 << 4);
55 SkUnPreMultiply::Scale scale0 = SkUnPreMultiply::GetScale(alpha0);
56 SkUnPreMultiply::Scale scale1 = SkUnPreMultiply::GetScale(alpha1);
57
58 dst[0] = (SkUnPreMultiply::ApplyScale(scale0, SkGetPackedR4444(src0)) << 4);
59 dst[0] |= SkUnPreMultiply::ApplyScale(scale0, SkGetPackedG4444(src0));
60 dst[1] = (SkUnPreMultiply::ApplyScale(scale0, SkGetPackedB4444(src0)) << 4);
61 dst[1] |= SkUnPreMultiply::ApplyScale(scale1, SkGetPackedR4444(src1));
62 dst[2] = (SkUnPreMultiply::ApplyScale(scale1, SkGetPackedG4444(src1)) << 4);
63 dst[2] |= SkUnPreMultiply::ApplyScale(scale1, SkGetPackedB4444(src1));
64 }
65
21 void extractImageData(const SkBitmap& bitmap, const SkIRect& srcRect, 66 void extractImageData(const SkBitmap& bitmap, const SkIRect& srcRect,
22 SkStream** imageData, SkStream** alphaData) { 67 SkStream** imageData, SkStream** alphaData) {
23 SkMemoryStream* image = NULL; 68 SkMemoryStream* image = NULL;
24 SkMemoryStream* alpha = NULL; 69 SkMemoryStream* alpha = NULL;
25 bool hasAlpha = false; 70 bool hasAlpha = false;
26 bool isTransparent = false; 71 bool isTransparent = false;
27 72
28 bitmap.lockPixels(); 73 bitmap.lockPixels();
29 switch (bitmap.getConfig()) { 74 switch (bitmap.getConfig()) {
30 case SkBitmap::kIndex8_Config: { 75 case SkBitmap::kIndex8_Config: {
(...skipping 11 matching lines...) Expand all
42 const int rowBytes = (srcRect.width() * 3 + 1) / 2; 87 const int rowBytes = (srcRect.width() * 3 + 1) / 2;
43 const int alphaRowBytes = (srcRect.width() + 1) / 2; 88 const int alphaRowBytes = (srcRect.width() + 1) / 2;
44 image = new SkMemoryStream(rowBytes * srcRect.height()); 89 image = new SkMemoryStream(rowBytes * srcRect.height());
45 alpha = new SkMemoryStream(alphaRowBytes * srcRect.height()); 90 alpha = new SkMemoryStream(alphaRowBytes * srcRect.height());
46 uint8_t* dst = (uint8_t*)image->getMemoryBase(); 91 uint8_t* dst = (uint8_t*)image->getMemoryBase();
47 uint8_t* alphaDst = (uint8_t*)alpha->getMemoryBase(); 92 uint8_t* alphaDst = (uint8_t*)alpha->getMemoryBase();
48 for (int y = srcRect.fTop; y < srcRect.fBottom; y++) { 93 for (int y = srcRect.fTop; y < srcRect.fBottom; y++) {
49 uint16_t* src = bitmap.getAddr16(0, y); 94 uint16_t* src = bitmap.getAddr16(0, y);
50 int x; 95 int x;
51 for (x = srcRect.fLeft; x + 1 < srcRect.fRight; x += 2) { 96 for (x = srcRect.fLeft; x + 1 < srcRect.fRight; x += 2) {
52 dst[0] = (SkGetPackedR4444(src[x]) << 4) | 97 uint16_t pixel0 = src[x];
vandebo (ex-Chrome) 2013/08/12 15:56:05 I was imagining the following code - push the cond
ducky 2013/08/12 20:51:58 Done.
53 SkGetPackedG4444(src[x]); 98 uint16_t pixel1 = src[x + 1];
54 dst[1] = (SkGetPackedB4444(src[x]) << 4) | 99 uint8_t alpha0 = SkGetPackedA4444(pixel0);
55 SkGetPackedR4444(src[x + 1]); 100 uint8_t alpha1 = SkGetPackedA4444(pixel1);
56 dst[2] = (SkGetPackedG4444(src[x + 1]) << 4) | 101 alphaDst[0] = (alpha0 << 4) | alpha1;
57 SkGetPackedB4444(src[x + 1]);
58 dst += 3;
59 alphaDst[0] = (SkGetPackedA4444(src[x]) << 4) |
60 SkGetPackedA4444(src[x + 1]);
61 if (alphaDst[0] != 0xFF) { 102 if (alphaDst[0] != 0xFF) {
vandebo (ex-Chrome) 2013/08/12 15:56:05 SK_AlphaOPAQUE
ducky 2013/08/12 20:51:58 Done.
62 hasAlpha = true; 103 hasAlpha = true;
104 unpremultiply_and_pack_argb4444(alpha0, alpha1,
105 pixel0, pixel1,
106 dst);
107 } else {
108 pack_argb4444(pixel0, pixel1, dst);
63 } 109 }
64 if (alphaDst[0]) { 110 if (alphaDst[0]) {
65 isTransparent = false; 111 isTransparent = false;
66 } 112 }
113
67 alphaDst++; 114 alphaDst++;
115 dst += 3;
68 } 116 }
69 if (srcRect.width() & 1) { 117 if (srcRect.width() & 1) {
70 dst[0] = (SkGetPackedR4444(src[x]) << 4) | 118 uint16_t pixel = src[x];
71 SkGetPackedG4444(src[x]); 119 uint8_t alpha = SkGetPackedA4444(pixel);
72 dst[1] = (SkGetPackedB4444(src[x]) << 4); 120 alphaDst[0] = (alpha << 4);
73 dst += 2; 121 // Use a buffer to translate from the usual 2 4444 values
74 alphaDst[0] = (SkGetPackedA4444(src[x]) << 4); 122 // in 12 bytes to the single 4444 value in 2 bytes.
123 uint8_t buffer[3];
75 if (alphaDst[0] != 0xF0) { 124 if (alphaDst[0] != 0xF0) {
76 hasAlpha = true; 125 hasAlpha = true;
126 unpremultiply_and_pack_argb4444(alpha, 0x00,
127 pixel, 0x00,
128 buffer);
129 } else {
130 pack_argb4444(pixel, 0x00, buffer);
77 } 131 }
78 if (alphaDst[0] & 0xF0) { 132 if (alphaDst[0] & 0xF0) {
79 isTransparent = false; 133 isTransparent = false;
80 } 134 }
135
136 dst[0] = buffer[0];
137 dst[1] = buffer[1];
138
81 alphaDst++; 139 alphaDst++;
140 dst += 2;
82 } 141 }
83 } 142 }
84 break; 143 break;
85 } 144 }
86 case SkBitmap::kRGB_565_Config: { 145 case SkBitmap::kRGB_565_Config: {
87 const int rowBytes = srcRect.width() * 3; 146 const int rowBytes = srcRect.width() * 3;
88 image = new SkMemoryStream(rowBytes * srcRect.height()); 147 image = new SkMemoryStream(rowBytes * srcRect.height());
89 uint8_t* dst = (uint8_t*)image->getMemoryBase(); 148 uint8_t* dst = (uint8_t*)image->getMemoryBase();
90 for (int y = srcRect.fTop; y < srcRect.fBottom; y++) { 149 for (int y = srcRect.fTop; y < srcRect.fBottom; y++) {
91 uint16_t* src = bitmap.getAddr16(0, y); 150 uint16_t* src = bitmap.getAddr16(0, y);
92 for (int x = srcRect.fLeft; x < srcRect.fRight; x++) { 151 for (int x = srcRect.fLeft; x < srcRect.fRight; x++) {
93 dst[0] = SkGetPackedR16(src[x]); 152 dst[0] = SkGetPackedR16(src[x]);
94 dst[1] = SkGetPackedG16(src[x]); 153 dst[1] = SkGetPackedG16(src[x]);
95 dst[2] = SkGetPackedB16(src[x]); 154 dst[2] = SkGetPackedB16(src[x]);
96 dst += 3; 155 dst += 3;
97 } 156 }
98 } 157 }
99 break; 158 break;
100 } 159 }
101 case SkBitmap::kARGB_8888_Config: { 160 case SkBitmap::kARGB_8888_Config: {
vandebo (ex-Chrome) 2013/08/12 15:56:05 I think you can just use PMColorToColor in this ca
ducky 2013/08/12 20:51:58 Done and moved up into the unpremul_and_pack, for
102 isTransparent = true; 161 isTransparent = true;
103 const int rowBytes = srcRect.width() * 3; 162 const int rowBytes = srcRect.width() * 3;
104 image = new SkMemoryStream(rowBytes * srcRect.height()); 163 image = new SkMemoryStream(rowBytes * srcRect.height());
105 alpha = new SkMemoryStream(srcRect.width() * srcRect.height()); 164 alpha = new SkMemoryStream(srcRect.width() * srcRect.height());
106 uint8_t* dst = (uint8_t*)image->getMemoryBase(); 165 uint8_t* dst = (uint8_t*)image->getMemoryBase();
107 uint8_t* alphaDst = (uint8_t*)alpha->getMemoryBase(); 166 uint8_t* alphaDst = (uint8_t*)alpha->getMemoryBase();
108 for (int y = srcRect.fTop; y < srcRect.fBottom; y++) { 167 for (int y = srcRect.fTop; y < srcRect.fBottom; y++) {
109 uint32_t* src = bitmap.getAddr32(0, y); 168 uint32_t* src = bitmap.getAddr32(0, y);
110 for (int x = srcRect.fLeft; x < srcRect.fRight; x++) { 169 for (int x = srcRect.fLeft; x < srcRect.fRight; x++) {
111 dst[0] = SkGetPackedR32(src[x]); 170 uint32_t pixel = src[x];
112 dst[1] = SkGetPackedG32(src[x]); 171 alphaDst[0] = SkGetPackedA32(pixel);
113 dst[2] = SkGetPackedB32(src[x]); 172 if (alphaDst[0] != SK_AlphaOPAQUE) {
114 dst += 3;
115 alphaDst[0] = SkGetPackedA32(src[x]);
116 if (alphaDst[0] != 0xFF) {
117 hasAlpha = true; 173 hasAlpha = true;
174 unpremultiply_and_pack_argb8888(alphaDst[0],
175 pixel,
176 dst);
177 } else {
178 pack_argb8888(pixel, dst);
118 } 179 }
119 if (alphaDst[0]) { 180 if (alphaDst[0] != SK_AlphaTRANSPARENT) {
120 isTransparent = false; 181 isTransparent = false;
121 } 182 }
183
122 alphaDst++; 184 alphaDst++;
185 dst += 3;
123 } 186 }
124 } 187 }
125 break; 188 break;
126 } 189 }
127 case SkBitmap::kA1_Config: { 190 case SkBitmap::kA1_Config: {
128 isTransparent = true; 191 isTransparent = true;
129 image = new SkMemoryStream(1); 192 image = new SkMemoryStream(1);
130 ((uint8_t*)image->getMemoryBase())[0] = 0; 193 ((uint8_t*)image->getMemoryBase())[0] = 0;
131 194
132 const int alphaRowBytes = (srcRect.width() + 7) / 8; 195 const int alphaRowBytes = (srcRect.width() + 7) / 8;
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
330 decodeValue->reserve(6); 393 decodeValue->reserve(6);
331 decodeValue->append(zeroVal.get()); 394 decodeValue->append(zeroVal.get());
332 decodeValue->append(scale5Val.get()); 395 decodeValue->append(scale5Val.get());
333 decodeValue->append(zeroVal.get()); 396 decodeValue->append(zeroVal.get());
334 decodeValue->append(scale6Val.get()); 397 decodeValue->append(scale6Val.get());
335 decodeValue->append(zeroVal.get()); 398 decodeValue->append(zeroVal.get());
336 decodeValue->append(scale5Val.get()); 399 decodeValue->append(scale5Val.get());
337 insert("Decode", decodeValue.get()); 400 insert("Decode", decodeValue.get());
338 } 401 }
339 } 402 }
OLDNEW
« no previous file with comments | « gyp/gmslides.gypi ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698