/*
 * 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 "include/core/SkTypes.h"

#if defined(SK_BUILD_FOR_WIN)

#include "include/core/SkBitmap.h"
#include "include/core/SkImageEncoder.h"
#include "include/core/SkStream.h"
#include "include/core/SkUnPreMultiply.h"
#include "include/private/base/SkTemplates.h"
#include "src/base/SkAutoMalloc.h"
#include "src/encode/SkImageEncoderPriv.h"
#include "src/utils/win/SkAutoCoInitialize.h"
#include "src/utils/win/SkIStream.h"
#include "src/utils/win/SkTScopedComPtr.h"
#include <wincodec.h>

//All Windows SDKs back to XPSP2 export the CLSID_WICImagingFactory symbol.
//In the Windows8 SDK the CLSID_WICImagingFactory symbol is still exported
//but CLSID_WICImagingFactory is then #defined to CLSID_WICImagingFactory2.
//Undo this #define if it has been done so that we link against the symbols
//we intended to link against on all SDKs.
#if defined(CLSID_WICImagingFactory)
#undef CLSID_WICImagingFactory
#endif

bool SkEncodeImageWithWIC(SkWStream* stream, const SkPixmap& pixmap,
                          SkEncodedImageFormat format, int quality) {
    GUID type;
    switch (format) {
        case SkEncodedImageFormat::kJPEG:
            type = GUID_ContainerFormatJpeg;
            break;
        case SkEncodedImageFormat::kPNG:
            type = GUID_ContainerFormatPng;
            break;
        default:
            return false;
    }
    SkBitmap bitmapOrig;
    if (!bitmapOrig.installPixels(pixmap)) {
        return false;
    }
    bitmapOrig.setImmutable();

    // First convert to BGRA if necessary.
    SkBitmap bitmap;
    if (!bitmap.tryAllocPixels(bitmapOrig.info().makeColorType(kBGRA_8888_SkColorType)) ||
        !bitmapOrig.readPixels(bitmap.info(), bitmap.getPixels(), bitmap.rowBytes(), 0, 0))
    {
        return false;
    }

    // WIC expects unpremultiplied pixels.  Unpremultiply if necessary.
    if (kPremul_SkAlphaType == bitmap.alphaType()) {
        uint8_t* pixels = reinterpret_cast<uint8_t*>(bitmap.getPixels());
        for (int y = 0; y < bitmap.height(); ++y) {
            for (int x = 0; x < bitmap.width(); ++x) {
                uint8_t* bytes = pixels + y * bitmap.rowBytes() + x * bitmap.bytesPerPixel();
                SkPMColor* src = reinterpret_cast<SkPMColor*>(bytes);
                SkColor* dst = reinterpret_cast<SkColor*>(bytes);
                *dst = SkUnPreMultiply::PMColorToColor(*src);
            }
        }
    }

    // Finally, if we are performing a jpeg encode, we must convert to BGR.
    void* pixels = bitmap.getPixels();
    size_t rowBytes = bitmap.rowBytes();
    SkAutoMalloc pixelStorage;
    WICPixelFormatGUID formatDesired = GUID_WICPixelFormat32bppBGRA;
    if (SkEncodedImageFormat::kJPEG == format) {
        formatDesired = GUID_WICPixelFormat24bppBGR;
        rowBytes = SkAlign4(bitmap.width() * 3);
        pixelStorage.reset(rowBytes * bitmap.height());
        for (int y = 0; y < bitmap.height(); y++) {
            uint8_t* dstRow = SkTAddOffset<uint8_t>(pixelStorage.get(), y * rowBytes);
            for (int x = 0; x < bitmap.width(); x++) {
                uint32_t bgra = *bitmap.getAddr32(x, y);
                dstRow[0] = (uint8_t) ((bgra >>  0) & 0xFF);
                dstRow[1] = (uint8_t) ((bgra >>  8) & 0xFF);
                dstRow[2] = (uint8_t) ((bgra >> 16) & 0xFF);
                dstRow += 3;
            }
        }

        pixels = pixelStorage.get();
    }


    //Initialize COM.
    SkAutoCoInitialize scopedCo;
    if (!scopedCo.succeeded()) {
        return false;
    }

    HRESULT hr = S_OK;

    //Create Windows Imaging Component ImagingFactory.
    SkTScopedComPtr<IWICImagingFactory> piImagingFactory;
    if (SUCCEEDED(hr)) {
        hr = CoCreateInstance(
            CLSID_WICImagingFactory
            , nullptr
            , CLSCTX_INPROC_SERVER
            , IID_PPV_ARGS(&piImagingFactory)
        );
    }

    //Convert the SkWStream to an IStream.
    SkTScopedComPtr<IStream> piStream;
    if (SUCCEEDED(hr)) {
        hr = SkWIStream::CreateFromSkWStream(stream, &piStream);
    }

    //Create an encode of the appropriate type.
    SkTScopedComPtr<IWICBitmapEncoder> piEncoder;
    if (SUCCEEDED(hr)) {
        hr = piImagingFactory->CreateEncoder(type, nullptr, &piEncoder);
    }

    if (SUCCEEDED(hr)) {
        hr = piEncoder->Initialize(piStream.get(), WICBitmapEncoderNoCache);
    }

    //Create a the frame.
    SkTScopedComPtr<IWICBitmapFrameEncode> piBitmapFrameEncode;
    SkTScopedComPtr<IPropertyBag2> piPropertybag;
    if (SUCCEEDED(hr)) {
        hr = piEncoder->CreateNewFrame(&piBitmapFrameEncode, &piPropertybag);
    }

    if (SUCCEEDED(hr)) {
        PROPBAG2 name;
        memset(&name, 0, sizeof(name));
        name.dwType = PROPBAG2_TYPE_DATA;
        name.vt = VT_R4;
        name.pstrName = const_cast<LPOLESTR>(L"ImageQuality");

        VARIANT value;
        VariantInit(&value);
        value.vt = VT_R4;
        value.fltVal = (FLOAT)(quality / 100.0);

        //Ignore result code.
        //  This returns E_FAIL if the named property is not in the bag.
        //TODO(bungeman) enumerate the properties,
        //  write and set hr iff property exists.
        piPropertybag->Write(1, &name, &value);
    }
    if (SUCCEEDED(hr)) {
        hr = piBitmapFrameEncode->Initialize(piPropertybag.get());
    }

    //Set the size of the frame.
    const UINT width = bitmap.width();
    const UINT height = bitmap.height();
    if (SUCCEEDED(hr)) {
        hr = piBitmapFrameEncode->SetSize(width, height);
    }

    //Set the pixel format of the frame.  If native encoded format cannot match BGRA,
    //it will choose the closest pixel format that it supports.
    WICPixelFormatGUID formatGUID = formatDesired;
    if (SUCCEEDED(hr)) {
        hr = piBitmapFrameEncode->SetPixelFormat(&formatGUID);
    }
    if (SUCCEEDED(hr)) {
        //Be sure the image format is the one requested.
        hr = IsEqualGUID(formatGUID, formatDesired) ? S_OK : E_FAIL;
    }

    //Write the pixels into the frame.
    if (SUCCEEDED(hr)) {
        hr = piBitmapFrameEncode->WritePixels(height,
                                              (UINT) rowBytes,
                                              (UINT) rowBytes * height,
                                              reinterpret_cast<BYTE*>(pixels));
    }

    if (SUCCEEDED(hr)) {
        hr = piBitmapFrameEncode->Commit();
    }

    if (SUCCEEDED(hr)) {
        hr = piEncoder->Commit();
    }

    return SUCCEEDED(hr);
}

#endif // defined(SK_BUILD_FOR_WIN)
