diff options
-rw-r--r-- | include/core/SkImage.h | 20 | ||||
-rw-r--r-- | include/images/SkImageEncoder.h | 20 | ||||
-rw-r--r-- | src/image/SkImage.cpp | 31 | ||||
-rw-r--r-- | src/image/SkImage_Base.h | 4 | ||||
-rw-r--r-- | src/image/SkImage_Gpu.cpp | 4 | ||||
-rw-r--r-- | src/image/SkImage_Raster.cpp | 6 | ||||
-rw-r--r-- | src/images/SkImageEncoder.cpp | 19 | ||||
-rw-r--r-- | tools/skhello.cpp | 35 |
8 files changed, 110 insertions, 29 deletions
diff --git a/include/core/SkImage.h b/include/core/SkImage.h index e6ac682876..9b7dfd13b7 100644 --- a/include/core/SkImage.h +++ b/include/core/SkImage.h @@ -21,8 +21,6 @@ class GrTexture; // 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 @@ public: 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 2965c88805..b990aff2a6 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 @@ public: }; /** + * 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 1169459df6..13af631b2a 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 @@ static SkImage_Base* asIB(SkImage* image) { 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 @@ void SkImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y, 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 d8e64a9a75..0b3ddb43b7 100644 --- a/src/image/SkImage_Base.h +++ b/src/image/SkImage_Base.h @@ -16,6 +16,10 @@ public: 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 451ad072a6..b6e4211d28 100644 --- a/src/image/SkImage_Gpu.cpp +++ b/src/image/SkImage_Gpu.cpp @@ -22,6 +22,10 @@ public: 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 4a18f4aef2..5e1e8a02f3 100644 --- a/src/image/SkImage_Raster.cpp +++ b/src/image/SkImage_Raster.cpp @@ -55,6 +55,7 @@ public: 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 @@ void SkImage_Raster::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPa 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 4b52fcdc8c..5f5ffb82a2 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 @@ bool SkImageEncoder::encodeFile(const char file[], const SkBitmap& bm, 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::EncodeFile(const char file[], const SkBitmap& bm, Type t, } 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 a4451ac91a..3b8ddee9a6 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 @@ int tool_main(int argc, char** argv) { 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 |