/*
* Copyright 2018 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/SkCanvas.h"
#include "include/core/SkData.h"
#include "include/core/SkImage.h"
#include "include/core/SkStream.h"
#include "include/core/SkSurface.h"
#include "include/encode/SkPngEncoder.h"
#include "modules/skcms/skcms.h"
#include "src/core/SkColorSpacePriv.h"

static void write_png(const char* path, sk_sp<SkImage> img) {
    sk_sp<SkData> png = SkPngEncoder::Encode(nullptr, img.get(), {});
    SkASSERT(png);
    SkFILEWStream(path).write(png->data(), png->size());
}

int main(int argc, char** argv) {
    const char* source_path = argc > 1 ? argv[1] : nullptr;
    if (!source_path) {
        SkDebugf("Please pass an image or profile to convert"
                 " as the first argument to this program.\n");
        return 1;
    }

    const char* dst_profile_path = argc > 2 ? argv[2] : nullptr;
    skcms_ICCProfile dst_profile = *skcms_sRGB_profile();
    sk_sp<SkData> dst_blob;
    if (dst_profile_path) {
        dst_blob = SkData::MakeFromFileName(dst_profile_path);
        if (!skcms_Parse(dst_blob->data(), dst_blob->size(), &dst_profile)) {
            SkDebugf("Can't parse %s as an ICC profile.\n", dst_profile_path);
            return 1;
        }
    }

    auto blob = SkData::MakeFromFileName(source_path);

    skcms_ICCProfile src_profile;
    if (skcms_Parse(blob->data(), blob->size(), &src_profile)) {
        // Transform white, black, primaries, and primary complements.
        float src[] = {
           0,0,0,
           1,1,1,

           1,0,0,
           0,1,0,
           0,0,1,

           0,1,1,
           1,0,1,
           1,1,0,
        };
        float dst[24] = {0};

        if (!skcms_Transform(
                    src, skcms_PixelFormat_RGB_fff, skcms_AlphaFormat_Unpremul, &src_profile,
                    dst, skcms_PixelFormat_RGB_fff, skcms_AlphaFormat_Unpremul, &dst_profile,
                    8)) {
            SkDebugf("Cannot transform.\n");
            return 1;
        }
        for (int i = 0; i < 8; i++) {
            SkDebugf("(%g, %g, %g) --> (%+.4f, %+.4f, %+.4f)\n",
                     src[3*i+0], src[3*i+1], src[3*i+2],
                     dst[3*i+0], dst[3*i+1], dst[3*i+2]);
        }
        return 0;
    }

    sk_sp<SkImage> image = SkImages::DeferredFromEncodedData(blob);
    if (!image) {
        SkDebugf("Couldn't decode %s as an SkImage or an ICC profile.\n", source_path);
        return 1;
    }

    image = image->makeRasterImage();
    if (!image) {
        SkDebugf("Converting to raster image failed.\n");
        return 1;
    }

    SkPixmap pixmap;
    if (!image->peekPixels(&pixmap)) {
        SkDebugf("We really should be able to peek raster pixels.\n");
        return 1;
    }

    sk_sp<SkColorSpace> dst_cs = SkColorSpace::Make(dst_profile);
    if (!dst_cs) {
        SkDebugf("We can't convert to this destination profile as-is. Coercing it.\n");
        if (skcms_MakeUsableAsDestinationWithSingleCurve(&dst_profile)) {
            dst_cs = SkColorSpace::Make(dst_profile);
        }
        if (!dst_cs) {
            SkDebugf("We can't convert to this destination profile at all.\n");
            return 1;
        }
    }

    { // transform with skcms
        SkColorSpace* src_cs = image->colorSpace() ? image->colorSpace()
                                                   : sk_srgb_singleton();
        src_cs->toProfile(&src_profile);

        skcms_PixelFormat fmt;
        switch (pixmap.colorType()) {
            case kRGBA_8888_SkColorType: fmt = skcms_PixelFormat_RGBA_8888; break;
            case kBGRA_8888_SkColorType: fmt = skcms_PixelFormat_BGRA_8888; break;
            default:
                SkDebugf("color type %d not yet supported, imgcvt.cpp needs an update.\n",
                         pixmap.colorType());
                return 1;
        }

        if (pixmap.alphaType() == kUnpremul_SkAlphaType) {
            SkDebugf("not premul, that's weird.\n");
            return 1;
        }
        auto alpha = skcms_AlphaFormat_PremulAsEncoded;

        if (pixmap.rowBytes() != (size_t)pixmap.width() * pixmap.info().bytesPerPixel()) {
            SkDebugf("not a tight pixmap, need a loop here\n");
            return 1;
        }

        if (!skcms_Transform(pixmap.addr(),          fmt,alpha, &src_profile,
                             pixmap.writable_addr(), fmt,alpha, &dst_profile,
                             pixmap.width() * pixmap.height())) {
            SkDebugf("skcms_Transform() failed\n");
            return 1;
        }
        pixmap.setColorSpace(dst_cs);

        write_png("transformed-skcms.png", SkImages::RasterFromPixmapCopy(pixmap));
    }

    { // transform with writePixels()
        sk_sp<SkSurface> surface = SkSurfaces::Raster(pixmap.info().makeColorSpace(dst_cs));
        if (!surface) {
            SkDebugf("couldn't create a surface\n");
            return 1;
        }

        surface->writePixels(pixmap, 0,0);

        write_png("transformed-writepixels.png", surface->makeImageSnapshot());
    }

    { // transform by drawing
        sk_sp<SkSurface> surface = SkSurfaces::Raster(pixmap.info().makeColorSpace(dst_cs));
        if (!surface) {
            SkDebugf("couldn't create a surface\n");
            return 1;
        }

        surface->getCanvas()->drawImage(image, 0,0);

        write_png("transformed-draw.png", surface->makeImageSnapshot());
    }

    return 0;
}
