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

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

Issue 22889020: Refactor SkPDFImage (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: More style fixes 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 | « src/pdf/SkPDFImage.h ('k') | src/pdf/SkPDFImageStream.h » ('j') | 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 "SkData.h"
14 #include "SkFlate.h"
13 #include "SkPDFCatalog.h" 15 #include "SkPDFCatalog.h"
14 #include "SkRect.h" 16 #include "SkRect.h"
15 #include "SkStream.h" 17 #include "SkStream.h"
16 #include "SkString.h" 18 #include "SkString.h"
17 #include "SkUnPreMultiply.h" 19 #include "SkUnPreMultiply.h"
18 20
19 namespace { 21 static const int kNoColorTransform = 0;
20 22
21 void extractImageData(const SkBitmap& bitmap, const SkIRect& srcRect, 23 static bool skip_compression(SkPDFCatalog* catalog) {
22 SkStream** imageData, SkStream** alphaData) { 24 return SkToBool(catalog->getDocumentFlags() &
23 SkMemoryStream* image = NULL; 25 SkPDFDocument::kFavorSpeedOverSize_Flags);
24 SkMemoryStream* alpha = NULL; 26 }
25 bool hasAlpha = false; 27
26 bool isTransparent = false; 28 static size_t get_uncompressed_size(const SkBitmap& bitmap,
27 29 const SkIRect& srcRect) {
28 bitmap.lockPixels();
29 switch (bitmap.getConfig()) { 30 switch (bitmap.getConfig()) {
30 case SkBitmap::kIndex8_Config: { 31 case SkBitmap::kIndex8_Config:
31 const int rowBytes = srcRect.width(); 32 return srcRect.width() * srcRect.height();
32 image = new SkMemoryStream(rowBytes * srcRect.height()); 33 case SkBitmap::kARGB_4444_Config:
33 uint8_t* dst = (uint8_t*)image->getMemoryBase(); 34 return ((srcRect.width() * 3 + 1) / 2) * srcRect.height();
34 for (int y = srcRect.fTop; y < srcRect.fBottom; y++) { 35 case SkBitmap::kRGB_565_Config:
35 memcpy(dst, bitmap.getAddr8(srcRect.fLeft, y), rowBytes); 36 return srcRect.width() * 3 * srcRect.height();
36 dst += rowBytes; 37 case SkBitmap::kARGB_8888_Config:
37 } 38 return srcRect.width() * 3 * srcRect.height();
38 break; 39 case SkBitmap::kA1_Config:
39 } 40 case SkBitmap::kA8_Config:
40 case SkBitmap::kARGB_4444_Config: { 41 return 1;
41 isTransparent = true;
42 const int rowBytes = (srcRect.width() * 3 + 1) / 2;
43 const int alphaRowBytes = (srcRect.width() + 1) / 2;
44 image = new SkMemoryStream(rowBytes * srcRect.height());
45 alpha = new SkMemoryStream(alphaRowBytes * srcRect.height());
46 uint8_t* dst = (uint8_t*)image->getMemoryBase();
47 uint8_t* alphaDst = (uint8_t*)alpha->getMemoryBase();
48 for (int y = srcRect.fTop; y < srcRect.fBottom; y++) {
49 uint16_t* src = bitmap.getAddr16(0, y);
50 int x;
51 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) |
60 SkGetPackedA4444(src[x + 1]);
61 if (alphaDst[0] != 0xFF) {
62 hasAlpha = true;
63 }
64 if (alphaDst[0]) {
65 isTransparent = false;
66 }
67 alphaDst++;
68 }
69 if (srcRect.width() & 1) {
70 dst[0] = (SkGetPackedR4444(src[x]) << 4) |
71 SkGetPackedG4444(src[x]);
72 dst[1] = (SkGetPackedB4444(src[x]) << 4);
73 dst += 2;
74 alphaDst[0] = (SkGetPackedA4444(src[x]) << 4);
75 if (alphaDst[0] != 0xF0) {
76 hasAlpha = true;
77 }
78 if (alphaDst[0] & 0xF0) {
79 isTransparent = false;
80 }
81 alphaDst++;
82 }
83 }
84 break;
85 }
86 case SkBitmap::kRGB_565_Config: {
87 const int rowBytes = srcRect.width() * 3;
88 image = new SkMemoryStream(rowBytes * srcRect.height());
89 uint8_t* dst = (uint8_t*)image->getMemoryBase();
90 for (int y = srcRect.fTop; y < srcRect.fBottom; y++) {
91 uint16_t* src = bitmap.getAddr16(0, y);
92 for (int x = srcRect.fLeft; x < srcRect.fRight; x++) {
93 dst[0] = SkGetPackedR16(src[x]);
94 dst[1] = SkGetPackedG16(src[x]);
95 dst[2] = SkGetPackedB16(src[x]);
96 dst += 3;
97 }
98 }
99 break;
100 }
101 case SkBitmap::kARGB_8888_Config: {
102 isTransparent = true;
103 const int rowBytes = srcRect.width() * 3;
104 image = new SkMemoryStream(rowBytes * srcRect.height());
105 alpha = new SkMemoryStream(srcRect.width() * srcRect.height());
106 uint8_t* dst = (uint8_t*)image->getMemoryBase();
107 uint8_t* alphaDst = (uint8_t*)alpha->getMemoryBase();
108 for (int y = srcRect.fTop; y < srcRect.fBottom; y++) {
109 uint32_t* src = bitmap.getAddr32(0, y);
110 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]);
116 if (alphaDst[0] != 0xFF) {
117 hasAlpha = true;
118 }
119 if (alphaDst[0]) {
120 isTransparent = false;
121 }
122 alphaDst++;
123 }
124 }
125 break;
126 }
127 case SkBitmap::kA1_Config: {
128 isTransparent = true;
129 image = new SkMemoryStream(1);
130 ((uint8_t*)image->getMemoryBase())[0] = 0;
131
132 const int alphaRowBytes = (srcRect.width() + 7) / 8;
133 alpha = new SkMemoryStream(alphaRowBytes * srcRect.height());
134 uint8_t* alphaDst = (uint8_t*)alpha->getMemoryBase();
135 int offset1 = srcRect.fLeft % 8;
136 int offset2 = 8 - offset1;
137 for (int y = srcRect.fTop; y < srcRect.fBottom; y++) {
138 uint8_t* src = bitmap.getAddr1(0, y);
139 // This may read up to one byte after src, but the potentially
140 // invalid bits are never used for computation.
141 for (int x = srcRect.fLeft; x < srcRect.fRight; x += 8) {
142 if (offset1) {
143 alphaDst[0] = src[x / 8] << offset1 |
144 src[x / 8 + 1] >> offset2;
145 } else {
146 alphaDst[0] = src[x / 8];
147 }
148 if (x + 7 < srcRect.fRight && alphaDst[0] != 0xFF) {
149 hasAlpha = true;
150 }
151 if (x + 7 < srcRect.fRight && alphaDst[0]) {
152 isTransparent = false;
153 }
154 alphaDst++;
155 }
156 // Calculate the mask of bits we're interested in within the
157 // last byte of alphaDst.
158 // width mod 8 == 1 -> 0x80 ... width mod 8 == 7 -> 0xFE
159 uint8_t mask = ~((1 << (8 - (srcRect.width() % 8))) - 1);
160 if (srcRect.width() % 8 && (alphaDst[-1] & mask) != mask) {
161 hasAlpha = true;
162 }
163 if (srcRect.width() % 8 && (alphaDst[-1] & mask)) {
164 isTransparent = false;
165 }
166 }
167 break;
168 }
169 case SkBitmap::kA8_Config: {
170 isTransparent = true;
171 image = new SkMemoryStream(1);
172 ((uint8_t*)image->getMemoryBase())[0] = 0;
173
174 const int alphaRowBytes = srcRect.width();
175 alpha = new SkMemoryStream(alphaRowBytes * srcRect.height());
176 uint8_t* alphaDst = (uint8_t*)alpha->getMemoryBase();
177 for (int y = srcRect.fTop; y < srcRect.fBottom; y++) {
178 uint8_t* src = bitmap.getAddr8(0, y);
179 for (int x = srcRect.fLeft; x < srcRect.fRight; x++) {
180 alphaDst[0] = src[x];
181 if (alphaDst[0] != 0xFF) {
182 hasAlpha = true;
183 }
184 if (alphaDst[0]) {
185 isTransparent = false;
186 }
187 alphaDst++;
188 }
189 }
190 break;
191 }
192 default: 42 default:
193 SkASSERT(false); 43 SkASSERT(false);
44 return 0;
45 }
46 }
47
48 static SkStream* extract_index8_image(const SkBitmap& bitmap,
49 const SkIRect& srcRect) {
50 const int rowBytes = srcRect.width();
51 SkStream* stream = SkNEW_ARGS(SkMemoryStream,
52 (get_uncompressed_size(bitmap, srcRect)));
53 uint8_t* dst = (uint8_t*)stream->getMemoryBase();
54
55 for (int y = srcRect.fTop; y < srcRect.fBottom; y++) {
56 memcpy(dst, bitmap.getAddr8(srcRect.fLeft, y), rowBytes);
57 dst += rowBytes;
58 }
59 return stream;
60 }
61
62 static SkStream* extract_argb4444_data(const SkBitmap& bitmap,
63 const SkIRect& srcRect,
64 bool extractAlpha,
65 bool* isOpaque,
66 bool* isTransparent) {
67 SkStream* stream;
68 uint8_t* dst = NULL;
69 if (extractAlpha) {
70 const int alphaRowBytes = (srcRect.width() + 1) / 2;
71 stream = SkNEW_ARGS(SkMemoryStream,
72 (alphaRowBytes * srcRect.height()));
73 } else {
74 stream = SkNEW_ARGS(SkMemoryStream,
75 (get_uncompressed_size(bitmap, srcRect)));
76 }
77 dst = (uint8_t*)stream->getMemoryBase();
78
79 for (int y = srcRect.fTop; y < srcRect.fBottom; y++) {
80 uint16_t* src = bitmap.getAddr16(0, y);
81 int x;
82 for (x = srcRect.fLeft; x + 1 < srcRect.fRight; x += 2) {
83 if (extractAlpha) {
84 dst[0] = (SkGetPackedA4444(src[x]) << 4) |
85 SkGetPackedA4444(src[x + 1]);
86 *isOpaque &= dst[0] == SK_AlphaOPAQUE;
87 *isTransparent &= dst[0] == SK_AlphaTRANSPARENT;
88 dst++;
89 } else {
90 dst[0] = (SkGetPackedR4444(src[x]) << 4) |
91 SkGetPackedG4444(src[x]);
92 dst[1] = (SkGetPackedB4444(src[x]) << 4) |
93 SkGetPackedR4444(src[x + 1]);
94 dst[2] = (SkGetPackedG4444(src[x + 1]) << 4) |
95 SkGetPackedB4444(src[x + 1]);
96 dst += 3;
97 }
98 }
99 if (srcRect.width() & 1) {
100 if (extractAlpha) {
101 dst[0] = (SkGetPackedA4444(src[x]) << 4);
102 *isOpaque &= dst[0] == (SK_AlphaOPAQUE & 0xF0);
103 *isTransparent &= dst[0] == (SK_AlphaTRANSPARENT & 0xF0);
104 dst++;
105
106 } else {
107 dst[0] = (SkGetPackedR4444(src[x]) << 4) |
108 SkGetPackedG4444(src[x]);
109 dst[1] = (SkGetPackedB4444(src[x]) << 4);
110 dst += 2;
111 }
112 }
113 }
114 return stream;
115 }
116
117 static SkStream* extract_rgb565_image(const SkBitmap& bitmap,
118 const SkIRect& srcRect) {
119 SkStream* stream = SkNEW_ARGS(SkMemoryStream,
120 (get_uncompressed_size(bitmap,
121 srcRect)));
122 uint8_t* dst = (uint8_t*)stream->getMemoryBase();
123 for (int y = srcRect.fTop; y < srcRect.fBottom; y++) {
124 uint16_t* src = bitmap.getAddr16(0, y);
125 for (int x = srcRect.fLeft; x < srcRect.fRight; x++) {
126 dst[0] = SkGetPackedR16(src[x]);
127 dst[1] = SkGetPackedG16(src[x]);
128 dst[2] = SkGetPackedB16(src[x]);
129 dst += 3;
130 }
131 }
132 return stream;
133 }
134
135 static SkStream* extract_argb8888_data(const SkBitmap& bitmap,
136 const SkIRect& srcRect,
137 bool extractAlpha,
138 bool* isOpaque,
139 bool* isTransparent) {
140 SkStream* stream;
141 if (extractAlpha) {
142 stream = SkNEW_ARGS(SkMemoryStream,
143 (srcRect.width() * srcRect.height()));
144 } else {
145 stream = SkNEW_ARGS(SkMemoryStream,
146 (get_uncompressed_size(bitmap, srcRect)));
147 }
148 uint8_t* dst = (uint8_t*)stream->getMemoryBase();
149
150 for (int y = srcRect.fTop; y < srcRect.fBottom; y++) {
151 uint32_t* src = bitmap.getAddr32(0, y);
152 for (int x = srcRect.fLeft; x < srcRect.fRight; x++) {
153 if (extractAlpha) {
154 dst[0] = SkGetPackedA32(src[x]);
155 *isOpaque &= dst[0] == SK_AlphaOPAQUE;
156 *isTransparent &= dst[0] == SK_AlphaTRANSPARENT;
157 dst++;
158 } else {
159 dst[0] = SkGetPackedR32(src[x]);
160 dst[1] = SkGetPackedG32(src[x]);
161 dst[2] = SkGetPackedB32(src[x]);
162 dst += 3;
163 }
164 }
165 }
166 return stream;
167 }
168
169 static SkStream* extract_a1_alpha(const SkBitmap& bitmap,
170 const SkIRect& srcRect,
171 bool* isOpaque,
172 bool* isTransparent) {
173 const int alphaRowBytes = (srcRect.width() + 7) / 8;
174 SkStream* stream = SkNEW_ARGS(SkMemoryStream,
175 (alphaRowBytes * srcRect.height()));
176 uint8_t* alphaDst = (uint8_t*)stream->getMemoryBase();
177
178 int offset1 = srcRect.fLeft % 8;
179 int offset2 = 8 - offset1;
180
181 for (int y = srcRect.fTop; y < srcRect.fBottom; y++) {
182 uint8_t* src = bitmap.getAddr1(0, y);
183 // This may read up to one byte after src, but the
184 // potentially invalid bits are never used for computation.
185 for (int x = srcRect.fLeft; x < srcRect.fRight; x += 8) {
186 if (offset1) {
187 alphaDst[0] = src[x / 8] << offset1 |
188 src[x / 8 + 1] >> offset2;
189 } else {
190 alphaDst[0] = src[x / 8];
191 }
192 if (x + 7 < srcRect.fRight) {
193 *isOpaque &= alphaDst[0] == SK_AlphaOPAQUE;
194 *isTransparent &= alphaDst[0] == SK_AlphaTRANSPARENT;
195 }
196 alphaDst++;
197 }
198 // Calculate the mask of bits we're interested in within the
199 // last byte of alphaDst.
200 // width mod 8 == 1 -> 0x80 ... width mod 8 == 7 -> 0xFE
201 uint8_t mask = ~((1 << (8 - (srcRect.width() % 8))) - 1);
202 if (srcRect.width() % 8) {
203 *isOpaque &= (alphaDst[-1] & mask) == (SK_AlphaOPAQUE & mask);
204 *isTransparent &=
205 (alphaDst[-1] & mask) == (SK_AlphaTRANSPARENT & mask);
206 }
207 }
208 return stream;
209 }
210
211 static SkStream* extract_a8_alpha(const SkBitmap& bitmap,
212 const SkIRect& srcRect,
213 bool* isOpaque,
214 bool* isTransparent) {
215 const int alphaRowBytes = srcRect.width();
216 SkStream* stream = SkNEW_ARGS(SkMemoryStream,
217 (alphaRowBytes * srcRect.height()));
218 uint8_t* alphaDst = (uint8_t*)stream->getMemoryBase();
219
220 for (int y = srcRect.fTop; y < srcRect.fBottom; y++) {
221 uint8_t* src = bitmap.getAddr8(0, y);
222 for (int x = srcRect.fLeft; x < srcRect.fRight; x++) {
223 alphaDst[0] = src[x];
224 *isOpaque &= alphaDst[0] == SK_AlphaOPAQUE;
225 *isTransparent &= alphaDst[0] == SK_AlphaTRANSPARENT;
226 alphaDst++;
227 }
228 }
229 return stream;
230 }
231
232 static SkStream* create_black_image() {
233 SkStream* stream = SkNEW_ARGS(SkMemoryStream, (1));
234 ((uint8_t*)stream->getMemoryBase())[0] = 0;
235 return stream;
236 }
237
238 /**
239 * Extract either the color or image data from a SkBitmap into a SkStream.
240 * @param bitmap Bitmap to extract data from.
241 * @param srcRect Region in the bitmap to extract.
242 * @param extractAlpha Set to true to extract the alpha data or false to
243 * extract the color data.
244 * @param isTransparent Pointer to a bool to output whether the alpha is
245 * completely transparent. May be NULL. Only valid when
246 * extractAlpha == true.
247 * @return Unencoded image data, or NULL if either data was not
248 * available or alpha data was requested but the image was
249 * entirely transparent or opaque.
250 */
251 static SkStream* extract_image_data(const SkBitmap& bitmap,
252 const SkIRect& srcRect,
253 bool extractAlpha, bool* isTransparent) {
254 SkBitmap::Config config = bitmap.config();
255 if (extractAlpha && (config == SkBitmap::kIndex8_Config ||
256 config == SkBitmap::kRGB_565_Config)) {
257 if (isTransparent != NULL) {
258 *isTransparent = false;
259 }
260 return NULL;
261 }
262 bool isOpaque = true;
263 bool localTransparent = true;
vandebo (ex-Chrome) 2013/08/23 18:22:52 nit: localTransparent -> transparent
vandebo (ex-Chrome) 2013/08/23 18:22:52 init to extractAlpha
264 SkStream* stream = NULL;
265
266 bitmap.lockPixels();
267 switch (config) {
268 case SkBitmap::kIndex8_Config:
269 if (!extractAlpha) {
270 stream = extract_index8_image(bitmap, srcRect);
271 }
272 break;
273 case SkBitmap::kARGB_4444_Config:
274 stream = extract_argb4444_data(bitmap, srcRect, extractAlpha,
275 &isOpaque, &localTransparent);
276 break;
277 case SkBitmap::kRGB_565_Config:
278 if (!extractAlpha) {
279 stream = extract_rgb565_image(bitmap, srcRect);
280 }
281 break;
282 case SkBitmap::kARGB_8888_Config:
283 stream = extract_argb8888_data(bitmap, srcRect, extractAlpha,
284 &isOpaque, &localTransparent);
285 break;
286 case SkBitmap::kA1_Config:
287 if (!extractAlpha) {
288 stream = create_black_image();
289 } else {
290 stream = extract_a1_alpha(bitmap, srcRect,
291 &isOpaque, &localTransparent);
292 }
293 break;
294 case SkBitmap::kA8_Config:
295 if (!extractAlpha) {
296 stream = create_black_image();
297 } else {
298 stream = extract_a8_alpha(bitmap, srcRect,
299 &isOpaque, &localTransparent);
300 }
301 break;
302 default:
303 SkASSERT(false);
194 } 304 }
195 bitmap.unlockPixels(); 305 bitmap.unlockPixels();
196 306
197 if (isTransparent) { 307 if (isTransparent != NULL) {
198 SkSafeUnref(image); 308 *isTransparent = localTransparent;
199 } else { 309 }
200 *imageData = image; 310 if (extractAlpha && (localTransparent || isOpaque)) {
201 } 311 SkSafeUnref(stream);
202 312 return NULL;
203 if (isTransparent || !hasAlpha) { 313 }
204 SkSafeUnref(alpha); 314 return stream;
205 } else { 315 }
206 *alphaData = alpha; 316
207 } 317 static SkPDFArray* make_indexed_color_space(SkColorTable* table) {
208 }
209
210 SkPDFArray* makeIndexedColorSpace(SkColorTable* table) {
211 SkPDFArray* result = new SkPDFArray(); 318 SkPDFArray* result = new SkPDFArray();
212 result->reserve(4); 319 result->reserve(4);
213 result->appendName("Indexed"); 320 result->appendName("Indexed");
214 result->appendName("DeviceRGB"); 321 result->appendName("DeviceRGB");
215 result->appendInt(table->count() - 1); 322 result->appendInt(table->count() - 1);
216 323
217 // Potentially, this could be represented in fewer bytes with a stream. 324 // Potentially, this could be represented in fewer bytes with a stream.
218 // Max size as a string is 1.5k. 325 // Max size as a string is 1.5k.
219 SkString index; 326 SkString index;
220 for (int i = 0; i < table->count(); i++) { 327 for (int i = 0; i < table->count(); i++) {
221 char buf[3]; 328 char buf[3];
222 SkColor color = SkUnPreMultiply::PMColorToColor((*table)[i]); 329 SkColor color = SkUnPreMultiply::PMColorToColor((*table)[i]);
223 buf[0] = SkGetPackedR32(color); 330 buf[0] = SkGetPackedR32(color);
224 buf[1] = SkGetPackedG32(color); 331 buf[1] = SkGetPackedG32(color);
225 buf[2] = SkGetPackedB32(color); 332 buf[2] = SkGetPackedB32(color);
226 index.append(buf, 3); 333 index.append(buf, 3);
227 } 334 }
228 result->append(new SkPDFString(index))->unref(); 335 result->append(new SkPDFString(index))->unref();
229 return result; 336 return result;
230 } 337 }
231 338
232 }; // namespace
233
234 // static 339 // static
235 SkPDFImage* SkPDFImage::CreateImage(const SkBitmap& bitmap, 340 SkPDFImage* SkPDFImage::CreateImage(const SkBitmap& bitmap,
236 const SkIRect& srcRect, 341 const SkIRect& srcRect,
237 EncodeToDCTStream encoder) { 342 EncodeToDCTStream encoder) {
238 if (bitmap.getConfig() == SkBitmap::kNo_Config) { 343 if (bitmap.getConfig() == SkBitmap::kNo_Config) {
239 return NULL; 344 return NULL;
240 } 345 }
241 346
242 SkStream* imageData = NULL; 347 bool isTransparent = false;
243 SkStream* alphaData = NULL; 348 SkAutoTUnref<SkStream> alphaData;
244 extractImageData(bitmap, srcRect, &imageData, &alphaData); 349 if (!bitmap.isOpaque()) {
245 SkAutoUnref unrefImageData(imageData); 350 // Note that isOpaque is not guaranteed to return false for bitmaps
246 SkAutoUnref unrefAlphaData(alphaData); 351 // with alpha support but a completely opaque alpha channel,
247 if (!imageData) { 352 // so alphaData may still be NULL if we have a completely opaque
248 SkASSERT(!alphaData); 353 // (or transparent) bitmap.
354 alphaData.reset(
355 extract_image_data(bitmap, srcRect, true, &isTransparent));
356 }
357 if (isTransparent) {
249 return NULL; 358 return NULL;
250 } 359 }
251 360
252 SkPDFImage* image = 361 SkPDFImage* image = SkNEW_ARGS(SkPDFImage, (NULL, bitmap,
253 SkNEW_ARGS(SkPDFImage, (imageData, bitmap, srcRect, false, encoder)); 362 false, srcRect, encoder));
363 if (alphaData.get() != NULL) {
364 SkAutoTUnref<SkPDFImage> mask(
365 SkNEW_ARGS(SkPDFImage, (alphaData.get(), bitmap,
366 true, srcRect, NULL)));
367 image->addSMask(mask);
368 }
254 369
255 if (alphaData != NULL) {
256 // Don't try to use DCT compression with alpha because alpha is small
257 // anyway and it could lead to artifacts.
258 image->addSMask(SkNEW_ARGS(SkPDFImage, (alphaData, bitmap, srcRect, true , NULL)))->unref();
259 }
260 return image; 370 return image;
261 } 371 }
262 372
263 SkPDFImage::~SkPDFImage() { 373 SkPDFImage::~SkPDFImage() {
264 fResources.unrefAll(); 374 fResources.unrefAll();
265 } 375 }
266 376
267 SkPDFImage* SkPDFImage::addSMask(SkPDFImage* mask) { 377 SkPDFImage* SkPDFImage::addSMask(SkPDFImage* mask) {
268 fResources.push(mask); 378 fResources.push(mask);
269 mask->ref(); 379 mask->ref();
270 insert("SMask", new SkPDFObjRef(mask))->unref(); 380 insert("SMask", new SkPDFObjRef(mask))->unref();
271 return mask; 381 return mask;
272 } 382 }
273 383
274 void SkPDFImage::getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, 384 void SkPDFImage::getResources(const SkTSet<SkPDFObject*>& knownResourceObjects,
275 SkTSet<SkPDFObject*>* newResourceObjects) { 385 SkTSet<SkPDFObject*>* newResourceObjects) {
276 GetResourcesHelper(&fResources, knownResourceObjects, newResourceObjects); 386 GetResourcesHelper(&fResources, knownResourceObjects, newResourceObjects);
277 } 387 }
278 388
279 SkPDFImage::SkPDFImage(SkStream* imageData, 389 SkPDFImage::SkPDFImage(SkStream* stream,
280 const SkBitmap& bitmap, 390 const SkBitmap& bitmap,
391 bool isAlpha,
281 const SkIRect& srcRect, 392 const SkIRect& srcRect,
282 bool doingAlpha,
283 EncodeToDCTStream encoder) 393 EncodeToDCTStream encoder)
284 : SkPDFImageStream(imageData, bitmap, srcRect, encoder) { 394 : fBitmap(bitmap),
285 SkBitmap::Config config = bitmap.getConfig(); 395 fIsAlpha(isAlpha),
286 bool alphaOnly = (config == SkBitmap::kA1_Config || 396 fSrcRect(srcRect),
287 config == SkBitmap::kA8_Config); 397 fEncoder(encoder) {
398
399 if (stream != NULL) {
400 setData(stream);
401 fStreamValid = true;
402 } else {
403 fStreamValid = false;
404 }
405
406 SkBitmap::Config config = fBitmap.getConfig();
288 407
289 insertName("Type", "XObject"); 408 insertName("Type", "XObject");
290 insertName("Subtype", "Image"); 409 insertName("Subtype", "Image");
291 410
292 if (!doingAlpha && alphaOnly) { 411 bool alphaOnly = (config == SkBitmap::kA1_Config ||
412 config == SkBitmap::kA8_Config);
413
414 if (!isAlpha && alphaOnly) {
293 // For alpha only images, we stretch a single pixel of black for 415 // For alpha only images, we stretch a single pixel of black for
294 // the color/shape part. 416 // the color/shape part.
295 SkAutoTUnref<SkPDFInt> one(new SkPDFInt(1)); 417 SkAutoTUnref<SkPDFInt> one(new SkPDFInt(1));
296 insert("Width", one.get()); 418 insert("Width", one.get());
297 insert("Height", one.get()); 419 insert("Height", one.get());
298 } else { 420 } else {
299 insertInt("Width", srcRect.width()); 421 insertInt("Width", fSrcRect.width());
300 insertInt("Height", srcRect.height()); 422 insertInt("Height", fSrcRect.height());
301 } 423 }
302 424
303 // if (!image mask) { 425 if (isAlpha || alphaOnly) {
304 if (doingAlpha || alphaOnly) {
305 insertName("ColorSpace", "DeviceGray"); 426 insertName("ColorSpace", "DeviceGray");
306 } else if (config == SkBitmap::kIndex8_Config) { 427 } else if (config == SkBitmap::kIndex8_Config) {
307 SkAutoLockPixels alp(bitmap); 428 SkAutoLockPixels alp(fBitmap);
308 insert("ColorSpace", 429 insert("ColorSpace",
309 makeIndexedColorSpace(bitmap.getColorTable()))->unref(); 430 make_indexed_color_space(fBitmap.getColorTable()))->unref();
310 } else { 431 } else {
311 insertName("ColorSpace", "DeviceRGB"); 432 insertName("ColorSpace", "DeviceRGB");
312 } 433 }
313 // }
314 434
315 int bitsPerComp = 8; 435 int bitsPerComp = 8;
316 if (config == SkBitmap::kARGB_4444_Config) { 436 if (config == SkBitmap::kARGB_4444_Config) {
317 bitsPerComp = 4; 437 bitsPerComp = 4;
318 } else if (doingAlpha && config == SkBitmap::kA1_Config) { 438 } else if (isAlpha && config == SkBitmap::kA1_Config) {
319 bitsPerComp = 1; 439 bitsPerComp = 1;
320 } 440 }
321 insertInt("BitsPerComponent", bitsPerComp); 441 insertInt("BitsPerComponent", bitsPerComp);
322 442
323 if (config == SkBitmap::kRGB_565_Config) { 443 if (config == SkBitmap::kRGB_565_Config) {
444 SkASSERT(!isAlpha);
324 SkAutoTUnref<SkPDFInt> zeroVal(new SkPDFInt(0)); 445 SkAutoTUnref<SkPDFInt> zeroVal(new SkPDFInt(0));
325 SkAutoTUnref<SkPDFScalar> scale5Val( 446 SkAutoTUnref<SkPDFScalar> scale5Val(
326 new SkPDFScalar(SkFloatToScalar(8.2258f))); // 255/2^5-1 447 new SkPDFScalar(SkFloatToScalar(8.2258f))); // 255/2^5-1
327 SkAutoTUnref<SkPDFScalar> scale6Val( 448 SkAutoTUnref<SkPDFScalar> scale6Val(
328 new SkPDFScalar(SkFloatToScalar(4.0476f))); // 255/2^6-1 449 new SkPDFScalar(SkFloatToScalar(4.0476f))); // 255/2^6-1
329 SkAutoTUnref<SkPDFArray> decodeValue(new SkPDFArray()); 450 SkAutoTUnref<SkPDFArray> decodeValue(new SkPDFArray());
330 decodeValue->reserve(6); 451 decodeValue->reserve(6);
331 decodeValue->append(zeroVal.get()); 452 decodeValue->append(zeroVal.get());
332 decodeValue->append(scale5Val.get()); 453 decodeValue->append(scale5Val.get());
333 decodeValue->append(zeroVal.get()); 454 decodeValue->append(zeroVal.get());
334 decodeValue->append(scale6Val.get()); 455 decodeValue->append(scale6Val.get());
335 decodeValue->append(zeroVal.get()); 456 decodeValue->append(zeroVal.get());
336 decodeValue->append(scale5Val.get()); 457 decodeValue->append(scale5Val.get());
337 insert("Decode", decodeValue.get()); 458 insert("Decode", decodeValue.get());
338 } 459 }
339 } 460 }
461
462 SkPDFImage::SkPDFImage(SkPDFImage& pdfImage)
463 : SkPDFStream(pdfImage),
464 fBitmap(pdfImage.fBitmap),
465 fIsAlpha(pdfImage.fIsAlpha),
466 fSrcRect(pdfImage.fSrcRect),
467 fEncoder(pdfImage.fEncoder),
468 fStreamValid(pdfImage.fStreamValid) {
469 // Nothing to do here - the image params are already copied in SkPDFStream's
470 // constructor, and the bitmap will be regenerated and encoded in
471 // populate.
472 }
473
474 bool SkPDFImage::populate(SkPDFCatalog* catalog) {
475 if (getState() == kUnused_State) {
476 // Initializing image data for the first time.
477 SkDynamicMemoryWStream dctCompressedWStream;
478 if (!skip_compression(catalog) && fEncoder &&
479 get_uncompressed_size(fBitmap, fSrcRect) > 1 &&
480 fEncoder(&dctCompressedWStream, fBitmap, fSrcRect) &&
481 dctCompressedWStream.getOffset() <
482 get_uncompressed_size(fBitmap, fSrcRect)) {
483 SkAutoTUnref<SkData> data(dctCompressedWStream.copyToData());
484 SkAutoTUnref<SkStream> stream(SkNEW_ARGS(SkMemoryStream, (data)));
485 setData(stream.get());
486
487 insertName("Filter", "DCTDecode");
488 insertInt("ColorTransform", kNoColorTransform);
489 insertInt("Length", getData()->getLength());
490 setState(kCompressed_State);
491 return true;
492 }
493 // Fallback method
494 if (!fStreamValid) {
495 SkAutoTUnref<SkStream> stream(
496 extract_image_data(fBitmap, fSrcRect, fIsAlpha, NULL));
497 setData(stream);
498 fStreamValid = true;
499 }
500 return INHERITED::populate(catalog);
501 } else if (getState() == kNoCompression_State &&
502 !skip_compression(catalog) &&
503 (SkFlate::HaveFlate() || fEncoder)) {
504 // Compression has not been requested when the stream was first created,
505 // but the new catalog wants it compressed.
506 if (!getSubstitute()) {
507 SkPDFStream* substitute = SkNEW_ARGS(SkPDFImage, (*this));
508 setSubstitute(substitute);
509 catalog->setSubstitute(this, substitute);
510 }
511 return false;
512 }
513 return true;
514 }
OLDNEW
« no previous file with comments | « src/pdf/SkPDFImage.h ('k') | src/pdf/SkPDFImageStream.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698