aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gm/cmykjpeg.cpp69
-rw-r--r--gm/gm.cpp2
-rw-r--r--gm/gm.h30
-rw-r--r--gm/gmmain.cpp35
-rw-r--r--gm/resources/CMYK.jpgbin0 -> 116536 bytes
-rw-r--r--gyp/gmslides.gypi1
-rw-r--r--gyp/images.gyp12
-rw-r--r--gyp/libjpeg.gyp13
-rw-r--r--samplecode/SampleApp.cpp54
-rw-r--r--src/images/SkImageDecoder_Factory.cpp31
-rw-r--r--src/images/SkImageDecoder_libbmp.cpp4
-rw-r--r--src/images/SkImageDecoder_libgif.cpp4
-rw-r--r--src/images/SkImageDecoder_libico.cpp5
-rw-r--r--src/images/SkImageDecoder_libjpeg.cpp70
-rw-r--r--src/images/SkImageDecoder_wbmp.cpp4
-rw-r--r--src/images/SkJpegUtility.cpp24
16 files changed, 262 insertions, 96 deletions
diff --git a/gm/cmykjpeg.cpp b/gm/cmykjpeg.cpp
new file mode 100644
index 0000000000..67d2a60451
--- /dev/null
+++ b/gm/cmykjpeg.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "gm.h"
+#include "SkCanvas.h"
+#include "SkImageDecoder.h"
+#include "SkStream.h"
+
+namespace skiagm {
+
+/** Draw a CMYK encoded jpeg - libjpeg doesn't support CMYK->RGB
+ conversion so this tests Skia's internal processing
+*/
+class CMYKJpegGM : public GM {
+public:
+ CMYKJpegGM() {
+
+ // parameters to the "decode" call
+ bool dither = false;
+ SkBitmap::Config prefConfig = SkBitmap::kARGB_8888_Config;
+
+ SkString filename(INHERITED::gResourcePath);
+ if (!filename.endsWith("/") && !filename.endsWith("\\")) {
+ filename.append("/");
+ }
+
+ filename.append("CMYK.jpg");
+
+ SkFILEStream stream(filename.c_str());
+ SkImageDecoder* codec = SkImageDecoder::Factory(&stream);
+ if (codec) {
+ stream.rewind();
+ codec->setDitherImage(dither);
+ codec->decode(&stream, &fBitmap, prefConfig,
+ SkImageDecoder::kDecodePixels_Mode);
+ }
+ }
+
+protected:
+ virtual SkString onShortName() {
+ return SkString("cmykjpeg");
+ }
+
+ virtual SkISize onISize() {
+ return make_isize(640, 480);
+ }
+
+ virtual void onDraw(SkCanvas* canvas) {
+
+ canvas->translate(20*SK_Scalar1, 20*SK_Scalar1);
+ canvas->drawBitmap(fBitmap, 0, 0);
+ }
+
+private:
+ SkBitmap fBitmap;
+
+ typedef GM INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static GM* MyFactory(void*) { return new CMYKJpegGM; }
+static GMRegistry reg(MyFactory);
+
+}
diff --git a/gm/gm.cpp b/gm/gm.cpp
index f9c0e6637f..b6f21f81ff 100644
--- a/gm/gm.cpp
+++ b/gm/gm.cpp
@@ -8,6 +8,8 @@
#include "gm.h"
using namespace skiagm;
+SkString GM::gResourcePath;
+
GM::GM() {
fBGColor = SK_ColorWHITE;
}
diff --git a/gm/gm.h b/gm/gm.h
index b0de9227f7..d75a1c17c8 100644
--- a/gm/gm.h
+++ b/gm/gm.h
@@ -18,18 +18,18 @@
#include "SkTRegistry.h"
namespace skiagm {
-
- static inline SkISize make_isize(int w, int h) {
- SkISize sz;
- sz.set(w, h);
- return sz;
- }
+
+ static inline SkISize make_isize(int w, int h) {
+ SkISize sz;
+ sz.set(w, h);
+ return sz;
+ }
class GM {
public:
GM();
virtual ~GM();
-
+
enum Flags {
kSkipPDF_Flag = 1 << 0,
kSkipPicture_Flag = 1 << 1
@@ -39,7 +39,7 @@ namespace skiagm {
void drawBackground(SkCanvas*);
void drawContent(SkCanvas*);
- SkISize getISize() { return this->onISize(); }
+ SkISize getISize() { return this->onISize(); }
const char* shortName();
uint32_t getFlags() const {
@@ -53,10 +53,16 @@ namespace skiagm {
// GM's getISize bounds.
void drawSizeBounds(SkCanvas*, SkColor);
- protected:
- virtual void onDraw(SkCanvas*) = 0;
- virtual void onDrawBackground(SkCanvas*);
- virtual SkISize onISize() = 0;
+ static void SetResourcePath(const char* resourcePath) {
+ gResourcePath = resourcePath;
+ }
+
+ protected:
+ static SkString gResourcePath;
+
+ virtual void onDraw(SkCanvas*) = 0;
+ virtual void onDrawBackground(SkCanvas*);
+ virtual SkISize onISize() = 0;
virtual SkString onShortName() = 0;
virtual uint32_t onGetFlags() const { return 0; }
diff --git a/gm/gmmain.cpp b/gm/gmmain.cpp
index 6f53ce8f7b..61095e173f 100644
--- a/gm/gmmain.cpp
+++ b/gm/gmmain.cpp
@@ -589,9 +589,9 @@ static ErrorBitfield test_picture_serialization(GM* gm,
static void usage(const char * argv0) {
SkDebugf(
- "%s [-w writePath] [-r readPath] [-d diffPath] [--noreplay]\n"
- " [--serialize] [--forceBWtext] [--nopdf] [--nodeferred]\n"
- " [--match substring] [--notexturecache]"
+ "%s [-w writePath] [-r readPath] [-d diffPath] [-i resourcePath]\n"
+ " [--noreplay] [--serialize] [--forceBWtext] [--nopdf] \n"
+ " [--nodeferred] [--match substring] [--notexturecache]"
#if SK_MESA
" [--mesagl]"
#endif
@@ -601,6 +601,7 @@ static void usage(const char * argv0) {
" readPath: directory to read reference images from;\n"
" reports if any pixels mismatch between reference and new images\n");
SkDebugf(" diffPath: directory to write difference images in.\n");
+ SkDebugf(" resourcePath: directory that stores image resources.\n");
SkDebugf(" --noreplay: do not exercise SkPicture replay.\n");
SkDebugf(
" --serialize: exercise SkPicture serialization & deserialization.\n");
@@ -660,6 +661,7 @@ int main(int argc, char * const argv[]) {
const char* writePath = NULL; // if non-null, where we write the originals
const char* readPath = NULL; // if non-null, were we read from to compare
const char* diffPath = NULL; // if non-null, where we write our diffs (from compare)
+ const char* resourcePath = NULL;// if non-null, where we read from for image resources
SkTDArray<const char*> fMatches;
@@ -688,6 +690,11 @@ int main(int argc, char * const argv[]) {
if (argv < stop && **argv) {
diffPath = *argv;
}
+ } else if (strcmp(*argv, "-i") == 0) {
+ argv++;
+ if (argv < stop && **argv) {
+ resourcePath = *argv;
+ }
} else if (strcmp(*argv, "--forceBWtext") == 0) {
gForceBWtext = true;
} else if (strcmp(*argv, "--noreplay") == 0) {
@@ -709,17 +716,19 @@ int main(int argc, char * const argv[]) {
useMesa = true;
#endif
} else if (strcmp(*argv, "--notexturecache") == 0) {
- disableTextureCache = true;
+ disableTextureCache = true;
} else {
- usage(commandName);
- return -1;
+ usage(commandName);
+ return -1;
}
}
if (argv != stop) {
- usage(commandName);
- return -1;
+ usage(commandName);
+ return -1;
}
+ GM::SetResourcePath(resourcePath);
+
int maxW = -1;
int maxH = -1;
Iter iter;
@@ -763,6 +772,10 @@ int main(int argc, char * const argv[]) {
fprintf(stderr, "writing to %s\n", writePath);
}
+ if (resourcePath) {
+ fprintf(stderr, "reading resources from %s\n", resourcePath);
+ }
+
// Accumulate success of all tests.
int testsRun = 0;
int testsPassed = 0;
@@ -828,10 +841,10 @@ int main(int argc, char * const argv[]) {
if (doDeferred && !testErrors &&
(kGPU_Backend == gRec[i].fBackend ||
- kRaster_Backend == gRec[i].fBackend)) {
+ kRaster_Backend == gRec[i].fBackend)) {
testErrors |= test_deferred_drawing(gm, gRec[i],
- forwardRenderedBitmap,
- diffPath, gGrContext, rt.get());
+ forwardRenderedBitmap,
+ diffPath, gGrContext, rt.get());
}
if ((ERROR_NONE == testErrors) && doReplay &&
diff --git a/gm/resources/CMYK.jpg b/gm/resources/CMYK.jpg
new file mode 100644
index 0000000000..04ed9859dd
--- /dev/null
+++ b/gm/resources/CMYK.jpg
Binary files differ
diff --git a/gyp/gmslides.gypi b/gyp/gmslides.gypi
index ec223fb07b..601aa88e85 100644
--- a/gyp/gmslides.gypi
+++ b/gyp/gmslides.gypi
@@ -9,6 +9,7 @@
'../gm/bitmapfilters.cpp',
'../gm/bitmapscroll.cpp',
'../gm/blurs.cpp',
+ '../gm/cmykjpeg.cpp',
'../gm/colormatrix.cpp',
'../gm/complexclip.cpp',
'../gm/complexclip2.cpp',
diff --git a/gyp/images.gyp b/gyp/images.gyp
index a93ba065e8..d0b5c1a715 100644
--- a/gyp/images.gyp
+++ b/gyp/images.gyp
@@ -5,6 +5,7 @@
'type': 'static_library',
'dependencies': [
'utils.gyp:utils',
+ 'libjpeg.gyp:libjpeg',
],
'include_dirs': [
'../include/config',
@@ -33,6 +34,7 @@
'../src/images/SkImageDecoder_libgif.cpp',
'../src/images/SkImageDecoder_libico.cpp',
'../src/images/SkImageDecoder_libpng.cpp',
+ '../src/images/SkImageDecoder_libjpeg.cpp',
'../src/images/SkImageDecoder_wbmp.cpp',
'../src/images/SkImageEncoder.cpp',
'../src/images/SkImageEncoder_Factory.cpp',
@@ -53,14 +55,11 @@
'conditions': [
[ 'skia_os == "win"', {
'sources!': [
- '../include/images/SkJpegUtility.h',
-
'../src/images/SkFDStream.cpp',
'../src/images/SkImageDecoder_Factory.cpp',
'../src/images/SkImageDecoder_libgif.cpp',
'../src/images/SkImageDecoder_libpng.cpp',
'../src/images/SkImageEncoder_Factory.cpp',
- '../src/images/SkJpegUtility.cpp',
'../src/images/SkMovie_gif.cpp',
],
'link_settings': {
@@ -75,13 +74,10 @@
}],
[ 'skia_os == "mac"', {
'sources!': [
- '../include/images/SkJpegUtility.h',
-
'../src/images/SkImageDecoder_Factory.cpp',
'../src/images/SkImageDecoder_libpng.cpp',
'../src/images/SkImageDecoder_libgif.cpp',
'../src/images/SkImageEncoder_Factory.cpp',
- '../src/images/SkJpegUtility.cpp',
'../src/images/SkMovie_gif.cpp',
],
},{ #else if skia_os != mac
@@ -91,10 +87,7 @@
}],
[ 'skia_os in ["linux", "freebsd", "openbsd", "solaris"]', {
'sources!': [
- '../include/images/SkJpegUtility.h',
-
'../src/images/SkImageDecoder_libgif.cpp',
- '../src/images/SkJpegUtility.cpp',
'../src/images/SkMovie_gif.cpp',
],
# libpng stuff:
@@ -113,7 +106,6 @@
}],
[ 'skia_os == "android"', {
'sources!': [
- '../src/images/SkJpegUtility.cpp',
],
'dependencies': [
'android_system.gyp:gif',
diff --git a/gyp/libjpeg.gyp b/gyp/libjpeg.gyp
index 4826f48dab..d628f66464 100644
--- a/gyp/libjpeg.gyp
+++ b/gyp/libjpeg.gyp
@@ -13,6 +13,19 @@
'dependencies': [
'../third_party/externals/libjpeg/libjpeg.gyp:libjpeg',
],
+
+ 'conditions': [
+ [ 'os_posix != 1 or OS == "mac"', {
+ # need to set include path when using our own version
+ 'direct_dependent_settings': {
+ 'include_dirs': [
+ '../third_party/externals/libjpeg',
+ ],
+ },
+ },],
+ ],
+
+
},
],
}
diff --git a/samplecode/SampleApp.cpp b/samplecode/SampleApp.cpp
index d40a670e3a..c93bae8e57 100644
--- a/samplecode/SampleApp.cpp
+++ b/samplecode/SampleApp.cpp
@@ -590,7 +590,44 @@ static inline SampleWindow::DeviceType cycle_devicetype(SampleWindow::DeviceType
return gCT[ct];
}
+static void usage(const char * argv0) {
+ SkDebugf("%s [sampleName] [-i resourcePath]\n", argv0);
+ SkDebugf(" sampleName: sample at which to start.\n");
+ SkDebugf(" resourcePath: directory that stores image resources.\n");
+}
+
SampleWindow::SampleWindow(void* hwnd, int argc, char** argv, DeviceManager* devManager) : INHERITED(hwnd) {
+
+ const char* resourcePath = NULL;
+ fCurrIndex = -1;
+
+ const char* const commandName = argv[0];
+ char* const* stop = argv + argc;
+ for (++argv; argv < stop; ++argv) {
+ if (strcmp(*argv, "-i") == 0) {
+ argv++;
+ if (argv < stop && **argv) {
+ resourcePath = *argv;
+ }
+ } else {
+ fCurrIndex = findByTitle(*argv);
+ if (fCurrIndex < 0) {
+ fprintf(stderr, "Unknown sample \"%s\"\n", *argv);
+ }
+ }
+ }
+
+ if (fCurrIndex < 0) {
+ SkString title;
+ if (readTitleFromPrefs(&title)) {
+ fCurrIndex = findByTitle(title.c_str());
+ }
+ }
+
+ if (fCurrIndex < 0) {
+ fCurrIndex = 0;
+ }
+
gSampleWindow = this;
#ifdef PIPE_FILE
@@ -694,6 +731,8 @@ SampleWindow::SampleWindow(void* hwnd, int argc, char** argv, DeviceManager* dev
this->setVisibleP(true);
this->setClipToBounds(false);
+ skiagm::GM::SetResourcePath(resourcePath);
+
SkGMRegistyToSampleRegistry();
{
const SkViewRegister* reg = SkViewRegister::Head();
@@ -702,22 +741,7 @@ SampleWindow::SampleWindow(void* hwnd, int argc, char** argv, DeviceManager* dev
reg = reg->next();
}
}
- fCurrIndex = 0;
- if (argc > 1) {
- fCurrIndex = findByTitle(argv[1]);
- if (fCurrIndex < 0) {
- fprintf(stderr, "Unknown sample \"%s\"\n", argv[1]);
- }
- } else {
- SkString title;
- if (readTitleFromPrefs(&title)) {
- fCurrIndex = findByTitle(title.c_str());
- }
- }
- if (fCurrIndex < 0) {
- fCurrIndex = 0;
- }
this->loadView((*fSamples[fCurrIndex])());
fPDFData = NULL;
diff --git a/src/images/SkImageDecoder_Factory.cpp b/src/images/SkImageDecoder_Factory.cpp
index f3cb120a47..048ed21a69 100644
--- a/src/images/SkImageDecoder_Factory.cpp
+++ b/src/images/SkImageDecoder_Factory.cpp
@@ -12,6 +12,37 @@
#include "SkStream.h"
#include "SkTRegistry.h"
+//extern SkImageDecoder* sk_libbmp_dfactory(SkStream*);
+//extern SkImageDecoder* sk_libgif_dfactory(SkStream*);
+//extern SkImageDecoder* sk_libico_dfactory(SkStream*);
+extern SkImageDecoder* sk_libjpeg_dfactory(SkStream*);
+//extern SkImageDecoder* sk_libpng_dfactory(SkStream*);
+//extern SkImageDecoder* sk_wbmp_dfactory(SkStream*);
+
+// To get the various image decoding classes to register themselves
+// pre-main we need to ensure they are linked into the application.
+// Ultimately we need to move to using DLLs rather than tightly
+// coupling the factory with the file format classes.
+void ForceLinking()
+{
+ SkImageDecoder* codec = NULL;
+
+ // TODO: rather than force the linking here expose a
+ // "Sk*ImageDecoderCreate" function for each codec
+ // and let the app add these calls to force the linking.
+ // Besides decoupling the codecs from the factory this
+ // will also give the app the ability to circumvent the
+ // factory and explicitly create a decoder w/o reaching
+ // into Skia's guts
+
+// codec = sk_libbmp_dfactory(NULL);
+// codec = sk_libgif_dfactory(NULL);
+// codec = sk_libico_dfactory(NULL);
+ codec = sk_libjpeg_dfactory(NULL);
+// codec = sk_libpng_dfactory(NULL);
+// codec = sk_wbmp_dfactory(NULL);
+}
+
typedef SkTRegistry<SkImageDecoder*, SkStream*> DecodeReg;
// N.B. You can't use "DecodeReg::gHead here" due to complex C++
diff --git a/src/images/SkImageDecoder_libbmp.cpp b/src/images/SkImageDecoder_libbmp.cpp
index b5e49e8cda..8683e21a7f 100644
--- a/src/images/SkImageDecoder_libbmp.cpp
+++ b/src/images/SkImageDecoder_libbmp.cpp
@@ -27,7 +27,7 @@ protected:
virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode mode);
};
-static SkImageDecoder* Factory(SkStream* stream) {
+SkImageDecoder* sk_libbmp_dfactory(SkStream* stream) {
static const char kBmpMagic[] = { 'B', 'M' };
size_t len = stream->getLength();
@@ -41,7 +41,7 @@ static SkImageDecoder* Factory(SkStream* stream) {
return NULL;
}
-static SkTRegistry<SkImageDecoder*, SkStream*> gReg(Factory);
+static SkTRegistry<SkImageDecoder*, SkStream*> gReg(sk_libbmp_dfactory);
///////////////////////////////////////////////////////////////////////////////
diff --git a/src/images/SkImageDecoder_libgif.cpp b/src/images/SkImageDecoder_libgif.cpp
index 7a451a0560..3bc33c3d07 100644
--- a/src/images/SkImageDecoder_libgif.cpp
+++ b/src/images/SkImageDecoder_libgif.cpp
@@ -330,7 +330,7 @@ DONE:
#include "SkTRegistry.h"
-static SkImageDecoder* Factory(SkStream* stream) {
+static SkImageDecoder* sk_libgif_dfactory(SkStream* stream) {
char buf[GIF_STAMP_LEN];
if (stream->read(buf, GIF_STAMP_LEN) == GIF_STAMP_LEN) {
if (memcmp(GIF_STAMP, buf, GIF_STAMP_LEN) == 0 ||
@@ -342,4 +342,4 @@ static SkImageDecoder* Factory(SkStream* stream) {
return NULL;
}
-static SkTRegistry<SkImageDecoder*, SkStream*> gReg(Factory);
+static SkTRegistry<SkImageDecoder*, SkStream*> gReg(sk_libgif_dfactory);
diff --git a/src/images/SkImageDecoder_libico.cpp b/src/images/SkImageDecoder_libico.cpp
index bb6bc95188..226c84af54 100644
--- a/src/images/SkImageDecoder_libico.cpp
+++ b/src/images/SkImageDecoder_libico.cpp
@@ -24,7 +24,6 @@ protected:
virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode);
};
-SkImageDecoder* SkCreateICOImageDecoder();
SkImageDecoder* SkCreateICOImageDecoder() {
return new SkICOImageDecoder;
}
@@ -371,7 +370,7 @@ static void editPixelBit32(const int pixelNo, const unsigned char* buf,
#include "SkTRegistry.h"
-static SkImageDecoder* Factory(SkStream* stream) {
+SkImageDecoder* sk_libico_dfactory(SkStream* stream) {
// Check to see if the first four bytes are 0,0,1,0
// FIXME: Is that required and sufficient?
SkAutoMalloc autoMal(4);
@@ -386,5 +385,5 @@ static SkImageDecoder* Factory(SkStream* stream) {
return SkNEW(SkICOImageDecoder);
}
-static SkTRegistry<SkImageDecoder*, SkStream*> gReg(Factory);
+static SkTRegistry<SkImageDecoder*, SkStream*> gReg(sk_libico_dfactory);
diff --git a/src/images/SkImageDecoder_libjpeg.cpp b/src/images/SkImageDecoder_libjpeg.cpp
index 77d383af97..5cb45a2e0a 100644
--- a/src/images/SkImageDecoder_libjpeg.cpp
+++ b/src/images/SkImageDecoder_libjpeg.cpp
@@ -146,6 +146,29 @@ static bool return_false(const jpeg_decompress_struct& cinfo,
return false; // must always return false
}
+// Convert a scanline of CMYK samples to RGBX in place. Note that this
+// method moves the "scanline" pointer in its processing
+static void convert_CMYK_to_RGB(uint8_t* scanline, unsigned int width) {
+ // At this point we've received CMYK pixels from libjpeg. We
+ // perform a crude conversion to RGB (based on the formulae
+ // from easyrgb.com):
+ // CMYK -> CMY
+ // C = ( C * (1 - K) + K ) // for each CMY component
+ // CMY -> RGB
+ // R = ( 1 - C ) * 255 // for each RGB component
+ // Unfortunately we are seeing inverted CMYK so all the original terms
+ // are 1-. This yields:
+ // CMYK -> CMY
+ // C = ( (1-C) * (1 - (1-K) + (1-K) ) -> C = 1 - C*K
+ // The conversion from CMY->RGB remains the same
+ for (unsigned int x = 0; x < width; ++x, scanline += 4) {
+ scanline[0] = SkMulDiv255Round(scanline[0], scanline[3]);
+ scanline[1] = SkMulDiv255Round(scanline[1], scanline[3]);
+ scanline[2] = SkMulDiv255Round(scanline[2], scanline[3]);
+ scanline[3] = 255;
+ }
+}
+
bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
#ifdef TIME_DECODE
AutoTimeMillis atm("JPEG Decode");
@@ -156,7 +179,7 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
jpeg_decompress_struct cinfo;
skjpeg_error_mgr sk_err;
- skjpeg_source_mgr sk_stream(stream, this);
+ skjpeg_source_mgr sk_stream(stream, this, false);
cinfo.err = jpeg_std_error(&sk_err);
sk_err.error_exit = skjpeg_error_exit;
@@ -201,7 +224,14 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
cinfo.do_block_smoothing = 0;
/* default format is RGB */
- cinfo.out_color_space = JCS_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 {
+ cinfo.out_color_space = JCS_RGB;
+ }
SkBitmap::Config config = this->getPrefConfig(k32Bit_SrcDepth, false);
// only these make sense for jpegs
@@ -213,9 +243,9 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
#ifdef ANDROID_RGB
cinfo.dither_mode = JDITHER_NONE;
- if (config == SkBitmap::kARGB_8888_Config) {
+ if (SkBitmap::kARGB_8888_Config == config && JCS_CMYK != cinfo.out_color_space) {
cinfo.out_color_space = JCS_RGBA_8888;
- } else if (config == SkBitmap::kRGB_565_Config) {
+ } else if (SkBitmap::kRGB_565_Config == config && JCS_CMYK != cinfo.out_color_space) {
cinfo.out_color_space = JCS_RGB_565;
if (this->getDitherImage()) {
cinfo.dither_mode = JDITHER_ORDERED;
@@ -300,10 +330,13 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
return true;
}
#endif
-
+
// check for supported formats
SkScaledBitmapSampler::SrcConfig sc;
- if (3 == cinfo.out_color_components && JCS_RGB == cinfo.out_color_space) {
+ if (JCS_CMYK == cinfo.out_color_space) {
+ // In this case we will manually convert the CMYK values to RGB
+ sc = SkScaledBitmapSampler::kRGBX;
+ } else if (3 == cinfo.out_color_components && JCS_RGB == cinfo.out_color_space) {
sc = SkScaledBitmapSampler::kRGB;
#ifdef ANDROID_RGB
} else if (JCS_RGBA_8888 == cinfo.out_color_space) {
@@ -322,7 +355,7 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
sampleSize);
bm->setConfig(config, sampler.scaledWidth(), sampler.scaledHeight());
- // jpegs are always opauqe (i.e. have no per-pixel alpha)
+ // jpegs are always opaque (i.e. have no per-pixel alpha)
bm->setIsOpaque(true);
if (SkImageDecoder::kDecodeBounds_Mode == mode) {
@@ -332,12 +365,13 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
return return_false(cinfo, *bm, "allocPixelRef");
}
- SkAutoLockPixels alp(*bm);
+ SkAutoLockPixels alp(*bm);
if (!sampler.begin(bm, sc, this->getDitherImage())) {
return return_false(cinfo, *bm, "sampler.begin");
}
- uint8_t* srcRow = (uint8_t*)srcStorage.alloc(cinfo.output_width * 4);
+ // The CMYK work-around relies on 4 components per pixel here
+ uint8_t* srcRow = (uint8_t*)srcStorage.reset(cinfo.output_width * 4);
// Possibly skip initial rows [sampler.srcY0]
if (!skip_src_rows(&cinfo, srcRow, sampler.srcY0())) {
@@ -354,7 +388,11 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
if (this->shouldCancelDecode()) {
return return_false(cinfo, *bm, "shouldCancelDecode");
}
-
+
+ if (JCS_CMYK == cinfo.out_color_space) {
+ convert_CMYK_to_RGB(srcRow, cinfo.output_width);
+ }
+
sampler.next(srcRow);
if (bm->height() - 1 == y) {
// we're done
@@ -593,7 +631,7 @@ protected:
jpeg_start_compress(&cinfo, TRUE);
const int width = bm.width();
- uint8_t* oneRowP = (uint8_t*)oneRow.alloc(width * 3);
+ uint8_t* oneRowP = (uint8_t*)oneRow.reset(width * 3);
const SkPMColor* colors = ctLocker.lockColors(bm);
const void* srcRow = bm.getPixels();
@@ -618,7 +656,7 @@ protected:
#include "SkTRegistry.h"
-static SkImageDecoder* DFactory(SkStream* stream) {
+SkImageDecoder* sk_libjpeg_dfactory(SkStream* stream) {
static const char gHeader[] = { 0xFF, 0xD8, 0xFF };
static const size_t HEADER_SIZE = sizeof(gHeader);
@@ -634,9 +672,11 @@ static SkImageDecoder* DFactory(SkStream* stream) {
return SkNEW(SkJPEGImageDecoder);
}
-static SkImageEncoder* EFactory(SkImageEncoder::Type t) {
+static SkImageEncoder* sk_libjpeg_efactory(SkImageEncoder::Type t) {
return (SkImageEncoder::kJPEG_Type == t) ? SkNEW(SkJPEGImageEncoder) : NULL;
}
-static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(DFactory);
-static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(EFactory);
+
+static SkTRegistry<SkImageDecoder*, SkStream*> gDReg(sk_libjpeg_dfactory);
+static SkTRegistry<SkImageEncoder*, SkImageEncoder::Type> gEReg(sk_libjpeg_efactory);
+
diff --git a/src/images/SkImageDecoder_wbmp.cpp b/src/images/SkImageDecoder_wbmp.cpp
index a7d910f0bc..262cf547cd 100644
--- a/src/images/SkImageDecoder_wbmp.cpp
+++ b/src/images/SkImageDecoder_wbmp.cpp
@@ -151,7 +151,7 @@ bool SkWBMPImageDecoder::onDecode(SkStream* stream, SkBitmap* decodedBitmap,
#include "SkTRegistry.h"
-static SkImageDecoder* Factory(SkStream* stream) {
+SkImageDecoder* sk_wbmp_dfactory(SkStream* stream) {
wbmp_head head;
if (head.init(stream)) {
@@ -160,5 +160,5 @@ static SkImageDecoder* Factory(SkStream* stream) {
return NULL;
}
-static SkTRegistry<SkImageDecoder*, SkStream*> gReg(Factory);
+static SkTRegistry<SkImageDecoder*, SkStream*> gReg(sk_wbmp_dfactory);
diff --git a/src/images/SkJpegUtility.cpp b/src/images/SkJpegUtility.cpp
index aa5237fa0b..e28c51229f 100644
--- a/src/images/SkJpegUtility.cpp
+++ b/src/images/SkJpegUtility.cpp
@@ -14,26 +14,9 @@ static void sk_init_source(j_decompress_ptr cinfo) {
skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src;
src->next_input_byte = (const JOCTET*)src->fBuffer;
src->bytes_in_buffer = 0;
- src->current_offset = 0;
src->fStream->rewind();
}
-static boolean sk_seek_input_data(j_decompress_ptr cinfo, long byte_offset) {
- skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src;
-
- if (byte_offset > src->current_offset) {
- (void)src->fStream->skip(byte_offset - src->current_offset);
- } else {
- src->fStream->rewind();
- (void)src->fStream->skip(byte_offset);
- }
-
- src->current_offset = byte_offset;
- src->next_input_byte = (const JOCTET*)src->fBuffer;
- src->bytes_in_buffer = 0;
- return TRUE;
-}
-
static boolean sk_fill_input_buffer(j_decompress_ptr cinfo) {
skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src;
if (src->fDecoder != NULL && src->fDecoder->shouldCancelDecode()) {
@@ -46,7 +29,6 @@ static boolean sk_fill_input_buffer(j_decompress_ptr cinfo) {
return FALSE;
}
- src->current_offset += bytes;
src->next_input_byte = (const JOCTET*)src->fBuffer;
src->bytes_in_buffer = bytes;
return TRUE;
@@ -64,7 +46,6 @@ static void sk_skip_input_data(j_decompress_ptr cinfo, long num_bytes) {
cinfo->err->error_exit((j_common_ptr)cinfo);
return;
}
- src->current_offset += bytes;
bytesToSkip -= bytes;
}
src->next_input_byte = (const JOCTET*)src->fBuffer;
@@ -96,9 +77,7 @@ static void sk_term_source(j_decompress_ptr /*cinfo*/) {}
static void skmem_init_source(j_decompress_ptr cinfo) {
skjpeg_source_mgr* src = (skjpeg_source_mgr*)cinfo->src;
src->next_input_byte = (const JOCTET*)src->fMemoryBase;
- src->start_input_byte = (const JOCTET*)src->fMemoryBase;
src->bytes_in_buffer = src->fMemoryBaseSize;
- src->current_offset = src->fMemoryBaseSize;
}
static boolean skmem_fill_input_buffer(j_decompress_ptr cinfo) {
@@ -127,8 +106,6 @@ skjpeg_source_mgr::skjpeg_source_mgr(SkStream* stream, SkImageDecoder* decoder,
bool ownStream) : fStream(stream) {
fDecoder = decoder;
const void* baseAddr = stream->getMemoryBase();
- size_t bufferSize = 4096;
- size_t len;
fMemoryBase = NULL;
fUnrefStream = ownStream;
fMemoryBaseSize = 0;
@@ -138,7 +115,6 @@ skjpeg_source_mgr::skjpeg_source_mgr(SkStream* stream, SkImageDecoder* decoder,
skip_input_data = sk_skip_input_data;
resync_to_restart = sk_resync_to_restart;
term_source = sk_term_source;
- seek_input_data = sk_seek_input_data;
// SkDebugf("**************** use memorybase %p %d\n", fMemoryBase, fMemoryBaseSize);
}