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

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

Issue 1498903004: Revert of Make SkAndroidCodec support ico (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: 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/SkCodec_libico.h ('k') | src/codec/SkSwizzler.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 "SkBmpCodec.h" 8 #include "SkBmpCodec.h"
9 #include "SkCodec_libico.h" 9 #include "SkCodec_libico.h"
10 #include "SkCodec_libpng.h" 10 #include "SkCodec_libpng.h"
11 #include "SkCodecPriv.h" 11 #include "SkCodecPriv.h"
12 #include "SkColorPriv.h" 12 #include "SkColorPriv.h"
13 #include "SkData.h" 13 #include "SkData.h"
14 #include "SkStream.h" 14 #include "SkStream.h"
15 #include "SkTDArray.h" 15 #include "SkTDArray.h"
16 #include "SkTSort.h" 16 #include "SkTSort.h"
17 17
18 static bool ico_conversion_possible(const SkImageInfo& dstInfo) {
19 // We only support kN32_SkColorType.
20 // This makes sense for BMP-in-ICO. The presence of an AND
21 // mask (which changes colors and adds transparency) means that
22 // we cannot use k565 or kIndex8.
23 // FIXME: For PNG-in-ICO, we could technically support whichever
24 // color types that the png supports.
25 if (kN32_SkColorType != dstInfo.colorType()) {
26 return false;
27 }
28
29 // We only support transparent alpha types. This is necessary for
30 // BMP-in-ICOs since there will be an AND mask.
31 // FIXME: For opaque PNG-in-ICOs, we should be able to support kOpaque.
32 return kPremul_SkAlphaType == dstInfo.alphaType() ||
33 kUnpremul_SkAlphaType == dstInfo.alphaType();
34 }
35
36 static SkImageInfo fix_embedded_alpha(const SkImageInfo& dstInfo, SkAlphaType em beddedAlpha) {
37 // FIXME (msarett): ICO is considered non-opaque, even if the embedded BMP
38 // incorrectly claims it has no alpha.
39 switch (embeddedAlpha) {
40 case kPremul_SkAlphaType:
41 case kUnpremul_SkAlphaType:
42 // Use the requested alpha type if the embedded codec supports alpha .
43 embeddedAlpha = dstInfo.alphaType();
44 break;
45 case kOpaque_SkAlphaType:
46 // If the embedded codec claims it is opaque, decode as if it is opa que.
47 break;
48 default:
49 SkASSERT(false);
50 break;
51 }
52 return dstInfo.makeAlphaType(embeddedAlpha);
53 }
54
55 /* 18 /*
56 * Checks the start of the stream to see if the image is an Ico or Cur 19 * Checks the start of the stream to see if the image is an Ico or Cur
57 */ 20 */
58 bool SkIcoCodec::IsIco(SkStream* stream) { 21 bool SkIcoCodec::IsIco(SkStream* stream) {
59 const char icoSig[] = { '\x00', '\x00', '\x01', '\x00' }; 22 const char icoSig[] = { '\x00', '\x00', '\x01', '\x00' };
60 const char curSig[] = { '\x00', '\x00', '\x02', '\x00' }; 23 const char curSig[] = { '\x00', '\x00', '\x02', '\x00' };
61 char buffer[sizeof(icoSig)]; 24 char buffer[sizeof(icoSig)];
62 return stream->read(buffer, sizeof(icoSig)) == sizeof(icoSig) && 25 return stream->read(buffer, sizeof(icoSig)) == sizeof(icoSig) &&
63 (!memcmp(buffer, icoSig, sizeof(icoSig)) || 26 (!memcmp(buffer, icoSig, sizeof(icoSig)) ||
64 !memcmp(buffer, curSig, sizeof(curSig))); 27 !memcmp(buffer, curSig, sizeof(curSig)));
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
227 } 190 }
228 191
229 /* 192 /*
230 * Creates an instance of the decoder 193 * Creates an instance of the decoder
231 * Called only by NewFromStream 194 * Called only by NewFromStream
232 */ 195 */
233 SkIcoCodec::SkIcoCodec(const SkImageInfo& info, 196 SkIcoCodec::SkIcoCodec(const SkImageInfo& info,
234 SkTArray<SkAutoTDelete<SkCodec>, true>* codecs) 197 SkTArray<SkAutoTDelete<SkCodec>, true>* codecs)
235 : INHERITED(info, nullptr) 198 : INHERITED(info, nullptr)
236 , fEmbeddedCodecs(codecs) 199 , fEmbeddedCodecs(codecs)
237 , fCurrScanlineCodec(nullptr)
238 {} 200 {}
239 201
240 /* 202 /*
241 * Chooses the best dimensions given the desired scale 203 * Chooses the best dimensions given the desired scale
242 */ 204 */
243 SkISize SkIcoCodec::onGetScaledDimensions(float desiredScale) const { 205 SkISize SkIcoCodec::onGetScaledDimensions(float desiredScale) const {
244 // We set the dimensions to the largest candidate image by default. 206 // We set the dimensions to the largest candidate image by default.
245 // Regardless of the scale request, this is the largest image that we 207 // Regardless of the scale request, this is the largest image that we
246 // will decode. 208 // will decode.
247 int origWidth = this->getInfo().width(); 209 int origWidth = this->getInfo().width();
248 int origHeight = this->getInfo().height(); 210 int origHeight = this->getInfo().height();
249 float desiredSize = desiredScale * origWidth * origHeight; 211 float desiredSize = desiredScale * origWidth * origHeight;
250 // At least one image will have smaller error than this initial value 212 // At least one image will have smaller error than this initial value
251 float minError = ((float) (origWidth * origHeight)) - desiredSize + 1.0f; 213 float minError = ((float) (origWidth * origHeight)) - desiredSize + 1.0f;
252 int32_t minIndex = -1; 214 int32_t minIndex = -1;
253 for (int32_t i = 0; i < fEmbeddedCodecs->count(); i++) { 215 for (int32_t i = 0; i < fEmbeddedCodecs->count(); i++) {
254 int width = fEmbeddedCodecs->operator[](i)->getInfo().width(); 216 int width = fEmbeddedCodecs->operator[](i)->getInfo().width();
255 int height = fEmbeddedCodecs->operator[](i)->getInfo().height(); 217 int height = fEmbeddedCodecs->operator[](i)->getInfo().height();
256 float error = SkTAbs(((float) (width * height)) - desiredSize); 218 float error = SkTAbs(((float) (width * height)) - desiredSize);
257 if (error < minError) { 219 if (error < minError) {
258 minError = error; 220 minError = error;
259 minIndex = i; 221 minIndex = i;
260 } 222 }
261 } 223 }
262 SkASSERT(minIndex >= 0); 224 SkASSERT(minIndex >= 0);
263 225
264 return fEmbeddedCodecs->operator[](minIndex)->getInfo().dimensions(); 226 return fEmbeddedCodecs->operator[](minIndex)->getInfo().dimensions();
265 } 227 }
266 228
267 int SkIcoCodec::chooseCodec(const SkISize& requestedSize, int startIndex) { 229 bool SkIcoCodec::onDimensionsSupported(const SkISize& dim) {
268 SkASSERT(startIndex >= 0);
269
270 // FIXME: Cache the index from onGetScaledDimensions? 230 // FIXME: Cache the index from onGetScaledDimensions?
271 for (int i = startIndex; i < fEmbeddedCodecs->count(); i++) { 231 for (int32_t i = 0; i < fEmbeddedCodecs->count(); i++) {
272 if (fEmbeddedCodecs->operator[](i)->getInfo().dimensions() == requestedS ize) { 232 if (fEmbeddedCodecs->operator[](i)->getInfo().dimensions() == dim) {
273 return i; 233 return true;
274 } 234 }
275 } 235 }
276 236
277 return -1; 237 return false;
278 }
279
280 bool SkIcoCodec::onDimensionsSupported(const SkISize& dim) {
281 return this->chooseCodec(dim, 0) >= 0;
282 } 238 }
283 239
284 /* 240 /*
285 * Initiates the Ico decode 241 * Initiates the Ico decode
286 */ 242 */
287 SkCodec::Result SkIcoCodec::onGetPixels(const SkImageInfo& dstInfo, 243 SkCodec::Result SkIcoCodec::onGetPixels(const SkImageInfo& dstInfo,
288 void* dst, size_t dstRowBytes, 244 void* dst, size_t dstRowBytes,
289 const Options& opts, SkPMColor* colorTab le, 245 const Options& opts, SkPMColor* colorTab le,
290 int* colorCount, int* rowsDecoded) { 246 int* colorCount, int* rowsDecoded) {
291 if (opts.fSubset) { 247 if (opts.fSubset) {
292 // Subsets are not supported. 248 // Subsets are not supported.
293 return kUnimplemented; 249 return kUnimplemented;
294 } 250 }
295 251
296 if (!ico_conversion_possible(dstInfo)) { 252 if (!valid_alpha(dstInfo.alphaType(), this->getInfo().alphaType())) {
297 return kInvalidConversion; 253 return kInvalidConversion;
298 } 254 }
299 255
300 int index = 0; 256 // We return invalid scale if there is no candidate image with matching
301 SkCodec::Result result = kInvalidScale; 257 // dimensions.
302 while (true) { 258 Result result = kInvalidScale;
303 index = this->chooseCodec(dstInfo.dimensions(), index); 259 for (int32_t i = 0; i < fEmbeddedCodecs->count(); i++) {
304 if (index < 0) { 260 SkCodec* embeddedCodec = fEmbeddedCodecs->operator[](i);
305 break; 261 // If the dimensions match, try to decode
262 if (dstInfo.dimensions() == embeddedCodec->getInfo().dimensions()) {
263
264 // Perform the decode
265 // FIXME (msarett): ICO is considered non-opaque, even if the embedd ed BMP
266 // incorrectly claims it has no alpha.
267 SkAlphaType embeddedAlpha = embeddedCodec->getInfo().alphaType();
268 switch (embeddedAlpha) {
269 case kPremul_SkAlphaType:
270 case kUnpremul_SkAlphaType:
271 // Use the requested alpha type if the embedded codec suppor ts alpha.
272 embeddedAlpha = dstInfo.alphaType();
273 break;
274 case kOpaque_SkAlphaType:
275 // If the embedded codec claims it is opaque, decode as if i t is opaque.
276 break;
277 default:
278 SkASSERT(false);
279 break;
280 }
281 SkImageInfo info = dstInfo.makeAlphaType(embeddedAlpha);
282 result = embeddedCodec->getPixels(info, dst, dstRowBytes, &opts, col orTable,
283 colorCount);
284 // The embedded codec will handle filling incomplete images, so we w ill indicate
285 // that all of the rows are initialized.
286 *rowsDecoded = info.height();
287
288 // On a fatal error, keep trying to find an image to decode
289 if (kInvalidConversion == result || kInvalidInput == result ||
290 kInvalidScale == result) {
291 SkCodecPrintf("Warning: Attempt to decode candidate ico failed.\ n");
292 continue;
293 }
294
295 // On success or partial success, return the result
296 return result;
306 } 297 }
307
308 SkCodec* embeddedCodec = fEmbeddedCodecs->operator[](index);
309 SkImageInfo decodeInfo = fix_embedded_alpha(dstInfo, embeddedCodec->getI nfo().alphaType());
310 SkASSERT(decodeInfo.colorType() == kN32_SkColorType);
311 result = embeddedCodec->getPixels(decodeInfo, dst, dstRowBytes, &opts, c olorTable,
312 colorCount);
313
314 switch (result) {
315 case kSuccess:
316 case kIncompleteInput:
317 // The embedded codec will handle filling incomplete images, so we will indicate
318 // that all of the rows are initialized.
319 *rowsDecoded = decodeInfo.height();
320 return result;
321 default:
322 // Continue trying to find a valid embedded codec on a failed de code.
323 break;
324 }
325
326 index++;
327 } 298 }
328 299
329 SkCodecPrintf("Error: No matching candidate image in ico.\n"); 300 SkCodecPrintf("Error: No matching candidate image in ico.\n");
330 return result; 301 return result;
331 } 302 }
332
333 SkCodec::Result SkIcoCodec::onStartScanlineDecode(const SkImageInfo& dstInfo,
334 const SkCodec::Options& options, SkPMColor colorTable[], int* colorCount ) {
335 if (!ico_conversion_possible(dstInfo)) {
336 return kInvalidConversion;
337 }
338
339 int index = 0;
340 SkCodec::Result result = kInvalidScale;
341 while (true) {
342 index = this->chooseCodec(dstInfo.dimensions(), index);
343 if (index < 0) {
344 break;
345 }
346
347 SkCodec* embeddedCodec = fEmbeddedCodecs->operator[](index);
348 SkImageInfo decodeInfo = fix_embedded_alpha(dstInfo, embeddedCodec->getI nfo().alphaType());
349 result = embeddedCodec->startScanlineDecode(decodeInfo, &options, colorT able, colorCount);
350 if (kSuccess == result) {
351 fCurrScanlineCodec = embeddedCodec;
352 return result;
353 }
354
355 index++;
356 }
357
358 SkCodecPrintf("Error: No matching candidate image in ico.\n");
359 return result;
360 }
361
362 int SkIcoCodec::onGetScanlines(void* dst, int count, size_t rowBytes) {
363 SkASSERT(fCurrScanlineCodec);
364 return fCurrScanlineCodec->getScanlines(dst, count, rowBytes);
365 }
366
367 bool SkIcoCodec::onSkipScanlines(int count) {
368 SkASSERT(fCurrScanlineCodec);
369 return fCurrScanlineCodec->skipScanlines(count);
370 }
371
372 SkCodec::SkScanlineOrder SkIcoCodec::onGetScanlineOrder() const {
373 // FIXME: This function will possibly return the wrong value if it is called
374 // before startScanlineDecode().
375 return fCurrScanlineCodec ? fCurrScanlineCodec->getScanlineOrder() :
376 INHERITED::onGetScanlineOrder();
377 }
378
379 SkSampler* SkIcoCodec::getSampler(bool createIfNecessary) {
380 return fCurrScanlineCodec ? fCurrScanlineCodec->getSampler(createIfNecessary ) : nullptr;
381 }
OLDNEW
« no previous file with comments | « src/codec/SkCodec_libico.h ('k') | src/codec/SkSwizzler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698