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

Side by Side Diff: src/codec/SkBmpStandardCodec.cpp

Issue 1287423002: Scanline decoding for bmp (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Response to Leon's comments Created 5 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
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 "SkBmpStandardCodec.h" 8 #include "SkBmpStandardCodec.h"
9 #include "SkCodecPriv.h" 9 #include "SkCodecPriv.h"
10 #include "SkColorPriv.h" 10 #include "SkColorPriv.h"
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
46 } 46 }
47 if (dstInfo.dimensions() != this->getInfo().dimensions()) { 47 if (dstInfo.dimensions() != this->getInfo().dimensions()) {
48 SkCodecPrintf("Error: scaling not supported.\n"); 48 SkCodecPrintf("Error: scaling not supported.\n");
49 return kInvalidScale; 49 return kInvalidScale;
50 } 50 }
51 if (!conversion_possible(dstInfo, this->getInfo())) { 51 if (!conversion_possible(dstInfo, this->getInfo())) {
52 SkCodecPrintf("Error: cannot convert input type to output type.\n"); 52 SkCodecPrintf("Error: cannot convert input type to output type.\n");
53 return kInvalidConversion; 53 return kInvalidConversion;
54 } 54 }
55 55
56 // Create the color table if necessary and prepare the stream for decode 56 Result result = this->prepareToDecode(dstInfo, opts, inputColorPtr, inputCol orCount);
57 // Note that if it is non-NULL, inputColorCount will be modified 57 if (kSuccess != result) {
58 if (!this->createColorTable(dstInfo.alphaType(), inputColorCount)) { 58 return result;
59 SkCodecPrintf("Error: could not create color table.\n");
60 return kInvalidInput;
61 }
62
63 // Copy the color table to the client if necessary
64 copy_color_table(dstInfo, fColorTable, inputColorPtr, inputColorCount);
65
66 // Initialize a swizzler if necessary
67 if (!this->initializeSwizzler(dstInfo, opts)) {
68 SkCodecPrintf("Error: cannot initialize swizzler.\n");
69 return kInvalidConversion;
70 } 59 }
71 60
72 return this->decode(dstInfo, dst, dstRowBytes, opts); 61 return this->decode(dstInfo, dst, dstRowBytes, opts);
73 } 62 }
74 63
75 /* 64 /*
76 * Process the color table for the bmp input 65 * Process the color table for the bmp input
77 */ 66 */
78 bool SkBmpStandardCodec::createColorTable(SkAlphaType alphaType, int* numColors ) { 67 bool SkBmpStandardCodec::createColorTable(SkAlphaType alphaType, int* numColors ) {
79 // Allocate memory for color table 68 // Allocate memory for color table
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
163 } 152 }
164 } 153 }
165 154
166 // Return true on success 155 // Return true on success
167 return true; 156 return true;
168 } 157 }
169 158
170 bool SkBmpStandardCodec::initializeSwizzler(const SkImageInfo& dstInfo, 159 bool SkBmpStandardCodec::initializeSwizzler(const SkImageInfo& dstInfo,
171 const Options& opts) { 160 const Options& opts) {
172 // Allocate space for a row buffer 161 // Allocate space for a row buffer
173 const size_t rowBytes = SkAlign4(compute_row_bytes(dstInfo.width(), this->bi tsPerPixel())); 162 const size_t rowBytes = SkAlign4(compute_row_bytes(this->getInfo().width(),
163 this->bitsPerPixel()));
174 fSrcBuffer.reset(SkNEW_ARRAY(uint8_t, rowBytes)); 164 fSrcBuffer.reset(SkNEW_ARRAY(uint8_t, rowBytes));
175 165
176 // Get swizzler configuration 166 // Get swizzler configuration
177 SkSwizzler::SrcConfig config; 167 SkSwizzler::SrcConfig config;
178 switch (this->bitsPerPixel()) { 168 switch (this->bitsPerPixel()) {
179 case 1: 169 case 1:
180 config = SkSwizzler::kIndex1; 170 config = SkSwizzler::kIndex1;
181 break; 171 break;
182 case 2: 172 case 2:
183 config = SkSwizzler::kIndex2; 173 config = SkSwizzler::kIndex2;
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 SkASSERT(false); 234 SkASSERT(false);
245 return 0; 235 return 0;
246 } 236 }
247 return fillColorOrIndex; 237 return fillColorOrIndex;
248 } 238 }
249 239
250 /* 240 /*
251 * Performs the bitmap decoding for standard input format 241 * Performs the bitmap decoding for standard input format
252 */ 242 */
253 SkCodec::Result SkBmpStandardCodec::decode(const SkImageInfo& dstInfo, 243 SkCodec::Result SkBmpStandardCodec::decode(const SkImageInfo& dstInfo,
254 void* dst, size_t dstRowBytes, 244 void* dst, size_t dstRowBytes,
255 const Options& opts) { 245 const Options& opts) {
256 // Set constant values 246 // Set constant values
257 const int width = dstInfo.width(); 247 const int width = this->getInfo().width();
258 const int height = dstInfo.height(); 248 const int height = dstInfo.height();
259 const size_t rowBytes = SkAlign4(compute_row_bytes(width, this->bitsPerPixel ())); 249 const size_t rowBytes = SkAlign4(compute_row_bytes(width, this->bitsPerPixel ()));
260 250
261 // Iterate over rows of the image 251 // Iterate over rows of the image
262 for (int y = 0; y < height; y++) { 252 for (int y = 0; y < height; y++) {
263 // Read a row of the input 253 // Read a row of the input
264 if (this->stream()->read(fSrcBuffer.get(), rowBytes) != rowBytes) { 254 if (this->stream()->read(fSrcBuffer.get(), rowBytes) != rowBytes) {
265 SkCodecPrintf("Warning: incomplete input stream.\n"); 255 SkCodecPrintf("Warning: incomplete input stream.\n");
266 // Fill the destination image on failure 256 // Fill the destination image on failure
267 // Get the fill color/index and check if it is 0 257 // Get the fill color/index and check if it is 0
268 uint32_t fillColorOrIndex = get_fill_color_or_index(this->bitsPerPix el(), 258 uint32_t fillColorOrIndex = get_fill_color_or_index(this->bitsPerPix el(),
269 dstInfo.alphaType()); 259 dstInfo.alphaType());
270 bool zeroFill = (0 == fillColorOrIndex); 260 bool zeroFill = (0 == fillColorOrIndex);
271 261
272 if (kNo_ZeroInitialized == opts.fZeroInitialized || !zeroFill) { 262 if (kNo_ZeroInitialized == opts.fZeroInitialized || !zeroFill) {
273 // Get a pointer to the color table if it exists 263 // Get a pointer to the color table if it exists
274 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); 264 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get());
275 265
276 void* dstStart = this->getDstStartRow(dst, dstRowBytes, y); 266 void* dstStart = this->getDstStartRow(dst, dstRowBytes, y);
277 SkSwizzler::Fill(dstStart, dstInfo, dstRowBytes, dstInfo.height( ) - y, 267 SkSwizzler::Fill(dstStart, dstInfo, dstRowBytes, dstInfo.height( ) - y,
278 fillColorOrIndex, colorPtr); 268 fillColorOrIndex, colorPtr);
279 } 269 }
280 return kIncompleteInput; 270 return kIncompleteInput;
281 } 271 }
282 272
283 // Decode the row in destination format 273 // Decode the row in destination format
284 uint32_t row; 274 uint32_t row = this->getDstRow(y);
285 if (SkBmpCodec::kTopDown_RowOrder == this->rowOrder()) {
286 row = y;
287 } else {
288 row = height - 1 - y;
289 }
290 275
291 void* dstRow = SkTAddOffset<void>(dst, row * dstRowBytes); 276 void* dstRow = SkTAddOffset<void>(dst, row * dstRowBytes);
292 fSwizzler->swizzle(dstRow, fSrcBuffer.get()); 277 fSwizzler->swizzle(dstRow, fSrcBuffer.get());
293 } 278 }
294 279
295 // Finally, apply the AND mask for bmp-in-ico images 280 // Finally, apply the AND mask for bmp-in-ico images
296 if (fInIco) { 281 if (fInIco) {
297 // BMP in ICO have transparency, so this cannot be 565, and this mask 282 // BMP in ICO have transparency, so this cannot be 565, and this mask
298 // prevents us from using kIndex8. The below code depends on the output 283 // prevents us from using kIndex8. The below code depends on the output
299 // being an SkPMColor. 284 // being an SkPMColor.
300 SkASSERT(dstInfo.colorType() == kN32_SkColorType); 285 SkASSERT(dstInfo.colorType() == kN32_SkColorType);
301 286
302 // The AND mask is always 1 bit per pixel 287 // The AND mask is always 1 bit per pixel
303 const size_t rowBytes = SkAlign4(compute_row_bytes(width, 1)); 288 const size_t rowBytes = SkAlign4(compute_row_bytes(width, 1));
304 289
305 SkPMColor* dstPtr = (SkPMColor*) dst; 290 SkPMColor* dstPtr = (SkPMColor*) dst;
306 for (int y = 0; y < height; y++) { 291 for (int y = 0; y < height; y++) {
307 // The srcBuffer will at least be large enough 292 // The srcBuffer will at least be large enough
308 if (stream()->read(fSrcBuffer.get(), rowBytes) != rowBytes) { 293 if (stream()->read(fSrcBuffer.get(), rowBytes) != rowBytes) {
309 SkCodecPrintf("Warning: incomplete AND mask for bmp-in-ico.\n"); 294 SkCodecPrintf("Warning: incomplete AND mask for bmp-in-ico.\n");
310 return kIncompleteInput; 295 return kIncompleteInput;
311 } 296 }
312 297
313 int row; 298 int row = this->getDstRow(y);
314 if (SkBmpCodec::kBottomUp_RowOrder == this->rowOrder()) {
315 row = height - y - 1;
316 } else {
317 row = y;
318 }
319 299
320 SkPMColor* dstRow = 300 SkPMColor* dstRow =
321 SkTAddOffset<SkPMColor>(dstPtr, row * dstRowBytes); 301 SkTAddOffset<SkPMColor>(dstPtr, row * dstRowBytes);
322 302
323 for (int x = 0; x < width; x++) { 303 for (int x = 0; x < width; x++) {
324 int quotient; 304 int quotient;
325 int modulus; 305 int modulus;
326 SkTDivMod(x, 8, &quotient, &modulus); 306 SkTDivMod(x, 8, &quotient, &modulus);
327 uint32_t shift = 7 - modulus; 307 uint32_t shift = 7 - modulus;
328 uint32_t alphaBit = 308 uint32_t alphaBit =
329 (fSrcBuffer.get()[quotient] >> shift) & 0x1; 309 (fSrcBuffer.get()[quotient] >> shift) & 0x1;
330 dstRow[x] &= alphaBit - 1; 310 dstRow[x] &= alphaBit - 1;
331 } 311 }
332 } 312 }
333 } 313 }
334 314
335 // Finished decoding the entire image 315 // Finished decoding the entire image
336 return kSuccess; 316 return kSuccess;
337 } 317 }
318
319 SkCodec::Result SkBmpStandardCodec::prepareToDecode(const SkImageInfo& dstInfo,
320 const SkCodec::Options& options, SkPMColor inputColorPtr[], int* inputCo lorCount) {
321 // Create the color table if necessary and prepare the stream for decode
322 // Note that if it is non-NULL, inputColorCount will be modified
323 if (!this->createColorTable(dstInfo.alphaType(), inputColorCount)) {
324 SkCodecPrintf("Error: could not create color table.\n");
325 return SkCodec::kInvalidInput;
326 }
327
328 // Copy the color table to the client if necessary
329 copy_color_table(dstInfo, this->fColorTable, inputColorPtr, inputColorCount) ;
330
331 // Initialize a swizzler if necessary
332 if (!this->initializeSwizzler(dstInfo, options)) {
333 SkCodecPrintf("Error: cannot initialize swizzler.\n");
334 return SkCodec::kInvalidConversion;
335 }
336 return SkCodec::kSuccess;
337 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698