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