add encodeData() to SkImageEncoder, and add encoding to SkImage
BUG=
R=scroggo@google.com
Review URL: https://codereview.chromium.org/15002004
git-svn-id: http://skia.googlecode.com/svn/trunk@9193 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/core/SkImage.h b/include/core/SkImage.h
index e6ac682..9b7dfd1 100644
--- a/include/core/SkImage.h
+++ b/include/core/SkImage.h
@@ -21,8 +21,6 @@
// need for TileMode
#include "SkShader.h"
-////// EXPERIMENTAL
-
/**
* SkImage is an abstraction for drawing a rectagle of pixels, though the
* particular type of image could be actually storing its data on the GPU, or
@@ -84,6 +82,24 @@
void draw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*);
+ enum EncodeType {
+ kBMP_EncodeType,
+ kGIF_EncodeType,
+ kICO_EncodeType,
+ kJPEG_EncodeType,
+ kPNG_EncodeType,
+ kWBMP_EncodeType,
+ kWEBP_EncodeType,
+ };
+ /**
+ * Encode the image's pixels and return the result as a new SkData, which
+ * the caller must manage (i.e. call unref() when they are done).
+ *
+ * If the image type cannot be encoded, or the requested encoder type is
+ * not supported, this will return NULL.
+ */
+ SkData* encode(EncodeType t = kPNG_EncodeType, int quality = 80) const;
+
protected:
SkImage(int width, int height) :
fWidth(width),
diff --git a/include/images/SkImageEncoder.h b/include/images/SkImageEncoder.h
index 2965c88..b990aff 100644
--- a/include/images/SkImageEncoder.h
+++ b/include/images/SkImageEncoder.h
@@ -11,6 +11,7 @@
#include "SkTypes.h"
class SkBitmap;
+class SkData;
class SkWStream;
class SkImageEncoder {
@@ -35,25 +36,28 @@
};
/**
+ * Encode bitmap 'bm', returning the results in an SkData, at quality level
+ * 'quality' (which can be in range 0-100). If the bitmap cannot be
+ * encoded, return null. On success, the caller is responsible for
+ * calling unref() on the data when they are finished.
+ */
+ SkData* encodeData(const SkBitmap&, int quality);
+
+ /**
* Encode bitmap 'bm' in the desired format, writing results to
* file 'file', at quality level 'quality' (which can be in range
- * 0-100).
- *
- * Calls the particular implementation's onEncode() method to
- * actually do the encoding.
+ * 0-100). Returns false on failure.
*/
bool encodeFile(const char file[], const SkBitmap& bm, int quality);
/**
* Encode bitmap 'bm' in the desired format, writing results to
* stream 'stream', at quality level 'quality' (which can be in
- * range 0-100).
- *
- * Calls the particular implementation's onEncode() method to
- * actually do the encoding.
+ * range 0-100). Returns false on failure.
*/
bool encodeStream(SkWStream* stream, const SkBitmap& bm, int quality);
+ static SkData* EncodeData(const SkBitmap&, Type, int quality);
static bool EncodeFile(const char file[], const SkBitmap&, Type,
int quality);
static bool EncodeStream(SkWStream*, const SkBitmap&, Type,
diff --git a/src/image/SkImage.cpp b/src/image/SkImage.cpp
index 1169459..13af631 100644
--- a/src/image/SkImage.cpp
+++ b/src/image/SkImage.cpp
@@ -9,6 +9,7 @@
#include "SkImagePriv.h"
#include "SkBitmap.h"
#include "SkCanvas.h"
+#include "../images/SkImageEncoder.h"
SK_DEFINE_INST_COUNT(SkImage)
@@ -16,6 +17,10 @@
return static_cast<SkImage_Base*>(image);
}
+static const SkImage_Base* asIB(const SkImage* image) {
+ return static_cast<const SkImage_Base*>(image);
+}
+
uint32_t SkImage::NextUniqueID() {
static int32_t gUniqueID;
@@ -35,3 +40,29 @@
GrTexture* SkImage::getTexture() {
return asIB(this)->onGetTexture();
}
+
+static const struct {
+ SkImageEncoder::Type fIE;
+ SkImage::EncodeType fET;
+} gTable[] = {
+ { SkImageEncoder::kBMP_Type, SkImage::kBMP_EncodeType },
+ { SkImageEncoder::kGIF_Type, SkImage::kGIF_EncodeType },
+ { SkImageEncoder::kICO_Type, SkImage::kICO_EncodeType },
+ { SkImageEncoder::kJPEG_Type, SkImage::kJPEG_EncodeType },
+ { SkImageEncoder::kPNG_Type, SkImage::kPNG_EncodeType },
+ { SkImageEncoder::kWBMP_Type, SkImage::kWBMP_EncodeType },
+ { SkImageEncoder::kWEBP_Type, SkImage::kWEBP_EncodeType },
+};
+
+SkData* SkImage::encode(EncodeType et, int quality) const {
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gTable); ++i) {
+ if (gTable[i].fET == et) {
+ SkBitmap bm;
+ if (asIB(this)->getROPixels(&bm)) {
+ return SkImageEncoder::EncodeData(bm, gTable[i].fIE, quality);
+ }
+ break;
+ }
+ }
+ return NULL;
+}
diff --git a/src/image/SkImage_Base.h b/src/image/SkImage_Base.h
index d8e64a9..0b3ddb4 100644
--- a/src/image/SkImage_Base.h
+++ b/src/image/SkImage_Base.h
@@ -16,6 +16,10 @@
virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) = 0;
virtual GrTexture* onGetTexture() { return NULL; }
+
+ // return a read-only copy of the pixels. We promise to not modify them,
+ // but only inspect them (or encode them).
+ virtual bool getROPixels(SkBitmap*) const { return false; }
private:
typedef SkImage INHERITED;
diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp
index 451ad07..b6e4211 100644
--- a/src/image/SkImage_Gpu.cpp
+++ b/src/image/SkImage_Gpu.cpp
@@ -22,6 +22,10 @@
virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) SK_OVERRIDE;
virtual GrTexture* onGetTexture() SK_OVERRIDE;
+ virtual bool getROPixels(SkBitmap*) const SK_OVERRIDE {
+ // TODO
+ return false;
+ }
GrTexture* getTexture() { return fTexture; }
diff --git a/src/image/SkImage_Raster.cpp b/src/image/SkImage_Raster.cpp
index 4a18f4a..5e1e8a0 100644
--- a/src/image/SkImage_Raster.cpp
+++ b/src/image/SkImage_Raster.cpp
@@ -55,6 +55,7 @@
virtual ~SkImage_Raster();
virtual void onDraw(SkCanvas*, SkScalar, SkScalar, const SkPaint*) SK_OVERRIDE;
+ virtual bool getROPixels(SkBitmap*) const SK_OVERRIDE;
// exposed for SkSurface_Raster via SkNewImageFromPixelRef
SkImage_Raster(const SkImage::Info&, SkPixelRef*, size_t rowBytes);
@@ -108,6 +109,11 @@
canvas->drawBitmap(fBitmap, x, y, paint);
}
+bool SkImage_Raster::getROPixels(SkBitmap* dst) const {
+ *dst = fBitmap;
+ return true;
+}
+
///////////////////////////////////////////////////////////////////////////////
SkImage* SkImage::NewRasterCopy(const SkImage::Info& info, const void* pixels, size_t rowBytes) {
diff --git a/src/images/SkImageEncoder.cpp b/src/images/SkImageEncoder.cpp
index 4b52fcd..5f5ffb8 100644
--- a/src/images/SkImageEncoder.cpp
+++ b/src/images/SkImageEncoder.cpp
@@ -1,4 +1,3 @@
-
/*
* Copyright 2009 The Android Open Source Project
*
@@ -6,7 +5,6 @@
* found in the LICENSE file.
*/
-
#include "SkImageEncoder.h"
#include "SkBitmap.h"
#include "SkStream.h"
@@ -27,6 +25,15 @@
return this->onEncode(&stream, bm, quality);
}
+SkData* SkImageEncoder::encodeData(const SkBitmap& bm, int quality) {
+ SkDynamicMemoryWStream stream;
+ quality = SkMin32(100, SkMax32(0, quality));
+ if (this->onEncode(&stream, bm, quality)) {
+ return stream.copyToData();
+ }
+ return NULL;
+}
+
bool SkImageEncoder::EncodeFile(const char file[], const SkBitmap& bm, Type t,
int quality) {
SkAutoTDelete<SkImageEncoder> enc(SkImageEncoder::Create(t));
@@ -34,7 +41,13 @@
}
bool SkImageEncoder::EncodeStream(SkWStream* stream, const SkBitmap& bm, Type t,
- int quality) {
+ int quality) {
SkAutoTDelete<SkImageEncoder> enc(SkImageEncoder::Create(t));
return enc.get() && enc.get()->encodeStream(stream, bm, quality);
}
+
+SkData* SkImageEncoder::EncodeData(const SkBitmap& bm, Type t, int quality) {
+ SkAutoTDelete<SkImageEncoder> enc(SkImageEncoder::Create(t));
+ return enc.get() ? enc.get()->encodeData(bm, quality) : NULL;
+}
+
diff --git a/tools/skhello.cpp b/tools/skhello.cpp
index a4451ac..3b8ddee 100644
--- a/tools/skhello.cpp
+++ b/tools/skhello.cpp
@@ -7,8 +7,11 @@
#include "SkCanvas.h"
#include "SkCommandLineFlags.h"
+#include "SkData.h"
#include "SkGraphics.h"
-#include "SkImageEncoder.h"
+#include "SkSurface.h"
+#include "SkImage.h"
+#include "SkStream.h"
#include "SkString.h"
DEFINE_string2(outFile, o, "skhello.png", "The filename to write the image.");
@@ -33,29 +36,29 @@
SkPaint paint;
paint.setAntiAlias(true);
paint.setTextSize(SkIntToScalar(30));
+ paint.setTextAlign(SkPaint::kCenter_Align);
+
SkScalar width = paint.measureText(text.c_str(), text.size());
SkScalar spacing = paint.getFontSpacing();
int w = SkScalarRound(width) + 30;
int h = SkScalarRound(spacing) + 30;
- SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, w, h);
- bitmap.allocPixels();
- SkCanvas canvas(bitmap);
- canvas.drawColor(SK_ColorWHITE);
+ SkImage::Info info = {
+ w, h, SkImage::kPMColor_ColorType, SkImage::kPremul_AlphaType
+ };
+ SkAutoTUnref<SkSurface> surface(SkSurface::NewRaster(info));
+ SkCanvas* canvas = surface->getCanvas();
- paint.setTextAlign(SkPaint::kCenter_Align);
- canvas.drawText(text.c_str(), text.size(),
- SkIntToScalar(w)/2, SkIntToScalar(h)*2/3,
- paint);
+ canvas->drawColor(SK_ColorWHITE);
+ canvas->drawText(text.c_str(), text.size(),
+ SkIntToScalar(w)/2, SkIntToScalar(h)*2/3,
+ paint);
- bool success = SkImageEncoder::EncodeFile(path.c_str(), bitmap,
- SkImageEncoder::kPNG_Type, 100);
- if (!success) {
- SkDebugf("--- failed to write %s\n", path.c_str());
- }
- return !success;
+ SkAutoTUnref<SkImage> image(surface->newImageSnapshot());
+ SkAutoDataUnref data(image->encode());
+ SkFILEWStream stream(path.c_str());
+ return stream.write(data->data(), data->size());
}
#if !defined SK_BUILD_FOR_IOS