/* * Copyright 2011 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "SampleCode.h" #include "SkView.h" #include "SkCanvas.h" #include "SkData.h" #include "SkDecodingImageGenerator.h" #include "SkGradientShader.h" #include "SkGraphics.h" #include "SkImageDecoder.h" #include "SkImageEncoder.h" #include "SkPath.h" #include "SkRegion.h" #include "SkShader.h" #include "SkUtils.h" #include "SkXfermode.h" #include "SkColorPriv.h" #include "SkColorFilter.h" #include "SkTime.h" #include "SkTypeface.h" #include "SkStream.h" static void make_image(SkBitmap* bm, SkColorType ct, int configIndex) { const int width = 98; const int height = 100; const SkImageInfo info = SkImageInfo::Make(width, height, ct, kPremul_SkAlphaType); SkBitmap device; device.allocN32Pixels(width, height); SkCanvas canvas(device); SkPaint paint; paint.setAntiAlias(true); canvas.drawColor(SK_ColorRED); paint.setColor(SK_ColorBLUE); canvas.drawCircle(SkIntToScalar(width)/2, SkIntToScalar(height)/2, SkIntToScalar(width)/2, paint); switch (ct) { case kN32_SkColorType: bm->swap(device); break; case kRGB_565_SkColorType: { bm->allocPixels(info); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { *bm->getAddr16(x, y) = SkPixel32ToPixel16(*device.getAddr32(x, y)); } } break; } case kIndex_8_SkColorType: { SkPMColor colors[256]; for (int i = 0; i < 256; i++) { if (configIndex & 1) { colors[i] = SkPackARGB32(255-i, 0, 0, 255-i); } else { colors[i] = SkPackARGB32(0xFF, i, 0, 255-i); } } SkColorTable* ctable = new SkColorTable(colors, 256); bm->allocPixels(info, NULL, ctable); ctable->unref(); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { *bm->getAddr8(x, y) = SkGetPackedR32(*device.getAddr32(x, y)); } } break; } default: SkASSERT(0); } } // configs to build the original bitmap in. Can be at most these 3 static const SkColorType gColorTypes[] = { kN32_SkColorType, kRGB_565_SkColorType, kIndex_8_SkColorType, // opaque kIndex_8_SkColorType // alpha }; static const char* const gConfigLabels[] = { "8888", "565", "Index8", "Index8 alpha" }; // types to encode into. Can be at most these 3. Must match up with gExt[] static const SkImageEncoder::Type gTypes[] = { SkImageEncoder::kJPEG_Type, SkImageEncoder::kPNG_Type }; // must match up with gTypes[] static const char* const gExt[] = { ".jpg", ".png" }; #include <sys/stat.h> class EncodeView : public SampleView { public: SkBitmap* fBitmaps; SkAutoDataUnref* fEncodedPNGs; SkAutoDataUnref* fEncodedJPEGs; int fBitmapCount; EncodeView() { fBitmapCount = SK_ARRAY_COUNT(gColorTypes); fBitmaps = new SkBitmap[fBitmapCount]; fEncodedPNGs = new SkAutoDataUnref[fBitmapCount]; fEncodedJPEGs = new SkAutoDataUnref[fBitmapCount]; for (int i = 0; i < fBitmapCount; i++) { make_image(&fBitmaps[i], gColorTypes[i], i); for (size_t j = 0; j < SK_ARRAY_COUNT(gTypes); j++) { SkAutoTDelete<SkImageEncoder> codec( SkImageEncoder::Create(gTypes[j])); if (NULL == codec.get()) { SkDebugf("[%s:%d] failed to encode %s%s\n", __FILE__, __LINE__,gConfigLabels[i], gExt[j]); continue; } SkAutoDataUnref data(codec->encodeData(fBitmaps[i], 100)); if (NULL == data.get()) { SkDebugf("[%s:%d] failed to encode %s%s\n", __FILE__, __LINE__,gConfigLabels[i], gExt[j]); continue; } if (SkImageEncoder::kJPEG_Type == gTypes[j]) { fEncodedJPEGs[i].reset(data.detach()); } else if (SkImageEncoder::kPNG_Type == gTypes[j]) { fEncodedPNGs[i].reset(data.detach()); } } } this->setBGColor(0xFFDDDDDD); } virtual ~EncodeView() { delete[] fBitmaps; delete[] fEncodedPNGs; delete[] fEncodedJPEGs; } protected: // overrides from SkEventSink virtual bool onQuery(SkEvent* evt) { if (SampleCode::TitleQ(*evt)) { SampleCode::TitleR(evt, "ImageEncoder"); return true; } return this->INHERITED::onQuery(evt); } virtual void onDrawContent(SkCanvas* canvas) { if (fBitmapCount == 0) { return; } SkPaint paint; paint.setAntiAlias(true); paint.setTextAlign(SkPaint::kCenter_Align); canvas->translate(SkIntToScalar(10), SkIntToScalar(20)); SkScalar x = 0, y = 0, maxX = 0; const int SPACER = 10; for (int i = 0; i < fBitmapCount; i++) { canvas->drawText(gConfigLabels[i], strlen(gConfigLabels[i]), x + SkIntToScalar(fBitmaps[i].width()) / 2, 0, paint); y = paint.getTextSize(); canvas->drawBitmap(fBitmaps[i], x, y); SkScalar yy = y; for (size_t j = 0; j < SK_ARRAY_COUNT(gTypes); j++) { yy += SkIntToScalar(fBitmaps[i].height() + 10); SkBitmap bm; SkData* encoded = NULL; if (SkImageEncoder::kJPEG_Type == gTypes[j]) { encoded = fEncodedJPEGs[i].get(); } else if (SkImageEncoder::kPNG_Type == gTypes[j]) { encoded = fEncodedPNGs[i].get(); } if (encoded) { if (!SkInstallDiscardablePixelRef( SkDecodingImageGenerator::Create(encoded, SkDecodingImageGenerator::Options()), &bm)) { SkDebugf("[%s:%d] failed to decode %s%s\n", __FILE__, __LINE__,gConfigLabels[i], gExt[j]); } canvas->drawBitmap(bm, x, yy); } } x += SkIntToScalar(fBitmaps[i].width() + SPACER); if (x > maxX) { maxX = x; } } y = (paint.getTextSize() + SkIntToScalar(fBitmaps[0].height())) * 3 / 2; x = maxX + SkIntToScalar(10); paint.setTextAlign(SkPaint::kLeft_Align); for (size_t j = 0; j < SK_ARRAY_COUNT(gExt); j++) { canvas->drawText(gExt[j], strlen(gExt[j]), x, y, paint); y += SkIntToScalar(fBitmaps[0].height() + SPACER); } } virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) { this->inval(NULL); return this->INHERITED::onFindClickHandler(x, y, modi); } private: typedef SampleView INHERITED; }; ////////////////////////////////////////////////////////////////////////////// static SkView* MyFactory() { return new EncodeView; } static SkViewRegister reg(MyFactory);