SkCodec* SkCodec::NewFromStream(SkStream* stream, SkPngChunkReader* chunkReader) { if (!stream) { return nullptr; } SkAutoTDelete<SkStream> streamDeleter(stream); // 14 is enough to read all of the supported types. const size_t bytesToRead = 14; SkASSERT(bytesToRead <= MinBufferedBytesNeeded()); char buffer[bytesToRead]; size_t bytesRead = stream->peek(buffer, bytesToRead); // It is also possible to have a complete image less than bytesToRead bytes // (e.g. a 1 x 1 wbmp), meaning peek() would return less than bytesToRead. // Assume that if bytesRead < bytesToRead, but > 0, the stream is shorter // than bytesToRead, so pass that directly to the decoder. // It also is possible the stream uses too small a buffer for peeking, but // we trust the caller to use a large enough buffer. if (0 == bytesRead) { SkCodecPrintf("Could not peek!\n"); // It is possible the stream does not support peeking, but does support // rewinding. // Attempt to read() and pass the actual amount read to the decoder. bytesRead = stream->read(buffer, bytesToRead); if (!stream->rewind()) { SkCodecPrintf("Could not rewind!\n"); return nullptr; } } SkAutoTDelete<SkCodec> codec(nullptr); // PNG is special, since we want to be able to supply an SkPngChunkReader. // But this code follows the same pattern as the loop. if (SkPngCodec::IsPng(buffer, bytesRead)) { codec.reset(SkPngCodec::NewFromStream(streamDeleter.detach(), chunkReader)); } else { for (DecoderProc proc : gDecoderProcs) { if (proc.IsFormat(buffer, bytesRead)) { codec.reset(proc.NewFromStream(streamDeleter.detach())); break; } } } // Set the max size at 128 megapixels (512 MB for kN32). // This is about 4x smaller than a test image that takes a few minutes for // dm to decode and draw. const int32_t maxSize = 1 << 27; if (codec && codec->getInfo().width() * codec->getInfo().height() > maxSize) { SkCodecPrintf("Error: Image size too large, cannot decode.\n"); return nullptr; } else { return codec.detach(); } }
SkCodec* SkCodec::NewFromStream(SkStream* stream, SkPngChunkReader* chunkReader) { if (!stream) { return nullptr; } SkAutoTDelete<SkStream> streamDeleter(stream); // 14 is enough to read all of the supported types. const size_t bytesToRead = 14; SkASSERT(bytesToRead <= MinBufferedBytesNeeded()); char buffer[bytesToRead]; size_t bytesRead = stream->peek(buffer, bytesToRead); // It is also possible to have a complete image less than bytesToRead bytes // (e.g. a 1 x 1 wbmp), meaning peek() would return less than bytesToRead. // Assume that if bytesRead < bytesToRead, but > 0, the stream is shorter // than bytesToRead, so pass that directly to the decoder. // It also is possible the stream uses too small a buffer for peeking, but // we trust the caller to use a large enough buffer. if (0 == bytesRead) { // TODO: After implementing peek in CreateJavaOutputStreamAdaptor.cpp, this // printf could be useful to notice failures. // SkCodecPrintf("Encoded image data failed to peek!\n"); // It is possible the stream does not support peeking, but does support // rewinding. // Attempt to read() and pass the actual amount read to the decoder. bytesRead = stream->read(buffer, bytesToRead); if (!stream->rewind()) { SkCodecPrintf("Encoded image data could not peek or rewind to determine format!\n"); return nullptr; } } // PNG is special, since we want to be able to supply an SkPngChunkReader. // But this code follows the same pattern as the loop. #ifdef SK_CODEC_DECODES_PNG if (SkPngCodec::IsPng(buffer, bytesRead)) { return SkPngCodec::NewFromStream(streamDeleter.detach(), chunkReader); } else #endif { for (DecoderProc proc : gDecoderProcs) { if (proc.IsFormat(buffer, bytesRead)) { return proc.NewFromStream(streamDeleter.detach()); } } #ifdef SK_CODEC_DECODES_RAW // Try to treat the input as RAW if all the other checks failed. return SkRawCodec::NewFromStream(streamDeleter.detach()); #endif } return nullptr; }