Chooser* getChooser() const { return fChooser; }
Chooser* setChooser(Chooser*);
- /** This optional table describes the caller's preferred config based on
+ /**
+ @Deprecated. Use the struct version instead.
+
+ This optional table describes the caller's preferred config based on
information about the src data. For this table, the src attributes are
described in terms of depth (index (8), 16, 32/24) and if there is
per-pixel alpha. These inputs combine to create an index into the
pref[] table, which contains the caller's preferred config for that
input, or kNo_Config if there is no preference.
- To specify no preferrence, call setPrefConfigTable(NULL), which is
+ To specify no preference, call setPrefConfigTable(NULL), which is
the default.
Note, it is still at the discretion of the codec as to what output
*/
void setPrefConfigTable(const SkBitmap::Config pref[6]);
+ /**
+ * Optional table describing the caller's preferred config based on
+ * information about the src data. Each field should be set to the
+ * preferred config for a src described in the name of the field. The
+ * src attributes are described in terms of depth (8-index,
+ * 8bit-grayscale, or 8-bits/component) and whether there is per-pixel
+ * alpha (does not apply to grayscale). If the caller has no preference
+ * for a particular src type, its slot should be set to kNo_Config.
+ *
+ * NOTE ABOUT PREFERRED CONFIGS:
+ * If a config is preferred, either using a pref table or as a parameter
+ * to some flavor of decode, it is still at the discretion of the codec
+ * as to what output config is actually returned, as it may not be able
+ * to support the caller's preference.
+ *
+ * If a bitmap is decoded into SkBitmap::A8_Config, the resulting bitmap
+ * will either be a conversion of the grayscale in the case of a
+ * grayscale source or the alpha channel in the case of a source with
+ * an alpha channel.
+ */
+ struct PrefConfigTable {
+ SkBitmap::Config fPrefFor_8Index_NoAlpha_src;
+ SkBitmap::Config fPrefFor_8Index_YesAlpha_src;
+ SkBitmap::Config fPrefFor_8Gray_src;
+ SkBitmap::Config fPrefFor_8bpc_NoAlpha_src;
+ SkBitmap::Config fPrefFor_8bpc_YesAlpha_src;
+ };
+
+ /**
+ * Set an optional table for specifying the caller's preferred config
+ * based on information about the src data.
+ *
+ * The default is no preference, which will assume the config set by
+ * decode is preferred.
+ */
+ void setPrefConfigTable(const PrefConfigTable&);
+
+ /**
+ * Do not use a PrefConfigTable to determine the output config. This
+ * is the default, so there is no need to call unless a PrefConfigTable
+ * was previously set.
+ */
+ void resetPrefConfigTable() { fUsePrefTable = false; }
+
SkBitmap::Allocator* getAllocator() const { return fAllocator; }
SkBitmap::Allocator* setAllocator(SkBitmap::Allocator*);
/** 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.
+ @param prefConfig If the PrefConfigTable is not set, prefer this config.
+ See NOTE ABOUT PREFERRED CONFIGS.
@param format On success, if format is non-null, it is set to the format
of the decoded file. On failure it is ignored.
/** 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.
+ @param prefConfig If the PrefConfigTable is not set, prefer this config.
+ See NOTE ABOUT PREFERRED CONFIGS.
@param format On success, if format is non-null, it is set to the format
of the decoded buffer. On failure it is ignored.
/** 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.
+ @param prefConfig If the PrefConfigTable is not set, prefer this config.
+ See NOTE ABOUT PREFERRED CONFIGS.
@param format On success, if format is non-null, it is set to the format
of the decoded stream. On failure it is ignored.
*/
bool allocPixelRef(SkBitmap*, SkColorTable*) const;
+ /**
+ * The raw data of the src image.
+ */
enum SrcDepth {
+ // Color-indexed.
kIndex_SrcDepth,
- k16Bit_SrcDepth,
- k32Bit_SrcDepth
+ // Grayscale in 8 bits.
+ k8BitGray_SrcDepth,
+ // 8 bits per component. Used for 24 bit if there is no alpha.
+ k32Bit_SrcDepth,
};
/** The subclass, inside onDecode(), calls this to determine the config of
the returned bitmap. SrcDepth and hasAlpha reflect the raw data of the
SkBitmap::Allocator* fAllocator;
int fSampleSize;
SkBitmap::Config fDefaultPref; // use if fUsePrefTable is false
- SkBitmap::Config fPrefTable[6]; // use if fUsePrefTable is true
+ PrefConfigTable fPrefTable; // use if fUsePrefTable is true
bool fDitherImage;
bool fUsePrefTable;
mutable bool fShouldCancelDecode;
/* this gives another few percents */
cinfo.do_block_smoothing = 0;
+ SrcDepth srcDepth = k32Bit_SrcDepth;
/* default format is RGB */
if (cinfo.jpeg_color_space == JCS_CMYK) {
// libjpeg cannot convert from CMYK to RGB - here we set up
// so libjpeg will give us CMYK samples back and we will
// later manually convert them to RGB
cinfo.out_color_space = JCS_CMYK;
+ } else if (cinfo.jpeg_color_space == JCS_GRAYSCALE) {
+ cinfo.out_color_space = JCS_GRAYSCALE;
+ srcDepth = k8BitGray_SrcDepth;
} else {
cinfo.out_color_space = JCS_RGB;
}
- SkBitmap::Config config = this->getPrefConfig(k32Bit_SrcDepth, false);
+ SkBitmap::Config config = this->getPrefConfig(srcDepth, false);
// only these make sense for jpegs
- if (config != SkBitmap::kARGB_8888_Config &&
- config != SkBitmap::kARGB_4444_Config &&
- config != SkBitmap::kRGB_565_Config) {
+ if (SkBitmap::kA8_Config == config) {
+ if (cinfo.jpeg_color_space != JCS_GRAYSCALE) {
+ // Converting from a non grayscale image to A8 is
+ // not currently supported.
+ config = SkBitmap::kARGB_8888_Config;
+ // Change the output from jpeg back to RGB.
+ cinfo.out_color_space = JCS_RGB;
+ }
+ } else if (config != SkBitmap::kARGB_8888_Config &&
+ config != SkBitmap::kARGB_4444_Config &&
+ config != SkBitmap::kRGB_565_Config) {
config = SkBitmap::kARGB_8888_Config;
}
return false;
}
+// A8
+static bool Sample_Gray_DA8(void* SK_RESTRICT dstRow,
+ const uint8_t* SK_RESTRICT src,
+ int width, int deltaSrc, int,
+ const SkPMColor[]) {
+ memcpy(dstRow, src, width);
+ return true;
+}
+
// 8888 Unpremul
static bool Sample_Gray_D8888_Unpremul(void* SK_RESTRICT dstRow,
NULL, NULL,
Sample_Index_DI, Sample_Index_DI,
NULL, NULL,
+ // A8
+ Sample_Gray_DA8, Sample_Gray_DA8,
+ NULL, NULL,
+ NULL, NULL,
+ NULL, NULL,
+ NULL, NULL,
// 8888 Unpremul (no dither distinction)
Sample_Gray_D8888_Unpremul, Sample_Gray_D8888_Unpremul,
Sample_RGBx_D8888, Sample_RGBx_D8888,
};
// The jump between dst configs in the table
static const int gProcDstConfigSpan = 10;
- SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gProcs) == 5 * gProcDstConfigSpan,
+ SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gProcs) == 6 * gProcDstConfigSpan,
gProcs_has_the_wrong_number_of_entries);
fCTable = ctable;
case SkBitmap::kIndex8_Config:
index += 3 * gProcDstConfigSpan;
break;
+ case SkBitmap::kA8_Config:
+ index += 4 * gProcDstConfigSpan;
+ break;
default:
return false;
}
if (dst->config() != SkBitmap::kARGB_8888_Config) {
return false;
}
- index += 4 * gProcDstConfigSpan;
+ index += 5 * gProcDstConfigSpan;
}
fRowProc = gProcs[index];
}
}
-static void test_imageDecodingTests(skiatest::Reporter* reporter) {
+// Create a fake ImageDecoder to test setPrefConfigTable for
+// backwards compatibility.
+class PrefConfigTestingImageDecoder : public SkImageDecoder {
+public:
+ void testPrefConfigTable(skiatest::Reporter* reporter) {
+ // Arbitrary list of Configs. The important thing about
+ // the list is that each one is different, so we can test
+ // to make sure the correct config is chosen.
+ const SkBitmap::Config configs[] = {
+ SkBitmap::kA1_Config,
+ SkBitmap::kA8_Config,
+ SkBitmap::kIndex8_Config,
+ SkBitmap::kRGB_565_Config,
+ SkBitmap::kARGB_4444_Config,
+ SkBitmap::kARGB_8888_Config,
+ };
+ this->setPrefConfigTable(configs);
+ REPORTER_ASSERT(reporter, configs[0] == this->getPrefConfig(kIndex_SrcDepth, false));
+ REPORTER_ASSERT(reporter, configs[1] == this->getPrefConfig(kIndex_SrcDepth, true));
+ REPORTER_ASSERT(reporter, configs[4] == this->getPrefConfig(k32Bit_SrcDepth, false));
+ REPORTER_ASSERT(reporter, configs[5] == this->getPrefConfig(k32Bit_SrcDepth, true));
+ }
+
+protected:
+ virtual bool onDecode(SkStream*, SkBitmap* bitmap, Mode) SK_OVERRIDE {
+ return false;
+ }
+};
+
+static void test_pref_config_table(skiatest::Reporter* reporter) {
+ PrefConfigTestingImageDecoder decoder;
+ decoder.testPrefConfigTable(reporter);
+}
+
+static void test_unpremul(skiatest::Reporter* reporter) {
// This test cannot run if there is no resource path.
SkString resourcePath = skiatest::Test::GetResourcePath();
if (resourcePath.isEmpty()) {
}
}
+static void test_imageDecodingTests(skiatest::Reporter* reporter) {
+ test_unpremul(reporter);
+ test_pref_config_table(reporter);
+}
+
#include "TestClassDef.h"
DEFINE_TESTCLASS("ImageDecoding", ImageDecodingTestClass,
test_imageDecodingTests)