25e9834c03
git-svn-id: http://skia.googlecode.com/svn/trunk@173 2bbb7eff-a529-9590-31e7-b0007b416f81
287 lines
11 KiB
C++
287 lines
11 KiB
C++
/*
|
|
* Copyright (C) 2006 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#ifndef SkImageDecoder_DEFINED
|
|
#define SkImageDecoder_DEFINED
|
|
|
|
#include "SkBitmap.h"
|
|
#include "SkRefCnt.h"
|
|
|
|
class SkStream;
|
|
|
|
/** \class SkImageDecoder
|
|
|
|
Base class for decoding compressed images into a SkBitmap
|
|
*/
|
|
class SkImageDecoder {
|
|
public:
|
|
virtual ~SkImageDecoder();
|
|
|
|
enum Format {
|
|
kUnknown_Format,
|
|
kBMP_Format,
|
|
kGIF_Format,
|
|
kICO_Format,
|
|
kJPEG_Format,
|
|
kPNG_Format,
|
|
kWBMP_Format,
|
|
|
|
kLastKnownFormat = kWBMP_Format
|
|
};
|
|
|
|
/** Return the compressed data's format (see Format enum)
|
|
*/
|
|
virtual Format getFormat() const;
|
|
|
|
/** Returns true if the decoder should try to dither the resulting image.
|
|
The default setting is true.
|
|
*/
|
|
bool getDitherImage() const { return fDitherImage; }
|
|
|
|
/** Set to true if the the decoder should try to dither the resulting image.
|
|
The default setting is true.
|
|
*/
|
|
void setDitherImage(bool dither) { fDitherImage = dither; }
|
|
|
|
/** \class Peeker
|
|
|
|
Base class for optional callbacks to retrieve meta/chunk data out of
|
|
an image as it is being decoded.
|
|
*/
|
|
class Peeker : public SkRefCnt {
|
|
public:
|
|
/** Return true to continue decoding, or false to indicate an error, which
|
|
will cause the decoder to not return the image.
|
|
*/
|
|
virtual bool peek(const char tag[], const void* data, size_t length) = 0;
|
|
};
|
|
|
|
Peeker* getPeeker() const { return fPeeker; }
|
|
Peeker* setPeeker(Peeker*);
|
|
|
|
/** \class Peeker
|
|
|
|
Base class for optional callbacks to retrieve meta/chunk data out of
|
|
an image as it is being decoded.
|
|
*/
|
|
class Chooser : public SkRefCnt {
|
|
public:
|
|
virtual void begin(int count) {}
|
|
virtual void inspect(int index, SkBitmap::Config config, int width, int height) {}
|
|
/** Return the index of the subimage you want, or -1 to choose none of them.
|
|
*/
|
|
virtual int choose() = 0;
|
|
};
|
|
|
|
Chooser* getChooser() const { return fChooser; }
|
|
Chooser* setChooser(Chooser*);
|
|
|
|
SkBitmap::Allocator* getAllocator() const { return fAllocator; }
|
|
SkBitmap::Allocator* setAllocator(SkBitmap::Allocator*);
|
|
|
|
// sample-size, if set to > 1, tells the decoder to return a smaller than
|
|
// original bitmap, sampling 1 pixel for every size pixels. e.g. if sample
|
|
// size is set to 3, then the returned bitmap will be 1/3 as wide and high,
|
|
// and will contain 1/9 as many pixels as the original.
|
|
// Note: this is a hint, and the codec may choose to ignore this, or only
|
|
// approximate the sample size.
|
|
int getSampleSize() const { return fSampleSize; }
|
|
void setSampleSize(int size);
|
|
|
|
/** Reset the sampleSize to its default of 1
|
|
*/
|
|
void resetSampleSize() { this->setSampleSize(1); }
|
|
|
|
/** Decoding is synchronous, but for long decodes, a different thread can
|
|
call this method safely. This sets a state that the decoders will
|
|
periodically check, and if they see it changed to cancel, they will
|
|
cancel. This will result in decode() returning false. However, there is
|
|
no guarantee that the decoder will see the state change in time, so
|
|
it is possible that cancelDecode() will be called, but will be ignored
|
|
and decode() will return true (assuming no other problems were
|
|
encountered).
|
|
|
|
This state is automatically reset at the beginning of decode().
|
|
*/
|
|
void cancelDecode() {
|
|
// now the subclass must query shouldCancelDecode() to be informed
|
|
// of the request
|
|
fShouldCancelDecode = true;
|
|
}
|
|
|
|
/** Passed to the decode method. If kDecodeBounds_Mode is passed, then
|
|
only the bitmap's width/height/config need be set. If kDecodePixels_Mode
|
|
is passed, then the bitmap must have pixels or a pixelRef.
|
|
*/
|
|
enum Mode {
|
|
kDecodeBounds_Mode, //!< only return width/height/config in bitmap
|
|
kDecodePixels_Mode //!< return entire bitmap (including pixels)
|
|
};
|
|
|
|
/** Given a stream, decode it into the specified bitmap.
|
|
If the decoder can decompress the image, it calls bitmap.setConfig(),
|
|
and then if the Mode is kDecodePixels_Mode, call allocPixelRef(),
|
|
which will allocated a pixelRef. To access the pixel memory, the codec
|
|
needs to call lockPixels/unlockPixels on the
|
|
bitmap. It can then set the pixels with the decompressed image.
|
|
* If the image cannot be decompressed, return false. After the
|
|
* decoding, the function converts the decoded config in bitmap
|
|
* to pref if possible. Whether a conversion is feasible is
|
|
* tested by Bitmap::canCopyTo(pref).
|
|
|
|
note: document use of Allocator, Peeker and Chooser
|
|
*/
|
|
bool decode(SkStream*, SkBitmap* bitmap, SkBitmap::Config pref, Mode);
|
|
|
|
/** Given a stream, this will try to find an appropriate decoder object.
|
|
If none is found, the method returns NULL.
|
|
*/
|
|
static SkImageDecoder* Factory(SkStream*);
|
|
|
|
/** Decode the image stored in the specified file, and store the result
|
|
in bitmap. Return true for success or false on failure.
|
|
|
|
If pref is kNo_Config, then the decoder is free to choose the most natural
|
|
config given the image data. If pref something other than kNo_Config,
|
|
the decoder will attempt to decode the image into that format, unless
|
|
there is a conflict (e.g. the image has per-pixel alpha and the bitmap's
|
|
config does not support that), in which case the decoder will choose a
|
|
closest match configuration.
|
|
*/
|
|
static bool DecodeFile(const char file[], SkBitmap* bitmap,
|
|
SkBitmap::Config prefConfig, Mode);
|
|
static bool DecodeFile(const char file[], SkBitmap* bitmap)
|
|
{
|
|
return DecodeFile(file, bitmap, SkBitmap::kNo_Config, kDecodePixels_Mode);
|
|
}
|
|
/** Decode the image stored in the specified memory buffer, and store the
|
|
result in bitmap. Return true for success or false on failure.
|
|
|
|
If pref is kNo_Config, then the decoder is free to choose the most natural
|
|
config given the image data. If pref something other than kNo_Config,
|
|
the decoder will attempt to decode the image into that format, unless
|
|
there is a conflict (e.g. the image has per-pixel alpha and the bitmap's
|
|
config does not support that), in which case the decoder will choose a
|
|
closest match configuration.
|
|
*/
|
|
static bool DecodeMemory(const void* buffer, size_t size, SkBitmap* bitmap,
|
|
SkBitmap::Config prefConfig, Mode);
|
|
static bool DecodeMemory(const void* buffer, size_t size, SkBitmap* bitmap)
|
|
{
|
|
return DecodeMemory(buffer, size, bitmap, SkBitmap::kNo_Config,
|
|
kDecodePixels_Mode);
|
|
}
|
|
/** Decode the image stored in the specified SkStream, and store the result
|
|
in bitmap. Return true for success or false on failure.
|
|
|
|
If pref is kNo_Config, then the decoder is free to choose the most
|
|
natural config given the image data. If pref something other than
|
|
kNo_Config, the decoder will attempt to decode the image into that
|
|
format, unless there is a conflict (e.g. the image has per-pixel alpha
|
|
and the bitmap's config does not support that), in which case the
|
|
decoder will choose a closest match configuration.
|
|
*/
|
|
static bool DecodeStream(SkStream* stream, SkBitmap* bitmap,
|
|
SkBitmap::Config prefConfig, Mode);
|
|
static bool DecodeStream(SkStream* stream, SkBitmap* bitmap)
|
|
{
|
|
return DecodeStream(stream, bitmap, SkBitmap::kNo_Config,
|
|
kDecodePixels_Mode);
|
|
}
|
|
|
|
/** Return the default config for the running device.
|
|
Currently this used as a suggestion to image decoders that need to guess
|
|
what config they should decode into.
|
|
Default is kNo_Config, but this can be changed with SetDeviceConfig()
|
|
*/
|
|
static SkBitmap::Config GetDeviceConfig();
|
|
/** Set the default config for the running device.
|
|
Currently this used as a suggestion to image decoders that need to guess
|
|
what config they should decode into.
|
|
Default is kNo_Config.
|
|
This can be queried with GetDeviceConfig()
|
|
*/
|
|
static void SetDeviceConfig(SkBitmap::Config);
|
|
|
|
/** @cond UNIT_TEST */
|
|
SkDEBUGCODE(static void UnitTest();)
|
|
/** @endcond */
|
|
|
|
protected:
|
|
// must be overridden in subclasses. This guy is called by decode(...)
|
|
virtual bool onDecode(SkStream*, SkBitmap* bitmap, SkBitmap::Config pref,
|
|
Mode) = 0;
|
|
|
|
/** Can be queried from within onDecode, to see if the user (possibly in
|
|
a different thread) has requested the decode to cancel. If this returns
|
|
true, your onDecode() should stop and return false.
|
|
Each subclass needs to decide how often it can query this, to balance
|
|
responsiveness with performance.
|
|
|
|
Calling this outside of onDecode() may return undefined values.
|
|
*/
|
|
|
|
public:
|
|
bool shouldCancelDecode() const { return fShouldCancelDecode; }
|
|
|
|
protected:
|
|
SkImageDecoder();
|
|
|
|
// helper function for decoders to handle the (common) case where there is only
|
|
// once choice available in the image file.
|
|
bool chooseFromOneChoice(SkBitmap::Config config, int width, int height) const;
|
|
|
|
/* Helper for subclasses. Call this to allocate the pixel memory given the bitmap's
|
|
width/height/rowbytes/config. Returns true on success. This method handles checking
|
|
for an optional Allocator.
|
|
*/
|
|
bool allocPixelRef(SkBitmap*, SkColorTable*) const;
|
|
|
|
private:
|
|
Peeker* fPeeker;
|
|
Chooser* fChooser;
|
|
SkBitmap::Allocator* fAllocator;
|
|
int fSampleSize;
|
|
bool fDitherImage;
|
|
mutable bool fShouldCancelDecode;
|
|
|
|
// illegal
|
|
SkImageDecoder(const SkImageDecoder&);
|
|
SkImageDecoder& operator=(const SkImageDecoder&);
|
|
};
|
|
|
|
/** Calling newDecoder with a stream returns a new matching imagedecoder
|
|
instance, or NULL if none can be found. The caller must manage its ownership
|
|
of the stream as usual, calling unref() when it is done, as the returned
|
|
decoder may have called ref() (and if so, the decoder is responsible for
|
|
balancing its ownership when it is destroyed).
|
|
*/
|
|
class SkImageDecoderFactory : public SkRefCnt {
|
|
public:
|
|
virtual SkImageDecoder* newDecoder(SkStream*) = 0;
|
|
};
|
|
|
|
class SkDefaultImageDecoderFactory : SkImageDecoderFactory {
|
|
public:
|
|
// calls SkImageDecoder::Factory(stream)
|
|
virtual SkImageDecoder* newDecoder(SkStream* stream) {
|
|
return SkImageDecoder::Factory(stream);
|
|
}
|
|
};
|
|
|
|
|
|
#endif
|