
/*
 * 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);
