diff options
Diffstat (limited to 'include/codec/SkCodec.h')
-rw-r--r-- | include/codec/SkCodec.h | 205 |
1 files changed, 202 insertions, 3 deletions
diff --git a/include/codec/SkCodec.h b/include/codec/SkCodec.h index bdfa2326fb..01fd4fa62a 100644 --- a/include/codec/SkCodec.h +++ b/include/codec/SkCodec.h @@ -45,7 +45,7 @@ public: /** * Return the ImageInfo associated with this codec. */ - const SkImageInfo& getInfo() const { return fInfo; } + const SkImageInfo& getInfo() const { return fSrcInfo; } /** * Return a size that approximately supports the desired scale factor. @@ -131,7 +131,12 @@ public: */ kCouldNotRewind, /** - * This method is not implemented by this generator. + * startScanlineDecode() was not called before calling getScanlines. + */ + kScanlineDecodingNotStarted, + /** + * This method is not implemented by this codec. + * FIXME: Perhaps this should be kUnsupported? */ kUnimplemented, }; @@ -202,6 +207,9 @@ public: * If info is not kIndex8_SkColorType, then the last two parameters may be NULL. If ctableCount * is not null, it will be set to 0. * + * If a scanline decode is in progress, scanline mode will end, requiring the client to call + * startScanlineDecode() in order to return to decoding scanlines. + * * @return Result kSuccess, or another value explaining the type of failure. */ Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const Options*, @@ -225,6 +233,147 @@ public: return this->onReallyHasAlpha(); } + /** + * The remaining functions revolve around decoding scanlines. + */ + + /** + * Prepare for a scanline decode with the specified options. + * + * After this call, this class will be ready to decode the first scanline. + * + * This must be called in order to call getScanlines or skipScanlines. + * + * This may require rewinding the stream. + * + * Not all SkCodecs support this. + * + * @param dstInfo Info of the destination. If the dimensions do not match + * those of getInfo, this implies a scale. + * @param options Contains decoding options, including if memory is zero + * initialized. + * @param ctable A pointer to a color table. When dstInfo.colorType() is + * kIndex8, this should be non-NULL and have enough storage for 256 + * colors. The color table will be populated after decoding the palette. + * @param ctableCount A pointer to the size of the color table. When + * dstInfo.colorType() is kIndex8, this should be non-NULL. It will + * be modified to the true size of the color table (<= 256) after + * decoding the palette. + * @return Enum representing success or reason for failure. + */ + Result startScanlineDecode(const SkImageInfo& dstInfo, const SkCodec::Options* options, + SkPMColor ctable[], int* ctableCount); + + /** + * Simplified version of startScanlineDecode() that asserts that info is NOT + * kIndex8_SkColorType and uses the default Options. + */ + Result startScanlineDecode(const SkImageInfo& dstInfo); + + /** + * Write the next countLines scanlines into dst. + * + * Not valid to call before calling startScanlineDecode(). + * + * @param dst Must be non-null, and large enough to hold countLines + * scanlines of size rowBytes. + * @param countLines Number of lines to write. + * @param rowBytes Number of bytes per row. Must be large enough to hold + * a scanline based on the SkImageInfo used to create this object. + */ + Result getScanlines(void* dst, int countLines, size_t rowBytes); + + /** + * Skip count scanlines. + * + * Not valid to call before calling startScanlineDecode(). + * + * The default version just calls onGetScanlines and discards the dst. + * NOTE: If skipped lines are the only lines with alpha, this default + * will make reallyHasAlpha return true, when it could have returned + * false. + */ + Result skipScanlines(int countLines); + + /** + * The order in which rows are output from the scanline decoder is not the + * same for all variations of all image types. This explains the possible + * output row orderings. + */ + enum SkScanlineOrder { + /* + * By far the most common, this indicates that the image can be decoded + * reliably using the scanline decoder, and that rows will be output in + * the logical order. + */ + kTopDown_SkScanlineOrder, + + /* + * This indicates that the scanline decoder reliably outputs rows, but + * they will be returned in reverse order. If the scanline format is + * kBottomUp, the nextScanline() API can be used to determine the actual + * y-coordinate of the next output row, but the client is not forced + * to take advantage of this, given that it's not too tough to keep + * track independently. + * + * For full image decodes, it is safe to get all of the scanlines at + * once, since the decoder will handle inverting the rows as it + * decodes. + * + * For subset decodes and sampling, it is simplest to get and skip + * scanlines one at a time, using the nextScanline() API. It is + * possible to ask for larger chunks at a time, but this should be used + * with caution. As with full image decodes, the decoder will handle + * inverting the requested rows, but rows will still be delivered + * starting from the bottom of the image. + * + * Upside down bmps are an example. + */ + kBottomUp_SkScanlineOrder, + + /* + * This indicates that the scanline decoder reliably outputs rows, but + * they will not be in logical order. If the scanline format is + * kOutOfOrder, the nextScanline() API should be used to determine the + * actual y-coordinate of the next output row. + * + * For this scanline ordering, it is advisable to get and skip + * scanlines one at a time. + * + * Interlaced gifs are an example. + */ + kOutOfOrder_SkScanlineOrder, + + /* + * Indicates that the entire image must be decoded in order to output + * any amount of scanlines. In this case, it is a REALLY BAD IDEA to + * request scanlines 1-by-1 or in small chunks. The client should + * determine which scanlines are needed and ask for all of them in + * a single call to getScanlines(). + * + * Interlaced pngs are an example. + */ + kNone_SkScanlineOrder, + }; + + /** + * An enum representing the order in which scanlines will be returned by + * the scanline decoder. + */ + SkScanlineOrder getScanlineOrder() const { return this->onGetScanlineOrder(); } + + /** + * Returns the y-coordinate of the next row to be returned by the scanline + * decoder. This will be overridden in the case of + * kOutOfOrder_SkScanlineOrder and should be unnecessary in the case of + * kNone_SkScanlineOrder. + * + * Results are undefined when not in scanline decoding mode. + */ + int nextScanline() const { + return this->onNextScanline(); + } + protected: SkCodec(const SkImageInfo&, SkStream*); @@ -275,9 +424,59 @@ protected: return fStream.get(); } + /** + * The remaining functions revolve around decoding scanlines. + */ + + /** + * Most images types will be kTopDown and will not need to override this function. + */ + virtual SkScanlineOrder onGetScanlineOrder() const { return kTopDown_SkScanlineOrder; } + + /** + * Most images will be kTopDown and will not need to override this function. + */ + virtual int onNextScanline() const { return fCurrScanline; } + + /** + * Update the next scanline. Used by interlaced png. + */ + void updateNextScanline(int newY) { fCurrScanline = newY; } + + const SkImageInfo& dstInfo() const { return fDstInfo; } + + const SkCodec::Options& options() const { return fOptions; } + private: - const SkImageInfo fInfo; + const SkImageInfo fSrcInfo; SkAutoTDelete<SkStream> fStream; bool fNeedsRewind; + // These fields are only meaningful during scanline decodes. + SkImageInfo fDstInfo; + SkCodec::Options fOptions; + int fCurrScanline; + + // Methods for scanline decoding. + virtual SkCodec::Result onStartScanlineDecode(const SkImageInfo& dstInfo, + const SkCodec::Options& options, SkPMColor ctable[], int* ctableCount) { + return kUnimplemented; + } + + // Naive default version just calls onGetScanlines on temp memory. + virtual SkCodec::Result onSkipScanlines(int countLines) { + SkAutoMalloc storage(fDstInfo.minRowBytes()); + // Note that we pass 0 to rowBytes so we continue to use the same memory. + // Also note that while getScanlines checks that rowBytes is big enough, + // onGetScanlines bypasses that check. + // Calling the virtual method also means we do not double count + // countLines. + return this->onGetScanlines(storage.get(), countLines, 0); + } + + virtual SkCodec::Result onGetScanlines(void* dst, int countLines, + size_t rowBytes) { + return kUnimplemented; + } + }; #endif // SkCodec_DEFINED |