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

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: Fix Windows build 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
« gm/bitmappremul.cpp ('K') | « 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 static void unpremultiply_and_pack_argb8888(uint32_t src, uint8_t dst[3]) {
22 uint8_t alpha = SkGetPackedA32(src);
23 if (alpha != SK_AlphaOPAQUE) {
24 SkColor unpremul = SkUnPreMultiply::PMColorToColor(src);
25 dst[0] = SkColorGetR(unpremul);
26 dst[1] = SkColorGetG(unpremul);
27 dst[2] = SkColorGetB(unpremul);
28 } else {
29 dst[0] = SkGetPackedR32(src);
30 dst[1] = SkGetPackedG32(src);
31 dst[2] = SkGetPackedB32(src);
32 }
33 }
34
35 static void unpremultiply_and_pack_argb4444(uint16_t src0, uint16_t src1,
36 uint8_t dst[3]) {
37 // Unpack and transform the alpha values from 4 bits to 8 bits.
38 // This is necessary since the unpremultiply functions expect to work in
39 // 8-bit space, but we are passing in 4-bit values. Since we scale up
40 // the alpha, we scale down the amount the value is increased by, so that
41 // the results are correct for 4-bit color components.
42 uint8_t alpha0 = SkGetPackedA4444(src0);
43 alpha0 = alpha0 | (alpha0 << 4);
44 if (alpha0 != SK_AlphaOPAQUE) {
45 SkUnPreMultiply::Scale scale0 = SkUnPreMultiply::GetScale(alpha0);
46 dst[0] = SkUnPreMultiply::ApplyScale(scale0,
47 SkGetPackedR4444(src0)) << 4;
48 dst[0] |= SkUnPreMultiply::ApplyScale(scale0, SkGetPackedG4444(src0));
49 dst[1] = SkUnPreMultiply::ApplyScale(scale0,
50 SkGetPackedB4444(src0)) << 4;
51 } else {
52 dst[0] = SkGetPackedR4444(src0) << 4;
53 dst[0] |= SkGetPackedG4444(src0);
54 dst[1] = SkGetPackedB4444(src0) << 4;
55 }
56
57 uint8_t alpha1 = SkGetPackedA4444(src1);
58 alpha1 = alpha1 | (alpha1 << 4);
59 if (alpha1 != SK_AlphaOPAQUE) {
60 SkUnPreMultiply::Scale scale1 = SkUnPreMultiply::GetScale(alpha1);
61 dst[1] |= SkUnPreMultiply::ApplyScale(scale1, SkGetPackedR4444(src1));
62 dst[2] = SkUnPreMultiply::ApplyScale(scale1,
63 SkGetPackedG4444(src1)) << 4;
64 dst[2] |= SkUnPreMultiply::ApplyScale(scale1, SkGetPackedB4444(src1));
65 } else {
66 dst[1] |= SkGetPackedR4444(src1);
67 dst[2] = SkGetPackedG4444(src1) << 4;
68 dst[2] |= SkGetPackedB4444(src1);
69 }
70 }
71
21 void extractImageData(const SkBitmap& bitmap, const SkIRect& srcRect, 72 void extractImageData(const SkBitmap& bitmap, const SkIRect& srcRect,
22 SkStream** imageData, SkStream** alphaData) { 73 SkStream** imageData, SkStream** alphaData) {
23 SkMemoryStream* image = NULL; 74 SkMemoryStream* image = NULL;
24 SkMemoryStream* alpha = NULL; 75 SkMemoryStream* alpha = NULL;
25 bool hasAlpha = false; 76 bool hasAlpha = false;
26 bool isTransparent = false; 77 bool isTransparent = false;
27 78
28 bitmap.lockPixels(); 79 bitmap.lockPixels();
29 switch (bitmap.getConfig()) { 80 switch (bitmap.getConfig()) {
30 case SkBitmap::kIndex8_Config: { 81 case SkBitmap::kIndex8_Config: {
(...skipping 11 matching lines...) Expand all
42 const int rowBytes = (srcRect.width() * 3 + 1) / 2; 93 const int rowBytes = (srcRect.width() * 3 + 1) / 2;
43 const int alphaRowBytes = (srcRect.width() + 1) / 2; 94 const int alphaRowBytes = (srcRect.width() + 1) / 2;
44 image = new SkMemoryStream(rowBytes * srcRect.height()); 95 image = new SkMemoryStream(rowBytes * srcRect.height());
45 alpha = new SkMemoryStream(alphaRowBytes * srcRect.height()); 96 alpha = new SkMemoryStream(alphaRowBytes * srcRect.height());
46 uint8_t* dst = (uint8_t*)image->getMemoryBase(); 97 uint8_t* dst = (uint8_t*)image->getMemoryBase();
47 uint8_t* alphaDst = (uint8_t*)alpha->getMemoryBase(); 98 uint8_t* alphaDst = (uint8_t*)alpha->getMemoryBase();
48 for (int y = srcRect.fTop; y < srcRect.fBottom; y++) { 99 for (int y = srcRect.fTop; y < srcRect.fBottom; y++) {
49 uint16_t* src = bitmap.getAddr16(0, y); 100 uint16_t* src = bitmap.getAddr16(0, y);
50 int x; 101 int x;
51 for (x = srcRect.fLeft; x + 1 < srcRect.fRight; x += 2) { 102 for (x = srcRect.fLeft; x + 1 < srcRect.fRight; x += 2) {
52 dst[0] = (SkGetPackedR4444(src[x]) << 4) |
53 SkGetPackedG4444(src[x]);
54 dst[1] = (SkGetPackedB4444(src[x]) << 4) |
55 SkGetPackedR4444(src[x + 1]);
56 dst[2] = (SkGetPackedG4444(src[x + 1]) << 4) |
57 SkGetPackedB4444(src[x + 1]);
58 dst += 3;
59 alphaDst[0] = (SkGetPackedA4444(src[x]) << 4) | 103 alphaDst[0] = (SkGetPackedA4444(src[x]) << 4) |
60 SkGetPackedA4444(src[x + 1]); 104 SkGetPackedA4444(src[x + 1]);
61 if (alphaDst[0] != 0xFF) { 105 if (alphaDst[0] != SK_AlphaOPAQUE) {
62 hasAlpha = true; 106 hasAlpha = true;
63 } 107 }
64 if (alphaDst[0]) { 108 if (alphaDst[0]) {
65 isTransparent = false; 109 isTransparent = false;
66 } 110 }
111 unpremultiply_and_pack_argb4444(src[x], src[x + 1], dst);
67 alphaDst++; 112 alphaDst++;
113 dst += 3;
68 } 114 }
69 if (srcRect.width() & 1) { 115 if (srcRect.width() & 1) {
70 dst[0] = (SkGetPackedR4444(src[x]) << 4) | 116 alphaDst[0] = SkGetPackedA4444(src[x]) << 4;
71 SkGetPackedG4444(src[x]); 117 // Use a buffer to translate from the usual 2 4444 values
72 dst[1] = (SkGetPackedB4444(src[x]) << 4); 118 // in 12 bytes to the single 4444 value in 2 bytes.
vandebo (ex-Chrome) 2013/08/13 20:52:33 nit: 12 bytes -> 3 bytes.
73 dst += 2; 119 uint8_t buffer[3];
74 alphaDst[0] = (SkGetPackedA4444(src[x]) << 4);
75 if (alphaDst[0] != 0xF0) { 120 if (alphaDst[0] != 0xF0) {
76 hasAlpha = true; 121 hasAlpha = true;
77 } 122 }
78 if (alphaDst[0] & 0xF0) { 123 if (alphaDst[0] & 0xF0) {
79 isTransparent = false; 124 isTransparent = false;
80 } 125 }
126 unpremultiply_and_pack_argb4444(src[x], 0x00, buffer);
127 dst[0] = buffer[0];
128 dst[1] = buffer[1];
129
81 alphaDst++; 130 alphaDst++;
131 dst += 2;
82 } 132 }
83 } 133 }
84 break; 134 break;
85 } 135 }
86 case SkBitmap::kRGB_565_Config: { 136 case SkBitmap::kRGB_565_Config: {
87 const int rowBytes = srcRect.width() * 3; 137 const int rowBytes = srcRect.width() * 3;
88 image = new SkMemoryStream(rowBytes * srcRect.height()); 138 image = new SkMemoryStream(rowBytes * srcRect.height());
89 uint8_t* dst = (uint8_t*)image->getMemoryBase(); 139 uint8_t* dst = (uint8_t*)image->getMemoryBase();
90 for (int y = srcRect.fTop; y < srcRect.fBottom; y++) { 140 for (int y = srcRect.fTop; y < srcRect.fBottom; y++) {
91 uint16_t* src = bitmap.getAddr16(0, y); 141 uint16_t* src = bitmap.getAddr16(0, y);
92 for (int x = srcRect.fLeft; x < srcRect.fRight; x++) { 142 for (int x = srcRect.fLeft; x < srcRect.fRight; x++) {
93 dst[0] = SkGetPackedR16(src[x]); 143 dst[0] = SkGetPackedR16(src[x]);
94 dst[1] = SkGetPackedG16(src[x]); 144 dst[1] = SkGetPackedG16(src[x]);
95 dst[2] = SkGetPackedB16(src[x]); 145 dst[2] = SkGetPackedB16(src[x]);
96 dst += 3; 146 dst += 3;
97 } 147 }
98 } 148 }
99 break; 149 break;
100 } 150 }
101 case SkBitmap::kARGB_8888_Config: { 151 case SkBitmap::kARGB_8888_Config: {
102 isTransparent = true; 152 isTransparent = true;
103 const int rowBytes = srcRect.width() * 3; 153 const int rowBytes = srcRect.width() * 3;
104 image = new SkMemoryStream(rowBytes * srcRect.height()); 154 image = new SkMemoryStream(rowBytes * srcRect.height());
105 alpha = new SkMemoryStream(srcRect.width() * srcRect.height()); 155 alpha = new SkMemoryStream(srcRect.width() * srcRect.height());
106 uint8_t* dst = (uint8_t*)image->getMemoryBase(); 156 uint8_t* dst = (uint8_t*)image->getMemoryBase();
107 uint8_t* alphaDst = (uint8_t*)alpha->getMemoryBase(); 157 uint8_t* alphaDst = (uint8_t*)alpha->getMemoryBase();
108 for (int y = srcRect.fTop; y < srcRect.fBottom; y++) { 158 for (int y = srcRect.fTop; y < srcRect.fBottom; y++) {
109 uint32_t* src = bitmap.getAddr32(0, y); 159 uint32_t* src = bitmap.getAddr32(0, y);
110 for (int x = srcRect.fLeft; x < srcRect.fRight; x++) { 160 for (int x = srcRect.fLeft; x < srcRect.fRight; x++) {
111 dst[0] = SkGetPackedR32(src[x]);
112 dst[1] = SkGetPackedG32(src[x]);
113 dst[2] = SkGetPackedB32(src[x]);
114 dst += 3;
115 alphaDst[0] = SkGetPackedA32(src[x]); 161 alphaDst[0] = SkGetPackedA32(src[x]);
116 if (alphaDst[0] != 0xFF) { 162 if (alphaDst[0] != SK_AlphaOPAQUE) {
117 hasAlpha = true; 163 hasAlpha = true;
118 } 164 }
119 if (alphaDst[0]) { 165 if (alphaDst[0] != SK_AlphaTRANSPARENT) {
120 isTransparent = false; 166 isTransparent = false;
121 } 167 }
168 unpremultiply_and_pack_argb8888(src[x], dst);
122 alphaDst++; 169 alphaDst++;
170 dst += 3;
123 } 171 }
124 } 172 }
125 break; 173 break;
126 } 174 }
127 case SkBitmap::kA1_Config: { 175 case SkBitmap::kA1_Config: {
128 isTransparent = true; 176 isTransparent = true;
129 image = new SkMemoryStream(1); 177 image = new SkMemoryStream(1);
130 ((uint8_t*)image->getMemoryBase())[0] = 0; 178 ((uint8_t*)image->getMemoryBase())[0] = 0;
131 179
132 const int alphaRowBytes = (srcRect.width() + 7) / 8; 180 const int alphaRowBytes = (srcRect.width() + 7) / 8;
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
330 decodeValue->reserve(6); 378 decodeValue->reserve(6);
331 decodeValue->append(zeroVal.get()); 379 decodeValue->append(zeroVal.get());
332 decodeValue->append(scale5Val.get()); 380 decodeValue->append(scale5Val.get());
333 decodeValue->append(zeroVal.get()); 381 decodeValue->append(zeroVal.get());
334 decodeValue->append(scale6Val.get()); 382 decodeValue->append(scale6Val.get());
335 decodeValue->append(zeroVal.get()); 383 decodeValue->append(zeroVal.get());
336 decodeValue->append(scale5Val.get()); 384 decodeValue->append(scale5Val.get());
337 insert("Decode", decodeValue.get()); 385 insert("Decode", decodeValue.get());
338 } 386 }
339 } 387 }
OLDNEW
« gm/bitmappremul.cpp ('K') | « gyp/gmslides.gypi ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698