1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
24c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com * Copyright 2013 The Android Open Source Project
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com#include "SkErrorInternals.h"
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkImageDecoder.h"
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkStream.h"
1100bf85a98675c9d0c3150bbeb0a3d7198ad8f21freed@android.com#include "SkTRegistry.h"
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
134c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com// This file is used for registration of SkImageDecoders. It also holds a function
144c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com// for checking all the the registered SkImageDecoders for one that matches an
15b5571b3324cf18629a255ec85e189447069c9b14scroggo@google.com// input SkStreamRewindable.
164c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com
17bd6343b1d60d2a85e930f33f4b06b4502b3e8caamtklein@google.comtemplate SkImageDecoder_DecodeReg* SkImageDecoder_DecodeReg::gHead;
183c2b7e8b5e718192e9c944b2c79189e2ee227606reed@android.com
19b5571b3324cf18629a255ec85e189447069c9b14scroggo@google.comSkImageDecoder* image_decoder_from_stream(SkStreamRewindable*);
204c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com
21b5571b3324cf18629a255ec85e189447069c9b14scroggo@google.comSkImageDecoder* image_decoder_from_stream(SkStreamRewindable* stream) {
22dfee579a8de6462399f1b1867f924856c11bc4a1reed@android.com    SkImageDecoder* codec = NULL;
23bd6343b1d60d2a85e930f33f4b06b4502b3e8caamtklein@google.com    const SkImageDecoder_DecodeReg* curr = SkImageDecoder_DecodeReg::Head();
2400bf85a98675c9d0c3150bbeb0a3d7198ad8f21freed@android.com    while (curr) {
25dfee579a8de6462399f1b1867f924856c11bc4a1reed@android.com        codec = curr->factory()(stream);
26a16cb97c89fedcd521aeaadfa94feddbcb6729b1reed@android.com        // we rewind here, because we promise later when we call "decode", that
27a16cb97c89fedcd521aeaadfa94feddbcb6729b1reed@android.com        // the stream will be at its beginning.
2850166524abd948f6288089c572cf125d2b4827a7djsollen@google.com        bool rewindSuceeded = stream->rewind();
2950166524abd948f6288089c572cf125d2b4827a7djsollen@google.com
3050166524abd948f6288089c572cf125d2b4827a7djsollen@google.com        // our image decoder's require that rewind is supported so we fail early
3150166524abd948f6288089c572cf125d2b4827a7djsollen@google.com        // if we are given a stream that does not support rewinding.
3250166524abd948f6288089c572cf125d2b4827a7djsollen@google.com        if (!rewindSuceeded) {
3350166524abd948f6288089c572cf125d2b4827a7djsollen@google.com            SkDEBUGF(("Unable to rewind the image stream."));
3450166524abd948f6288089c572cf125d2b4827a7djsollen@google.com            SkDELETE(codec);
3550166524abd948f6288089c572cf125d2b4827a7djsollen@google.com            return NULL;
3650166524abd948f6288089c572cf125d2b4827a7djsollen@google.com        }
3750166524abd948f6288089c572cf125d2b4827a7djsollen@google.com
3800bf85a98675c9d0c3150bbeb0a3d7198ad8f21freed@android.com        if (codec) {
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return codec;
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
4100bf85a98675c9d0c3150bbeb0a3d7198ad8f21freed@android.com        curr = curr->next();
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return NULL;
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
46bd6343b1d60d2a85e930f33f4b06b4502b3e8caamtklein@google.comtemplate SkImageDecoder_FormatReg* SkImageDecoder_FormatReg::gHead;
4739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com
48b5571b3324cf18629a255ec85e189447069c9b14scroggo@google.comSkImageDecoder::Format SkImageDecoder::GetStreamFormat(SkStreamRewindable* stream) {
49bd6343b1d60d2a85e930f33f4b06b4502b3e8caamtklein@google.com    const SkImageDecoder_FormatReg* curr = SkImageDecoder_FormatReg::Head();
5039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    while (curr != NULL) {
5139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        Format format = curr->factory()(stream);
5239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        if (!stream->rewind()) {
5339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com            SkErrorInternals::SetError(kInvalidOperation_SkError,
5439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com                                       "Unable to rewind the image stream\n");
5539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com            return kUnknown_Format;
5639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        }
5739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        if (format != kUnknown_Format) {
5839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com            return format;
5939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        }
6039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com        curr = curr->next();
6139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    }
6239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com    return kUnknown_Format;
6339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com}
64