Home | History | Annotate | Download | only in codec
      1 /*
      2  * Copyright 2015 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkCodec.h"
      9 #include "SkData.h"
     10 #include "SkCodec_libbmp.h"
     11 #include "SkCodec_libgif.h"
     12 #include "SkCodec_libico.h"
     13 #include "SkCodec_libpng.h"
     14 #include "SkCodec_wbmp.h"
     15 #include "SkCodecPriv.h"
     16 #include "SkJpegCodec.h"
     17 #include "SkStream.h"
     18 
     19 struct DecoderProc {
     20     bool (*IsFormat)(SkStream*);
     21     SkCodec* (*NewFromStream)(SkStream*);
     22 };
     23 
     24 static const DecoderProc gDecoderProcs[] = {
     25     { SkPngCodec::IsPng, SkPngCodec::NewFromStream },
     26     { SkJpegCodec::IsJpeg, SkJpegCodec::NewFromStream },
     27     { SkGifCodec::IsGif, SkGifCodec::NewFromStream },
     28     { SkIcoCodec::IsIco, SkIcoCodec::NewFromStream },
     29     { SkBmpCodec::IsBmp, SkBmpCodec::NewFromStream },
     30     { SkWbmpCodec::IsWbmp, SkWbmpCodec::NewFromStream }
     31 };
     32 
     33 SkCodec* SkCodec::NewFromStream(SkStream* stream) {
     34     if (!stream) {
     35         return NULL;
     36     }
     37 
     38     SkAutoTDelete<SkStream> streamDeleter(stream);
     39 
     40     SkAutoTDelete<SkCodec> codec(NULL);
     41     for (uint32_t i = 0; i < SK_ARRAY_COUNT(gDecoderProcs); i++) {
     42         DecoderProc proc = gDecoderProcs[i];
     43         const bool correctFormat = proc.IsFormat(stream);
     44         if (!stream->rewind()) {
     45             return NULL;
     46         }
     47         if (correctFormat) {
     48             codec.reset(proc.NewFromStream(streamDeleter.detach()));
     49             break;
     50         }
     51     }
     52 
     53     // Set the max size at 128 megapixels (512 MB for kN32).
     54     // This is about 4x smaller than a test image that takes a few minutes for
     55     // dm to decode and draw.
     56     const int32_t maxSize = 1 << 27;
     57     if (codec && codec->getInfo().width() * codec->getInfo().height() > maxSize) {
     58         SkCodecPrintf("Error: Image size too large, cannot decode.\n");
     59         return NULL;
     60     } else {
     61         return codec.detach();
     62     }
     63 }
     64 
     65 SkCodec* SkCodec::NewFromData(SkData* data) {
     66     if (!data) {
     67         return NULL;
     68     }
     69     return NewFromStream(SkNEW_ARGS(SkMemoryStream, (data)));
     70 }
     71 
     72 SkCodec::SkCodec(const SkImageInfo& info, SkStream* stream)
     73     : INHERITED(info)
     74     , fStream(stream)
     75     , fNeedsRewind(false)
     76 {}
     77 
     78 SkCodec::RewindState SkCodec::rewindIfNeeded() {
     79     // Store the value of fNeedsRewind so we can update it. Next read will
     80     // require a rewind.
     81     const bool needsRewind = fNeedsRewind;
     82     fNeedsRewind = true;
     83     if (!needsRewind) {
     84         return kNoRewindNecessary_RewindState;
     85     }
     86     return fStream->rewind() ? kRewound_RewindState
     87                              : kCouldNotRewind_RewindState;
     88 }
     89 
     90 SkScanlineDecoder* SkCodec::getScanlineDecoder(const SkImageInfo& dstInfo, const Options* options,
     91         SkPMColor ctable[], int* ctableCount) {
     92 
     93     // Set options.
     94     Options optsStorage;
     95     if (NULL == options) {
     96         options = &optsStorage;
     97     }
     98 
     99     fScanlineDecoder.reset(this->onGetScanlineDecoder(dstInfo, *options, ctable, ctableCount));
    100     return fScanlineDecoder.get();
    101 }
    102 
    103 SkScanlineDecoder* SkCodec::getScanlineDecoder(const SkImageInfo& dstInfo) {
    104     SkASSERT(kIndex_8_SkColorType != dstInfo.colorType());
    105     if (kIndex_8_SkColorType == dstInfo.colorType()) {
    106         return NULL;
    107     }
    108     return this->getScanlineDecoder(dstInfo, NULL, NULL, NULL);
    109 }
    110