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

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

Issue 1472933002: Make SkAndroidCodec support ico (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Response to comments Created 5 years 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/SkBmpStandardCodec.h ('k') | src/codec/SkCodec_libico.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 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"
11 #include "SkStream.h" 11 #include "SkStream.h"
12 12
13 /* 13 /*
14 * Creates an instance of the decoder 14 * Creates an instance of the decoder
15 * Called only by NewFromStream 15 * Called only by NewFromStream
16 */ 16 */
17 SkBmpStandardCodec::SkBmpStandardCodec(const SkImageInfo& info, SkStream* stream , 17 SkBmpStandardCodec::SkBmpStandardCodec(const SkImageInfo& info, SkStream* stream ,
18 uint16_t bitsPerPixel, uint32_t numColors , 18 uint16_t bitsPerPixel, uint32_t numColors ,
19 uint32_t bytesPerColor, uint32_t offset, 19 uint32_t bytesPerColor, uint32_t offset,
20 SkCodec::SkScanlineOrder rowOrder, bool i nIco) 20 SkCodec::SkScanlineOrder rowOrder, bool i nIco)
21 : INHERITED(info, stream, bitsPerPixel, rowOrder) 21 : INHERITED(info, stream, bitsPerPixel, rowOrder)
22 , fColorTable(nullptr) 22 , fColorTable(nullptr)
23 , fNumColors(this->computeNumColors(numColors)) 23 , fNumColors(this->computeNumColors(numColors))
24 , fBytesPerColor(bytesPerColor) 24 , fBytesPerColor(bytesPerColor)
25 , fOffset(offset) 25 , fOffset(offset)
26 , fSwizzler(nullptr) 26 , fSwizzler(nullptr)
27 , fSrcRowBytes(SkAlign4(compute_row_bytes(this->getInfo().width(), this->bit sPerPixel()))) 27 , fSrcRowBytes(SkAlign4(compute_row_bytes(this->getInfo().width(), this->bit sPerPixel())))
28 , fSrcBuffer(new uint8_t [fSrcRowBytes]) 28 , fSrcBuffer(new uint8_t [fSrcRowBytes])
29 , fInIco(inIco) 29 , fInIco(inIco)
30 , fAndMaskRowBytes(fInIco ? SkAlign4(compute_row_bytes(this->getInfo().width (), 1)) : 0)
30 {} 31 {}
31 32
32 /* 33 /*
33 * Initiates the bitmap decode 34 * Initiates the bitmap decode
34 */ 35 */
35 SkCodec::Result SkBmpStandardCodec::onGetPixels(const SkImageInfo& dstInfo, 36 SkCodec::Result SkBmpStandardCodec::onGetPixels(const SkImageInfo& dstInfo,
36 void* dst, size_t dstRowBytes, 37 void* dst, size_t dstRowBytes,
37 const Options& opts, 38 const Options& opts,
38 SkPMColor* inputColorPtr, 39 SkPMColor* inputColorPtr,
39 int* inputColorCount, 40 int* inputColorCount,
(...skipping 13 matching lines...) Expand all
53 54
54 Result result = this->prepareToDecode(dstInfo, opts, inputColorPtr, inputCol orCount); 55 Result result = this->prepareToDecode(dstInfo, opts, inputColorPtr, inputCol orCount);
55 if (kSuccess != result) { 56 if (kSuccess != result) {
56 return result; 57 return result;
57 } 58 }
58 int rows = this->decodeRows(dstInfo, dst, dstRowBytes, opts); 59 int rows = this->decodeRows(dstInfo, dst, dstRowBytes, opts);
59 if (rows != dstInfo.height()) { 60 if (rows != dstInfo.height()) {
60 *rowsDecoded = rows; 61 *rowsDecoded = rows;
61 return kIncompleteInput; 62 return kIncompleteInput;
62 } 63 }
63 if (fInIco) {
64 return this->decodeIcoMask(dstInfo, dst, dstRowBytes);
65 }
66 return kSuccess; 64 return kSuccess;
67 } 65 }
68 66
69 /* 67 /*
70 * Process the color table for the bmp input 68 * Process the color table for the bmp input
71 */ 69 */
72 bool SkBmpStandardCodec::createColorTable(SkAlphaType alphaType, int* numColors ) { 70 bool SkBmpStandardCodec::createColorTable(SkAlphaType alphaType, int* numColors ) {
73 // Allocate memory for color table 71 // Allocate memory for color table
74 uint32_t colorBytes = 0; 72 uint32_t colorBytes = 0;
75 SkPMColor colorTable[256]; 73 SkPMColor colorTable[256];
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 if (!this->initializeSwizzler(dstInfo, options)) { 218 if (!this->initializeSwizzler(dstInfo, options)) {
221 SkCodecPrintf("Error: cannot initialize swizzler.\n"); 219 SkCodecPrintf("Error: cannot initialize swizzler.\n");
222 return SkCodec::kInvalidConversion; 220 return SkCodec::kInvalidConversion;
223 } 221 }
224 return SkCodec::kSuccess; 222 return SkCodec::kSuccess;
225 } 223 }
226 224
227 /* 225 /*
228 * Performs the bitmap decoding for standard input format 226 * Performs the bitmap decoding for standard input format
229 */ 227 */
230 int SkBmpStandardCodec::decodeRows(const SkImageInfo& dstInfo, 228 int SkBmpStandardCodec::decodeRows(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes,
231 void* dst, size_t dstRowBytes, 229 const Options& opts) {
232 const Options& opts) {
233 // Iterate over rows of the image 230 // Iterate over rows of the image
234 const int height = dstInfo.height(); 231 const int height = dstInfo.height();
235 for (int y = 0; y < height; y++) { 232 for (int y = 0; y < height; y++) {
236 // Read a row of the input 233 // Read a row of the input
237 if (this->stream()->read(fSrcBuffer.get(), fSrcRowBytes) != fSrcRowBytes ) { 234 if (this->stream()->read(fSrcBuffer.get(), fSrcRowBytes) != fSrcRowBytes ) {
238 SkCodecPrintf("Warning: incomplete input stream.\n"); 235 SkCodecPrintf("Warning: incomplete input stream.\n");
239 return y; 236 return y;
240 } 237 }
241 238
242 // Decode the row in destination format 239 // Decode the row in destination format
243 uint32_t row = this->getDstRow(y, dstInfo.height()); 240 uint32_t row = this->getDstRow(y, dstInfo.height());
244 241
245 void* dstRow = SkTAddOffset<void>(dst, row * dstRowBytes); 242 void* dstRow = SkTAddOffset<void>(dst, row * dstRowBytes);
246 fSwizzler->swizzle(dstRow, fSrcBuffer.get()); 243 fSwizzler->swizzle(dstRow, fSrcBuffer.get());
247 } 244 }
248 245
249 // Finished decoding the entire image 246 if (fInIco) {
247 const int startScanline = this->currScanline();
248 if (startScanline < 0) {
249 // We are not performing a scanline decode.
250 // Just decode the entire ICO mask and return.
251 decodeIcoMask(this->stream(), dstInfo, dst, dstRowBytes);
252 return height;
253 }
254
255 // In order to perform a scanline ICO decode, we must be able
256 // to skip ahead in the stream in order to apply the AND mask
257 // to the requested scanlines.
258 // We will do this by taking advantage of the fact that
259 // SkIcoCodec always uses a SkMemoryStream as its underlying
260 // representation of the stream.
261 const void* memoryBase = this->stream()->getMemoryBase();
262 SkASSERT(nullptr != memoryBase);
263 SkASSERT(this->stream()->hasLength());
264 SkASSERT(this->stream()->hasPosition());
265
266 const size_t length = this->stream()->getLength();
267 const size_t currPosition = this->stream()->getPosition();
268
269 // Calculate how many bytes we must skip to reach the AND mask.
270 const int remainingScanlines = this->getInfo().height() - startScanline - height;
271 const size_t bytesToSkip = remainingScanlines * fSrcRowBytes +
272 startScanline * fAndMaskRowBytes;
273 const size_t subStreamStartPosition = currPosition + bytesToSkip;
274 if (subStreamStartPosition >= length) {
275 // FIXME: How can we indicate that this decode was actually incomple te?
276 return height;
277 }
278
279 // Create a subStream to pass to decodeIcoMask(). It is useful to encap sulate
280 // the memory base into a stream in order to safely handle incomplete im ages
281 // without reading out of bounds memory.
282 const void* subStreamMemoryBase = SkTAddOffset<const void>(memoryBase,
283 subStreamStartPosition);
284 const size_t subStreamLength = length - subStreamStartPosition;
285 // This call does not transfer ownership of the subStreamMemoryBase.
286 SkMemoryStream subStream(subStreamMemoryBase, subStreamLength, false);
287
288 // FIXME: If decodeIcoMask does not succeed, is there a way that we can
289 // indicate the decode was incomplete?
290 decodeIcoMask(&subStream, dstInfo, dst, dstRowBytes);
291 }
292
250 return height; 293 return height;
251 } 294 }
252 295
253 // TODO (msarett): This function will need to be modified in order to perform ro w by row decodes 296 void SkBmpStandardCodec::decodeIcoMask(SkStream* stream, const SkImageInfo& dstI nfo,
254 // when the Ico scanline decoder is implemented.
255 SkCodec::Result SkBmpStandardCodec::decodeIcoMask(const SkImageInfo& dstInfo,
256 void* dst, size_t dstRowBytes) { 297 void* dst, size_t dstRowBytes) {
257 // BMP in ICO have transparency, so this cannot be 565, and this mask 298 // BMP in ICO have transparency, so this cannot be 565, and this mask
258 // prevents us from using kIndex8. The below code depends on the output 299 // prevents us from using kIndex8. The below code depends on the output
259 // being an SkPMColor. 300 // being an SkPMColor.
260 SkASSERT(dstInfo.colorType() == kN32_SkColorType); 301 SkASSERT(dstInfo.colorType() == kN32_SkColorType);
261 302
262 // The AND mask is always 1 bit per pixel 303 // If we are sampling, make sure that we only mask the sampled pixels.
263 const int width = this->getInfo().width(); 304 // We do not need to worry about sampling in the y-dimension because that
264 const size_t rowBytes = SkAlign4(compute_row_bytes(width, 1)); 305 // should be handled by SkSampledCodec.
306 const int sampleX = fSwizzler->sampleX();
307 const int sampledWidth = get_scaled_dimension(this->getInfo().width(), sampl eX);
308 const int srcStartX = get_start_coord(sampleX);
309
265 310
266 SkPMColor* dstPtr = (SkPMColor*) dst; 311 SkPMColor* dstPtr = (SkPMColor*) dst;
267 for (int y = 0; y < dstInfo.height(); y++) { 312 for (int y = 0; y < dstInfo.height(); y++) {
268 // The srcBuffer will at least be large enough 313 // The srcBuffer will at least be large enough
269 if (stream()->read(fSrcBuffer.get(), rowBytes) != rowBytes) { 314 if (stream->read(fSrcBuffer.get(), fAndMaskRowBytes) != fAndMaskRowBytes ) {
270 SkCodecPrintf("Warning: incomplete AND mask for bmp-in-ico.\n"); 315 SkCodecPrintf("Warning: incomplete AND mask for bmp-in-ico.\n");
271 return kIncompleteInput; 316 return;
272 } 317 }
273 318
274 int row = this->getDstRow(y, dstInfo.height()); 319 int row = this->getDstRow(y, dstInfo.height());
275 320
276 SkPMColor* dstRow = 321 SkPMColor* dstRow =
277 SkTAddOffset<SkPMColor>(dstPtr, row * dstRowBytes); 322 SkTAddOffset<SkPMColor>(dstPtr, row * dstRowBytes);
278 323
279 for (int x = 0; x < width; x++) { 324 int srcX = srcStartX;
325 for (int dstX = 0; dstX < sampledWidth; dstX++) {
280 int quotient; 326 int quotient;
281 int modulus; 327 int modulus;
282 SkTDivMod(x, 8, &quotient, &modulus); 328 SkTDivMod(srcX, 8, &quotient, &modulus);
283 uint32_t shift = 7 - modulus; 329 uint32_t shift = 7 - modulus;
284 uint32_t alphaBit = 330 uint32_t alphaBit = (fSrcBuffer.get()[quotient] >> shift) & 0x1;
285 (fSrcBuffer.get()[quotient] >> shift) & 0x1; 331 dstRow[dstX] &= alphaBit - 1;
286 dstRow[x] &= alphaBit - 1; 332 srcX += sampleX;
287 } 333 }
288 } 334 }
289 return kSuccess;
290 } 335 }
291 336
292 uint32_t SkBmpStandardCodec::onGetFillValue(SkColorType colorType, SkAlphaType a lphaType) const { 337 uint32_t SkBmpStandardCodec::onGetFillValue(SkColorType colorType, SkAlphaType a lphaType) const {
293 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); 338 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get());
294 if (colorPtr) { 339 if (colorPtr) {
295 return get_color_table_fill_value(colorType, colorPtr, 0); 340 return get_color_table_fill_value(colorType, colorPtr, 0);
296 } 341 }
297 return INHERITED::onGetFillValue(colorType, alphaType); 342 return INHERITED::onGetFillValue(colorType, alphaType);
298 } 343 }
OLDNEW
« no previous file with comments | « src/codec/SkBmpStandardCodec.h ('k') | src/codec/SkCodec_libico.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698