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/codec/SkCodec_libbmp.cpp

Issue 1032093004: Use a wrapper for SkDebugf in SkCodec. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years, 9 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
« no previous file with comments | « src/codec/SkCodec_libbmp.h ('k') | src/codec/SkCodec_libico.cpp » ('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 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 "SkCodec_libbmp.h" 8 #include "SkCodec_libbmp.h"
9 #include "SkCodecPriv.h" 9 #include "SkCodecPriv.h"
10 #include "SkColorPriv.h" 10 #include "SkColorPriv.h"
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 // The size of the second (info) header in bytes 132 // The size of the second (info) header in bytes
133 uint32_t infoBytes; 133 uint32_t infoBytes;
134 134
135 // Bmps embedded in Icos skip the first Bmp header 135 // Bmps embedded in Icos skip the first Bmp header
136 if (!isIco) { 136 if (!isIco) {
137 // Read the first header and the size of the second header 137 // Read the first header and the size of the second header
138 SkAutoTDeleteArray<uint8_t> hBuffer( 138 SkAutoTDeleteArray<uint8_t> hBuffer(
139 SkNEW_ARRAY(uint8_t, kBmpHeaderBytesPlusFour)); 139 SkNEW_ARRAY(uint8_t, kBmpHeaderBytesPlusFour));
140 if (stream->read(hBuffer.get(), kBmpHeaderBytesPlusFour) != 140 if (stream->read(hBuffer.get(), kBmpHeaderBytesPlusFour) !=
141 kBmpHeaderBytesPlusFour) { 141 kBmpHeaderBytesPlusFour) {
142 SkDebugf("Error: unable to read first bitmap header.\n"); 142 SkCodecPrintf("Error: unable to read first bitmap header.\n");
143 return NULL; 143 return NULL;
144 } 144 }
145 145
146 totalBytes = get_int(hBuffer.get(), 2); 146 totalBytes = get_int(hBuffer.get(), 2);
147 offset = get_int(hBuffer.get(), 10); 147 offset = get_int(hBuffer.get(), 10);
148 if (offset < kBmpHeaderBytes + kBmpOS2V1Bytes) { 148 if (offset < kBmpHeaderBytes + kBmpOS2V1Bytes) {
149 SkDebugf("Error: invalid starting location for pixel data\n"); 149 SkCodecPrintf("Error: invalid starting location for pixel data\n");
150 return NULL; 150 return NULL;
151 } 151 }
152 152
153 // The size of the second (info) header in bytes 153 // The size of the second (info) header in bytes
154 // The size is the first field of the second header, so we have already 154 // The size is the first field of the second header, so we have already
155 // read the first four infoBytes. 155 // read the first four infoBytes.
156 infoBytes = get_int(hBuffer.get(), 14); 156 infoBytes = get_int(hBuffer.get(), 14);
157 if (infoBytes < kBmpOS2V1Bytes) { 157 if (infoBytes < kBmpOS2V1Bytes) {
158 SkDebugf("Error: invalid second header size.\n"); 158 SkCodecPrintf("Error: invalid second header size.\n");
159 return NULL; 159 return NULL;
160 } 160 }
161 } else { 161 } else {
162 // This value is only used by RLE compression. Bmp in Ico files do not 162 // This value is only used by RLE compression. Bmp in Ico files do not
163 // use RLE. If the compression field is incorrectly signaled as RLE, 163 // use RLE. If the compression field is incorrectly signaled as RLE,
164 // we will catch this and signal an error below. 164 // we will catch this and signal an error below.
165 totalBytes = 0; 165 totalBytes = 0;
166 166
167 // Bmps in Ico cannot specify an offset. We will always assume that 167 // Bmps in Ico cannot specify an offset. We will always assume that
168 // pixel data begins immediately after the color table. This value 168 // pixel data begins immediately after the color table. This value
169 // will be corrected below. 169 // will be corrected below.
170 offset = 0; 170 offset = 0;
171 171
172 // Read the size of the second header 172 // Read the size of the second header
173 SkAutoTDeleteArray<uint8_t> hBuffer( 173 SkAutoTDeleteArray<uint8_t> hBuffer(
174 SkNEW_ARRAY(uint8_t, 4)); 174 SkNEW_ARRAY(uint8_t, 4));
175 if (stream->read(hBuffer.get(), 4) != 4) { 175 if (stream->read(hBuffer.get(), 4) != 4) {
176 SkDebugf("Error: unable to read size of second bitmap header.\n"); 176 SkCodecPrintf("Error: unable to read size of second bitmap header.\n ");
177 return NULL; 177 return NULL;
178 } 178 }
179 infoBytes = get_int(hBuffer.get(), 0); 179 infoBytes = get_int(hBuffer.get(), 0);
180 if (infoBytes < kBmpOS2V1Bytes) { 180 if (infoBytes < kBmpOS2V1Bytes) {
181 SkDebugf("Error: invalid second header size.\n"); 181 SkCodecPrintf("Error: invalid second header size.\n");
182 return NULL; 182 return NULL;
183 } 183 }
184 } 184 }
185 185
186 // We already read the first four bytes of the info header to get the size 186 // We already read the first four bytes of the info header to get the size
187 const uint32_t infoBytesRemaining = infoBytes - 4; 187 const uint32_t infoBytesRemaining = infoBytes - 4;
188 188
189 // Read the second header 189 // Read the second header
190 SkAutoTDeleteArray<uint8_t> iBuffer( 190 SkAutoTDeleteArray<uint8_t> iBuffer(
191 SkNEW_ARRAY(uint8_t, infoBytesRemaining)); 191 SkNEW_ARRAY(uint8_t, infoBytesRemaining));
192 if (stream->read(iBuffer.get(), infoBytesRemaining) != infoBytesRemaining) { 192 if (stream->read(iBuffer.get(), infoBytesRemaining) != infoBytesRemaining) {
193 SkDebugf("Error: unable to read second bitmap header.\n"); 193 SkCodecPrintf("Error: unable to read second bitmap header.\n");
194 return NULL; 194 return NULL;
195 } 195 }
196 196
197 // The number of bits used per pixel in the pixel data 197 // The number of bits used per pixel in the pixel data
198 uint16_t bitsPerPixel; 198 uint16_t bitsPerPixel;
199 199
200 // The compression method for the pixel data 200 // The compression method for the pixel data
201 uint32_t compression = kNone_BitmapCompressionMethod; 201 uint32_t compression = kNone_BitmapCompressionMethod;
202 202
203 // Number of colors in the color table, defaults to 0 or max (see below) 203 // Number of colors in the color table, defaults to 0 or max (see below)
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
241 case 60: 241 case 60:
242 case kBmpOS2V2Bytes: 242 case kBmpOS2V2Bytes:
243 headerType = kOS2VX_BitmapHeaderType; 243 headerType = kOS2VX_BitmapHeaderType;
244 break; 244 break;
245 default: 245 default:
246 // We do not signal an error here because there is the 246 // We do not signal an error here because there is the
247 // possibility of new or undocumented bmp header types. Most 247 // possibility of new or undocumented bmp header types. Most
248 // of the newer versions of bmp headers are similar to and 248 // of the newer versions of bmp headers are similar to and
249 // build off of the older versions, so we may still be able to 249 // build off of the older versions, so we may still be able to
250 // decode the bmp. 250 // decode the bmp.
251 SkDebugf("Warning: unknown bmp header format.\n"); 251 SkCodecPrintf("Warning: unknown bmp header format.\n");
252 headerType = kUnknown_BitmapHeaderType; 252 headerType = kUnknown_BitmapHeaderType;
253 break; 253 break;
254 } 254 }
255 // We check the size of the header before entering the if statement. 255 // We check the size of the header before entering the if statement.
256 // We should not reach this point unless the size is large enough for 256 // We should not reach this point unless the size is large enough for
257 // these required fields. 257 // these required fields.
258 SkASSERT(infoBytesRemaining >= 12); 258 SkASSERT(infoBytesRemaining >= 12);
259 width = get_int(iBuffer.get(), 0); 259 width = get_int(iBuffer.get(), 0);
260 height = get_int(iBuffer.get(), 4); 260 height = get_int(iBuffer.get(), 4);
261 bitsPerPixel = get_short(iBuffer.get(), 10); 261 bitsPerPixel = get_short(iBuffer.get(), 10);
(...skipping 12 matching lines...) Expand all
274 bytesPerColor = 4; 274 bytesPerColor = 4;
275 } else if (infoBytes >= kBmpOS2V1Bytes) { 275 } else if (infoBytes >= kBmpOS2V1Bytes) {
276 // The OS2V1 is treated separately because it has a unique format 276 // The OS2V1 is treated separately because it has a unique format
277 headerType = kOS2V1_BitmapHeaderType; 277 headerType = kOS2V1_BitmapHeaderType;
278 width = (int) get_short(iBuffer.get(), 0); 278 width = (int) get_short(iBuffer.get(), 0);
279 height = (int) get_short(iBuffer.get(), 2); 279 height = (int) get_short(iBuffer.get(), 2);
280 bitsPerPixel = get_short(iBuffer.get(), 6); 280 bitsPerPixel = get_short(iBuffer.get(), 6);
281 bytesPerColor = 3; 281 bytesPerColor = 3;
282 } else { 282 } else {
283 // There are no valid bmp headers 283 // There are no valid bmp headers
284 SkDebugf("Error: second bitmap header size is invalid.\n"); 284 SkCodecPrintf("Error: second bitmap header size is invalid.\n");
285 return NULL; 285 return NULL;
286 } 286 }
287 287
288 // Check for valid dimensions from header 288 // Check for valid dimensions from header
289 RowOrder rowOrder = kBottomUp_RowOrder; 289 RowOrder rowOrder = kBottomUp_RowOrder;
290 if (height < 0) { 290 if (height < 0) {
291 height = -height; 291 height = -height;
292 rowOrder = kTopDown_RowOrder; 292 rowOrder = kTopDown_RowOrder;
293 } 293 }
294 // The height field for bmp in ico is double the actual height because they 294 // The height field for bmp in ico is double the actual height because they
295 // contain an XOR mask followed by an AND mask 295 // contain an XOR mask followed by an AND mask
296 if (isIco) { 296 if (isIco) {
297 height /= 2; 297 height /= 2;
298 } 298 }
299 static const int kBmpMaxDim = 1 << 16; 299 static const int kBmpMaxDim = 1 << 16;
300 if (width < 0 || width >= kBmpMaxDim || height >= kBmpMaxDim) { 300 if (width < 0 || width >= kBmpMaxDim || height >= kBmpMaxDim) {
301 // TODO: Decide if we want to support really large bmps. 301 // TODO: Decide if we want to support really large bmps.
302 SkDebugf("Error: invalid bitmap dimensions.\n"); 302 SkCodecPrintf("Error: invalid bitmap dimensions.\n");
303 return NULL; 303 return NULL;
304 } 304 }
305 305
306 // Create mask struct 306 // Create mask struct
307 SkMasks::InputMasks inputMasks; 307 SkMasks::InputMasks inputMasks;
308 memset(&inputMasks, 0, sizeof(SkMasks::InputMasks)); 308 memset(&inputMasks, 0, sizeof(SkMasks::InputMasks));
309 309
310 // Determine the input compression format and set bit masks if necessary 310 // Determine the input compression format and set bit masks if necessary
311 uint32_t maskBytes = 0; 311 uint32_t maskBytes = 0;
312 BitmapInputFormat inputFormat = kUnknown_BitmapInputFormat; 312 BitmapInputFormat inputFormat = kUnknown_BitmapInputFormat;
313 switch (compression) { 313 switch (compression) {
314 case kNone_BitmapCompressionMethod: 314 case kNone_BitmapCompressionMethod:
315 inputFormat = kStandard_BitmapInputFormat; 315 inputFormat = kStandard_BitmapInputFormat;
316 break; 316 break;
317 case k8BitRLE_BitmapCompressionMethod: 317 case k8BitRLE_BitmapCompressionMethod:
318 if (bitsPerPixel != 8) { 318 if (bitsPerPixel != 8) {
319 SkDebugf("Warning: correcting invalid bitmap format.\n"); 319 SkCodecPrintf("Warning: correcting invalid bitmap format.\n");
320 bitsPerPixel = 8; 320 bitsPerPixel = 8;
321 } 321 }
322 inputFormat = kRLE_BitmapInputFormat; 322 inputFormat = kRLE_BitmapInputFormat;
323 break; 323 break;
324 case k4BitRLE_BitmapCompressionMethod: 324 case k4BitRLE_BitmapCompressionMethod:
325 if (bitsPerPixel != 4) { 325 if (bitsPerPixel != 4) {
326 SkDebugf("Warning: correcting invalid bitmap format.\n"); 326 SkCodecPrintf("Warning: correcting invalid bitmap format.\n");
327 bitsPerPixel = 4; 327 bitsPerPixel = 4;
328 } 328 }
329 inputFormat = kRLE_BitmapInputFormat; 329 inputFormat = kRLE_BitmapInputFormat;
330 break; 330 break;
331 case kAlphaBitMasks_BitmapCompressionMethod: 331 case kAlphaBitMasks_BitmapCompressionMethod:
332 case kBitMasks_BitmapCompressionMethod: 332 case kBitMasks_BitmapCompressionMethod:
333 // Load the masks 333 // Load the masks
334 inputFormat = kBitMask_BitmapInputFormat; 334 inputFormat = kBitMask_BitmapInputFormat;
335 switch (headerType) { 335 switch (headerType) {
336 case kInfoV1_BitmapHeaderType: { 336 case kInfoV1_BitmapHeaderType: {
337 // The V1 header stores the bit masks after the header 337 // The V1 header stores the bit masks after the header
338 SkAutoTDeleteArray<uint8_t> mBuffer( 338 SkAutoTDeleteArray<uint8_t> mBuffer(
339 SkNEW_ARRAY(uint8_t, kBmpMaskBytes)); 339 SkNEW_ARRAY(uint8_t, kBmpMaskBytes));
340 if (stream->read(mBuffer.get(), kBmpMaskBytes) != 340 if (stream->read(mBuffer.get(), kBmpMaskBytes) !=
341 kBmpMaskBytes) { 341 kBmpMaskBytes) {
342 SkDebugf("Error: unable to read bit inputMasks.\n"); 342 SkCodecPrintf("Error: unable to read bit inputMasks.\n") ;
343 return NULL; 343 return NULL;
344 } 344 }
345 maskBytes = kBmpMaskBytes; 345 maskBytes = kBmpMaskBytes;
346 inputMasks.red = get_int(mBuffer.get(), 0); 346 inputMasks.red = get_int(mBuffer.get(), 0);
347 inputMasks.green = get_int(mBuffer.get(), 4); 347 inputMasks.green = get_int(mBuffer.get(), 4);
348 inputMasks.blue = get_int(mBuffer.get(), 8); 348 inputMasks.blue = get_int(mBuffer.get(), 8);
349 break; 349 break;
350 } 350 }
351 case kInfoV2_BitmapHeaderType: 351 case kInfoV2_BitmapHeaderType:
352 case kInfoV3_BitmapHeaderType: 352 case kInfoV3_BitmapHeaderType:
353 case kInfoV4_BitmapHeaderType: 353 case kInfoV4_BitmapHeaderType:
354 case kInfoV5_BitmapHeaderType: 354 case kInfoV5_BitmapHeaderType:
355 // Header types are matched based on size. If the header 355 // Header types are matched based on size. If the header
356 // is V2+, we are guaranteed to be able to read at least 356 // is V2+, we are guaranteed to be able to read at least
357 // this size. 357 // this size.
358 SkASSERT(infoBytesRemaining >= 48); 358 SkASSERT(infoBytesRemaining >= 48);
359 inputMasks.red = get_int(iBuffer.get(), 36); 359 inputMasks.red = get_int(iBuffer.get(), 36);
360 inputMasks.green = get_int(iBuffer.get(), 40); 360 inputMasks.green = get_int(iBuffer.get(), 40);
361 inputMasks.blue = get_int(iBuffer.get(), 44); 361 inputMasks.blue = get_int(iBuffer.get(), 44);
362 break; 362 break;
363 case kOS2VX_BitmapHeaderType: 363 case kOS2VX_BitmapHeaderType:
364 // TODO: Decide if we intend to support this. 364 // TODO: Decide if we intend to support this.
365 // It is unsupported in the previous version and 365 // It is unsupported in the previous version and
366 // in chromium. I have not come across a test case 366 // in chromium. I have not come across a test case
367 // that uses this format. 367 // that uses this format.
368 SkDebugf("Error: huffman format unsupported.\n"); 368 SkCodecPrintf("Error: huffman format unsupported.\n");
369 return NULL; 369 return NULL;
370 default: 370 default:
371 SkDebugf("Error: invalid bmp bit masks header.\n"); 371 SkCodecPrintf("Error: invalid bmp bit masks header.\n");
372 return NULL; 372 return NULL;
373 } 373 }
374 break; 374 break;
375 case kJpeg_BitmapCompressionMethod: 375 case kJpeg_BitmapCompressionMethod:
376 if (24 == bitsPerPixel) { 376 if (24 == bitsPerPixel) {
377 inputFormat = kRLE_BitmapInputFormat; 377 inputFormat = kRLE_BitmapInputFormat;
378 break; 378 break;
379 } 379 }
380 // Fall through 380 // Fall through
381 case kPng_BitmapCompressionMethod: 381 case kPng_BitmapCompressionMethod:
382 // TODO: Decide if we intend to support this. 382 // TODO: Decide if we intend to support this.
383 // It is unsupported in the previous version and 383 // It is unsupported in the previous version and
384 // in chromium. I think it is used mostly for printers. 384 // in chromium. I think it is used mostly for printers.
385 SkDebugf("Error: compression format not supported.\n"); 385 SkCodecPrintf("Error: compression format not supported.\n");
386 return NULL; 386 return NULL;
387 case kCMYK_BitmapCompressionMethod: 387 case kCMYK_BitmapCompressionMethod:
388 case kCMYK8BitRLE_BitmapCompressionMethod: 388 case kCMYK8BitRLE_BitmapCompressionMethod:
389 case kCMYK4BitRLE_BitmapCompressionMethod: 389 case kCMYK4BitRLE_BitmapCompressionMethod:
390 // TODO: Same as above. 390 // TODO: Same as above.
391 SkDebugf("Error: CMYK not supported for bitmap decoding.\n"); 391 SkCodecPrintf("Error: CMYK not supported for bitmap decoding.\n");
392 return NULL; 392 return NULL;
393 default: 393 default:
394 SkDebugf("Error: invalid format for bitmap decoding.\n"); 394 SkCodecPrintf("Error: invalid format for bitmap decoding.\n");
395 return NULL; 395 return NULL;
396 } 396 }
397 397
398 // Most versions of bmps should be rendered as opaque. Either they do 398 // Most versions of bmps should be rendered as opaque. Either they do
399 // not have an alpha channel, or they expect the alpha channel to be 399 // not have an alpha channel, or they expect the alpha channel to be
400 // ignored. V3+ bmp files introduce an alpha mask and allow the creator 400 // ignored. V3+ bmp files introduce an alpha mask and allow the creator
401 // of the image to use the alpha channels. However, many of these images 401 // of the image to use the alpha channels. However, many of these images
402 // leave the alpha channel blank and expect to be rendered as opaque. This 402 // leave the alpha channel blank and expect to be rendered as opaque. This
403 // is the case for almost all V3 images, so we render these as opaque. For 403 // is the case for almost all V3 images, so we render these as opaque. For
404 // V4+, we will use the alpha channel, and fix the image later if it turns 404 // V4+, we will use the alpha channel, and fix the image later if it turns
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
439 } 439 }
440 break; 440 break;
441 case 1: 441 case 1:
442 case 2: 442 case 2:
443 case 4: 443 case 4:
444 case 8: 444 case 8:
445 case 24: 445 case 24:
446 case 32: 446 case 32:
447 break; 447 break;
448 default: 448 default:
449 SkDebugf("Error: invalid input value for bits per pixel.\n"); 449 SkCodecPrintf("Error: invalid input value for bits per pixel.\n");
450 return NULL; 450 return NULL;
451 } 451 }
452 452
453 // Check that input bit masks are valid and create the masks object 453 // Check that input bit masks are valid and create the masks object
454 SkAutoTDelete<SkMasks> 454 SkAutoTDelete<SkMasks>
455 masks(SkMasks::CreateMasks(inputMasks, bitsPerPixel)); 455 masks(SkMasks::CreateMasks(inputMasks, bitsPerPixel));
456 if (NULL == masks) { 456 if (NULL == masks) {
457 SkDebugf("Error: invalid input masks.\n"); 457 SkCodecPrintf("Error: invalid input masks.\n");
458 return NULL; 458 return NULL;
459 } 459 }
460 460
461 // Check for a valid number of total bytes when in RLE mode 461 // Check for a valid number of total bytes when in RLE mode
462 if (totalBytes <= offset && kRLE_BitmapInputFormat == inputFormat) { 462 if (totalBytes <= offset && kRLE_BitmapInputFormat == inputFormat) {
463 SkDebugf("Error: RLE requires valid input size.\n"); 463 SkCodecPrintf("Error: RLE requires valid input size.\n");
464 return NULL; 464 return NULL;
465 } 465 }
466 const size_t RLEBytes = totalBytes - offset; 466 const size_t RLEBytes = totalBytes - offset;
467 467
468 // Calculate the number of bytes read so far 468 // Calculate the number of bytes read so far
469 const uint32_t bytesRead = kBmpHeaderBytes + infoBytes + maskBytes; 469 const uint32_t bytesRead = kBmpHeaderBytes + infoBytes + maskBytes;
470 if (!isIco && offset < bytesRead) { 470 if (!isIco && offset < bytesRead) {
471 SkDebugf("Error: pixel data offset less than header size.\n"); 471 SkCodecPrintf("Error: pixel data offset less than header size.\n");
472 return NULL; 472 return NULL;
473 } 473 }
474 474
475 // Return the codec 475 // Return the codec
476 // We will use ImageInfo to store width, height, and alpha type. We will 476 // We will use ImageInfo to store width, height, and alpha type. We will
477 // set color type to kN32_SkColorType because that should be the default 477 // set color type to kN32_SkColorType because that should be the default
478 // output. 478 // output.
479 const SkImageInfo& imageInfo = SkImageInfo::Make(width, height, 479 const SkImageInfo& imageInfo = SkImageInfo::Make(width, height,
480 kN32_SkColorType, alphaType); 480 kN32_SkColorType, alphaType);
481 return SkNEW_ARGS(SkBmpCodec, (imageInfo, stream, bitsPerPixel, 481 return SkNEW_ARGS(SkBmpCodec, (imageInfo, stream, bitsPerPixel,
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
516 */ 516 */
517 SkCodec::Result SkBmpCodec::onGetPixels(const SkImageInfo& dstInfo, 517 SkCodec::Result SkBmpCodec::onGetPixels(const SkImageInfo& dstInfo,
518 void* dst, size_t dstRowBytes, 518 void* dst, size_t dstRowBytes,
519 const Options&, 519 const Options&,
520 SkPMColor*, int*) { 520 SkPMColor*, int*) {
521 // Check for proper input and output formats 521 // Check for proper input and output formats
522 if (!this->rewindIfNeeded()) { 522 if (!this->rewindIfNeeded()) {
523 return kCouldNotRewind; 523 return kCouldNotRewind;
524 } 524 }
525 if (dstInfo.dimensions() != this->getInfo().dimensions()) { 525 if (dstInfo.dimensions() != this->getInfo().dimensions()) {
526 SkDebugf("Error: scaling not supported.\n"); 526 SkCodecPrintf("Error: scaling not supported.\n");
527 return kInvalidScale; 527 return kInvalidScale;
528 } 528 }
529 if (!conversion_possible(dstInfo, this->getInfo())) { 529 if (!conversion_possible(dstInfo, this->getInfo())) {
530 SkDebugf("Error: cannot convert input type to output type.\n"); 530 SkCodecPrintf("Error: cannot convert input type to output type.\n");
531 return kInvalidConversion; 531 return kInvalidConversion;
532 } 532 }
533 533
534 // Create the color table if necessary and prepare the stream for decode 534 // Create the color table if necessary and prepare the stream for decode
535 if (!createColorTable(dstInfo.alphaType())) { 535 if (!createColorTable(dstInfo.alphaType())) {
536 SkDebugf("Error: could not create color table.\n"); 536 SkCodecPrintf("Error: could not create color table.\n");
537 return kInvalidInput; 537 return kInvalidInput;
538 } 538 }
539 539
540 // Perform the decode 540 // Perform the decode
541 switch (fInputFormat) { 541 switch (fInputFormat) {
542 case kBitMask_BitmapInputFormat: 542 case kBitMask_BitmapInputFormat:
543 return decodeMask(dstInfo, dst, dstRowBytes); 543 return decodeMask(dstInfo, dst, dstRowBytes);
544 case kRLE_BitmapInputFormat: 544 case kRLE_BitmapInputFormat:
545 return decodeRLE(dstInfo, dst, dstRowBytes); 545 return decodeRLE(dstInfo, dst, dstRowBytes);
546 case kStandard_BitmapInputFormat: 546 case kStandard_BitmapInputFormat:
(...skipping 19 matching lines...) Expand all
566 // Also set fNumColors to maxColors when it is too large 566 // Also set fNumColors to maxColors when it is too large
567 maxColors = 1 << fBitsPerPixel; 567 maxColors = 1 << fBitsPerPixel;
568 if (fNumColors == 0 || fNumColors >= maxColors) { 568 if (fNumColors == 0 || fNumColors >= maxColors) {
569 fNumColors = maxColors; 569 fNumColors = maxColors;
570 } 570 }
571 571
572 // Read the color table from the stream 572 // Read the color table from the stream
573 colorBytes = fNumColors * fBytesPerColor; 573 colorBytes = fNumColors * fBytesPerColor;
574 SkAutoTDeleteArray<uint8_t> cBuffer(SkNEW_ARRAY(uint8_t, colorBytes)); 574 SkAutoTDeleteArray<uint8_t> cBuffer(SkNEW_ARRAY(uint8_t, colorBytes));
575 if (stream()->read(cBuffer.get(), colorBytes) != colorBytes) { 575 if (stream()->read(cBuffer.get(), colorBytes) != colorBytes) {
576 SkDebugf("Error: unable to read color table.\n"); 576 SkCodecPrintf("Error: unable to read color table.\n");
577 return false; 577 return false;
578 } 578 }
579 579
580 // Choose the proper packing function 580 // Choose the proper packing function
581 SkPMColor (*packARGB) (uint32_t, uint32_t, uint32_t, uint32_t); 581 SkPMColor (*packARGB) (uint32_t, uint32_t, uint32_t, uint32_t);
582 switch (alphaType) { 582 switch (alphaType) {
583 case kOpaque_SkAlphaType: 583 case kOpaque_SkAlphaType:
584 case kUnpremul_SkAlphaType: 584 case kUnpremul_SkAlphaType:
585 packARGB = &SkPackARGB32NoCheck; 585 packARGB = &SkPackARGB32NoCheck;
586 break; 586 break;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
619 // Bmp-in-Ico files do not use an offset to indicate where the pixel data 619 // Bmp-in-Ico files do not use an offset to indicate where the pixel data
620 // begins. Pixel data always begins immediately after the color table. 620 // begins. Pixel data always begins immediately after the color table.
621 if (!fIsIco) { 621 if (!fIsIco) {
622 // Check that we have not read past the pixel array offset 622 // Check that we have not read past the pixel array offset
623 if(fOffset < colorBytes) { 623 if(fOffset < colorBytes) {
624 // This may occur on OS 2.1 and other old versions where the color 624 // This may occur on OS 2.1 and other old versions where the color
625 // table defaults to max size, and the bmp tries to use a smaller 625 // table defaults to max size, and the bmp tries to use a smaller
626 // color table. This is invalid, and our decision is to indicate 626 // color table. This is invalid, and our decision is to indicate
627 // an error, rather than try to guess the intended size of the 627 // an error, rather than try to guess the intended size of the
628 // color table. 628 // color table.
629 SkDebugf("Error: pixel data offset less than color table size.\n"); 629 SkCodecPrintf("Error: pixel data offset less than color table size.\ n");
630 return false; 630 return false;
631 } 631 }
632 632
633 // After reading the color table, skip to the start of the pixel array 633 // After reading the color table, skip to the start of the pixel array
634 if (stream()->skip(fOffset - colorBytes) != fOffset - colorBytes) { 634 if (stream()->skip(fOffset - colorBytes) != fOffset - colorBytes) {
635 SkDebugf("Error: unable to skip to image data.\n"); 635 SkCodecPrintf("Error: unable to skip to image data.\n");
636 return false; 636 return false;
637 } 637 }
638 } 638 }
639 639
640 // Set the color table and return true on success 640 // Set the color table and return true on success
641 fColorTable.reset(SkNEW_ARGS(SkColorTable, (colorTable, maxColors))); 641 fColorTable.reset(SkNEW_ARGS(SkColorTable, (colorTable, maxColors)));
642 return true; 642 return true;
643 } 643 }
644 644
645 /* 645 /*
(...skipping 16 matching lines...) Expand all
662 // Create the swizzler 662 // Create the swizzler
663 SkAutoTDelete<SkMaskSwizzler> maskSwizzler( 663 SkAutoTDelete<SkMaskSwizzler> maskSwizzler(
664 SkMaskSwizzler::CreateMaskSwizzler(dstInfo, dst, dstRowBytes, 664 SkMaskSwizzler::CreateMaskSwizzler(dstInfo, dst, dstRowBytes,
665 fMasks, fBitsPerPixel)); 665 fMasks, fBitsPerPixel));
666 666
667 // Iterate over rows of the image 667 // Iterate over rows of the image
668 bool transparent = true; 668 bool transparent = true;
669 for (int y = 0; y < height; y++) { 669 for (int y = 0; y < height; y++) {
670 // Read a row of the input 670 // Read a row of the input
671 if (stream()->read(srcRow, rowBytes) != rowBytes) { 671 if (stream()->read(srcRow, rowBytes) != rowBytes) {
672 SkDebugf("Warning: incomplete input stream.\n"); 672 SkCodecPrintf("Warning: incomplete input stream.\n");
673 return kIncompleteInput; 673 return kIncompleteInput;
674 } 674 }
675 675
676 // Decode the row in destination format 676 // Decode the row in destination format
677 int row = kBottomUp_RowOrder == fRowOrder ? height - 1 - y : y; 677 int row = kBottomUp_RowOrder == fRowOrder ? height - 1 - y : y;
678 SkSwizzler::ResultAlpha r = maskSwizzler->next(srcRow, row); 678 SkSwizzler::ResultAlpha r = maskSwizzler->next(srcRow, row);
679 transparent &= SkSwizzler::IsTransparent(r); 679 transparent &= SkSwizzler::IsTransparent(r);
680 680
681 // Move to the next row 681 // Move to the next row
682 srcRow = SkTAddOffset<uint8_t>(srcRow, rowBytes); 682 srcRow = SkTAddOffset<uint8_t>(srcRow, rowBytes);
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
800 800
801 // Set constant values 801 // Set constant values
802 const int width = dstInfo.width(); 802 const int width = dstInfo.width();
803 const int height = dstInfo.height(); 803 const int height = dstInfo.height();
804 804
805 // Input buffer parameters 805 // Input buffer parameters
806 uint32_t currByte = 0; 806 uint32_t currByte = 0;
807 SkAutoTDeleteArray<uint8_t> buffer(SkNEW_ARRAY(uint8_t, fRLEBytes)); 807 SkAutoTDeleteArray<uint8_t> buffer(SkNEW_ARRAY(uint8_t, fRLEBytes));
808 size_t totalBytes = stream()->read(buffer.get(), fRLEBytes); 808 size_t totalBytes = stream()->read(buffer.get(), fRLEBytes);
809 if (totalBytes < fRLEBytes) { 809 if (totalBytes < fRLEBytes) {
810 SkDebugf("Warning: incomplete RLE file.\n"); 810 SkCodecPrintf("Warning: incomplete RLE file.\n");
811 } else if (totalBytes <= 0) { 811 } else if (totalBytes <= 0) {
812 SkDebugf("Error: could not read RLE image data.\n"); 812 SkCodecPrintf("Error: could not read RLE image data.\n");
813 return kInvalidInput; 813 return kInvalidInput;
814 } 814 }
815 815
816 // Destination parameters 816 // Destination parameters
817 int x = 0; 817 int x = 0;
818 int y = 0; 818 int y = 0;
819 // If the code skips pixels, remaining pixels are transparent or black 819 // If the code skips pixels, remaining pixels are transparent or black
820 // TODO: Skip this if memory was already zeroed. 820 // TODO: Skip this if memory was already zeroed.
821 memset(dst, 0, dstRowBytes * height); 821 memset(dst, 0, dstRowBytes * height);
822 SkPMColor* dstPtr = (SkPMColor*) dst; 822 SkPMColor* dstPtr = (SkPMColor*) dst;
823 823
824 while (true) { 824 while (true) {
825 // Every entry takes at least two bytes 825 // Every entry takes at least two bytes
826 if ((int) totalBytes - currByte < 2) { 826 if ((int) totalBytes - currByte < 2) {
827 SkDebugf("Warning: incomplete RLE input.\n"); 827 SkCodecPrintf("Warning: incomplete RLE input.\n");
828 return kIncompleteInput; 828 return kIncompleteInput;
829 } 829 }
830 830
831 // Read the next two bytes. These bytes have different meanings 831 // Read the next two bytes. These bytes have different meanings
832 // depending on their values. In the first interpretation, the first 832 // depending on their values. In the first interpretation, the first
833 // byte is an escape flag and the second byte indicates what special 833 // byte is an escape flag and the second byte indicates what special
834 // task to perform. 834 // task to perform.
835 const uint8_t flag = buffer.get()[currByte++]; 835 const uint8_t flag = buffer.get()[currByte++];
836 const uint8_t task = buffer.get()[currByte++]; 836 const uint8_t task = buffer.get()[currByte++];
837 837
838 // If we have reached a row that is beyond the image size, and the RLE 838 // If we have reached a row that is beyond the image size, and the RLE
839 // code does not indicate end of file, abort and signal a warning. 839 // code does not indicate end of file, abort and signal a warning.
840 if (y >= height && (flag != RLE_ESCAPE || (task != RLE_EOF))) { 840 if (y >= height && (flag != RLE_ESCAPE || (task != RLE_EOF))) {
841 SkDebugf("Warning: invalid RLE input.\n"); 841 SkCodecPrintf("Warning: invalid RLE input.\n");
842 return kIncompleteInput; 842 return kIncompleteInput;
843 } 843 }
844 844
845 // Perform decoding 845 // Perform decoding
846 if (RLE_ESCAPE == flag) { 846 if (RLE_ESCAPE == flag) {
847 switch (task) { 847 switch (task) {
848 case RLE_EOL: 848 case RLE_EOL:
849 x = 0; 849 x = 0;
850 y++; 850 y++;
851 break; 851 break;
852 case RLE_EOF: 852 case RLE_EOF:
853 return kSuccess; 853 return kSuccess;
854 case RLE_DELTA: { 854 case RLE_DELTA: {
855 // Two bytes are needed to specify delta 855 // Two bytes are needed to specify delta
856 if ((int) totalBytes - currByte < 2) { 856 if ((int) totalBytes - currByte < 2) {
857 SkDebugf("Warning: incomplete RLE input\n"); 857 SkCodecPrintf("Warning: incomplete RLE input\n");
858 return kIncompleteInput; 858 return kIncompleteInput;
859 } 859 }
860 // Modify x and y 860 // Modify x and y
861 const uint8_t dx = buffer.get()[currByte++]; 861 const uint8_t dx = buffer.get()[currByte++];
862 const uint8_t dy = buffer.get()[currByte++]; 862 const uint8_t dy = buffer.get()[currByte++];
863 x += dx; 863 x += dx;
864 y += dy; 864 y += dy;
865 if (x > width || y > height) { 865 if (x > width || y > height) {
866 SkDebugf("Warning: invalid RLE input.\n"); 866 SkCodecPrintf("Warning: invalid RLE input.\n");
867 return kIncompleteInput; 867 return kIncompleteInput;
868 } 868 }
869 break; 869 break;
870 } 870 }
871 default: { 871 default: {
872 // If task does not match any of the above signals, it 872 // If task does not match any of the above signals, it
873 // indicates that we have a sequence of non-RLE pixels. 873 // indicates that we have a sequence of non-RLE pixels.
874 // Furthermore, the value of task is equal to the number 874 // Furthermore, the value of task is equal to the number
875 // of pixels to interpret. 875 // of pixels to interpret.
876 uint8_t numPixels = task; 876 uint8_t numPixels = task;
877 const size_t rowBytes = compute_row_bytes(numPixels, 877 const size_t rowBytes = compute_row_bytes(numPixels,
878 fBitsPerPixel); 878 fBitsPerPixel);
879 // Abort if setting numPixels moves us off the edge of the 879 // Abort if setting numPixels moves us off the edge of the
880 // image. Also abort if there are not enough bytes 880 // image. Also abort if there are not enough bytes
881 // remaining in the stream to set numPixels. 881 // remaining in the stream to set numPixels.
882 if (x + numPixels > width || 882 if (x + numPixels > width ||
883 (int) totalBytes - currByte < SkAlign2(rowBytes)) { 883 (int) totalBytes - currByte < SkAlign2(rowBytes)) {
884 SkDebugf("Warning: invalid RLE input.\n"); 884 SkCodecPrintf("Warning: invalid RLE input.\n");
885 return kIncompleteInput; 885 return kIncompleteInput;
886 } 886 }
887 // Set numPixels number of pixels 887 // Set numPixels number of pixels
888 while (numPixels > 0) { 888 while (numPixels > 0) {
889 switch(fBitsPerPixel) { 889 switch(fBitsPerPixel) {
890 case 4: { 890 case 4: {
891 SkASSERT(currByte < totalBytes); 891 SkASSERT(currByte < totalBytes);
892 uint8_t val = buffer.get()[currByte++]; 892 uint8_t val = buffer.get()[currByte++];
893 setRLEPixel(dstPtr, dstRowBytes, dstInfo, x++, 893 setRLEPixel(dstPtr, dstRowBytes, dstInfo, x++,
894 y, val >> 4); 894 y, val >> 4);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
931 // If the first byte read is not a flag, it indicates the number of 931 // If the first byte read is not a flag, it indicates the number of
932 // pixels to set in RLE mode. 932 // pixels to set in RLE mode.
933 const uint8_t numPixels = flag; 933 const uint8_t numPixels = flag;
934 const int endX = SkTMin<int>(x + numPixels, width); 934 const int endX = SkTMin<int>(x + numPixels, width);
935 935
936 if (24 == fBitsPerPixel) { 936 if (24 == fBitsPerPixel) {
937 // In RLE24, the second byte read is part of the pixel color. 937 // In RLE24, the second byte read is part of the pixel color.
938 // There are two more required bytes to finish encoding the 938 // There are two more required bytes to finish encoding the
939 // color. 939 // color.
940 if ((int) totalBytes - currByte < 2) { 940 if ((int) totalBytes - currByte < 2) {
941 SkDebugf("Warning: incomplete RLE input\n"); 941 SkCodecPrintf("Warning: incomplete RLE input\n");
942 return kIncompleteInput; 942 return kIncompleteInput;
943 } 943 }
944 944
945 // Fill the pixels up to endX with the specified color 945 // Fill the pixels up to endX with the specified color
946 uint8_t blue = task; 946 uint8_t blue = task;
947 uint8_t green = buffer.get()[currByte++]; 947 uint8_t green = buffer.get()[currByte++];
948 uint8_t red = buffer.get()[currByte++]; 948 uint8_t red = buffer.get()[currByte++];
949 while (x < endX) { 949 while (x < endX) {
950 setRLE24Pixel(dstPtr, dstRowBytes, dstInfo, x++, y, red, 950 setRLE24Pixel(dstPtr, dstRowBytes, dstInfo, x++, y, red,
951 green, blue); 951 green, blue);
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
1021 SkImageGenerator::kNo_ZeroInitialized)); 1021 SkImageGenerator::kNo_ZeroInitialized));
1022 1022
1023 // Allocate space for a row buffer and a source for the swizzler 1023 // Allocate space for a row buffer and a source for the swizzler
1024 SkAutoTDeleteArray<uint8_t> srcBuffer(SkNEW_ARRAY(uint8_t, rowBytes)); 1024 SkAutoTDeleteArray<uint8_t> srcBuffer(SkNEW_ARRAY(uint8_t, rowBytes));
1025 1025
1026 // Iterate over rows of the image 1026 // Iterate over rows of the image
1027 // FIXME: bool transparent = true; 1027 // FIXME: bool transparent = true;
1028 for (int y = 0; y < height; y++) { 1028 for (int y = 0; y < height; y++) {
1029 // Read a row of the input 1029 // Read a row of the input
1030 if (stream()->read(srcBuffer.get(), rowBytes) != rowBytes) { 1030 if (stream()->read(srcBuffer.get(), rowBytes) != rowBytes) {
1031 SkDebugf("Warning: incomplete input stream.\n"); 1031 SkCodecPrintf("Warning: incomplete input stream.\n");
1032 return kIncompleteInput; 1032 return kIncompleteInput;
1033 } 1033 }
1034 1034
1035 // Decode the row in destination format 1035 // Decode the row in destination format
1036 uint32_t row; 1036 uint32_t row;
1037 if (kTopDown_RowOrder == fRowOrder) { 1037 if (kTopDown_RowOrder == fRowOrder) {
1038 row = y; 1038 row = y;
1039 } else { 1039 } else {
1040 row = height - 1 - y; 1040 row = height - 1 - y;
1041 } 1041 }
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1073 1073
1074 // Finally, apply the AND mask for bmp-in-ico images 1074 // Finally, apply the AND mask for bmp-in-ico images
1075 if (fIsIco) { 1075 if (fIsIco) {
1076 // The AND mask is always 1 bit per pixel 1076 // The AND mask is always 1 bit per pixel
1077 const size_t rowBytes = SkAlign4(compute_row_bytes(width, 1)); 1077 const size_t rowBytes = SkAlign4(compute_row_bytes(width, 1));
1078 1078
1079 SkPMColor* dstPtr = (SkPMColor*) dst; 1079 SkPMColor* dstPtr = (SkPMColor*) dst;
1080 for (int y = 0; y < height; y++) { 1080 for (int y = 0; y < height; y++) {
1081 // The srcBuffer will at least be large enough 1081 // The srcBuffer will at least be large enough
1082 if (stream()->read(srcBuffer.get(), rowBytes) != rowBytes) { 1082 if (stream()->read(srcBuffer.get(), rowBytes) != rowBytes) {
1083 SkDebugf("Warning: incomplete AND mask for bmp-in-ico.\n"); 1083 SkCodecPrintf("Warning: incomplete AND mask for bmp-in-ico.\n");
1084 return kIncompleteInput; 1084 return kIncompleteInput;
1085 } 1085 }
1086 1086
1087 int row; 1087 int row;
1088 if (kBottomUp_RowOrder == fRowOrder) { 1088 if (kBottomUp_RowOrder == fRowOrder) {
1089 row = height - y - 1; 1089 row = height - y - 1;
1090 } else { 1090 } else {
1091 row = y; 1091 row = y;
1092 } 1092 }
1093 1093
1094 SkPMColor* dstRow = 1094 SkPMColor* dstRow =
1095 SkTAddOffset<SkPMColor>(dstPtr, row * dstRowBytes); 1095 SkTAddOffset<SkPMColor>(dstPtr, row * dstRowBytes);
1096 1096
1097 for (int x = 0; x < width; x++) { 1097 for (int x = 0; x < width; x++) {
1098 int quotient; 1098 int quotient;
1099 int modulus; 1099 int modulus;
1100 SkTDivMod(x, 8, &quotient, &modulus); 1100 SkTDivMod(x, 8, &quotient, &modulus);
1101 uint32_t shift = 7 - modulus; 1101 uint32_t shift = 7 - modulus;
1102 uint32_t alphaBit = 1102 uint32_t alphaBit =
1103 (srcBuffer.get()[quotient] >> shift) & 0x1; 1103 (srcBuffer.get()[quotient] >> shift) & 0x1;
1104 dstRow[x] &= alphaBit - 1; 1104 dstRow[x] &= alphaBit - 1;
1105 } 1105 }
1106 } 1106 }
1107 } 1107 }
1108 1108
1109 // Finished decoding the entire image 1109 // Finished decoding the entire image
1110 return kSuccess; 1110 return kSuccess;
1111 } 1111 }
OLDNEW
« no previous file with comments | « src/codec/SkCodec_libbmp.h ('k') | src/codec/SkCodec_libico.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698