/*
 * Copyright 2016 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "Resources.h"

#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkCodec.h"
#include "SkColorSpace_A2B.h"
#include "SkColorSpace_XYZ.h"
#include "SkColorSpacePriv.h"
#include "SkCommandLineFlags.h"
#include "SkImageEncoder.h"
#include "SkMatrix44.h"
#include "SkOSFile.h"

#include "sk_tool_utils.h"

DEFINE_string(input, "input.png", "A path to the input image or icc profile.");
DEFINE_string(gamut_output, "gamut_output.png", "A path to the output gamut image.");
DEFINE_string(gamma_output, "gamma_output.png", "A path to the output gamma image.");
DEFINE_bool(sRGB_gamut, false, "Draws the sRGB gamut on the gamut visualization.");
DEFINE_bool(adobeRGB, false, "Draws the Adobe RGB gamut on the gamut visualization.");
DEFINE_bool(sRGB_gamma, false, "Draws the sRGB gamma on all gamma output images.");
DEFINE_string(uncorrected, "", "A path to reencode the uncorrected input image.");

static const char* kRGBChannelNames[3] = {
    "Red  ", "Green", "Blue "
};

static const SkColor kRGBChannelColors[3] = {
    SkColorSetARGB(164, 255, 32, 32),
    SkColorSetARGB(164, 32, 255, 32),
    SkColorSetARGB(164, 32, 32, 255)
};

static void dump_transfer_fn(SkGammaNamed gammaNamed) {
    switch (gammaNamed) {
        case kSRGB_SkGammaNamed:
            SkDebugf("Transfer Function: sRGB\n");
            return;
        case k2Dot2Curve_SkGammaNamed:
            SkDebugf("Exponential Transfer Function: Exponent 2.2\n");
            return;
        case kLinear_SkGammaNamed:
            SkDebugf("Transfer Function: Linear\n");
            return;
        default:
            break;
    }

}

static void dump_transfer_fn(const SkGammas& gammas) {
    SkASSERT(gammas.channels() == 3);
    for (int i = 0; i < gammas.channels(); i++) {
        if (gammas.isNamed(i)) {
            switch (gammas.data(i).fNamed) {
                case kSRGB_SkGammaNamed:
                    SkDebugf("%s Transfer Function: sRGB\n", kRGBChannelNames[i]);
                    return;
                case k2Dot2Curve_SkGammaNamed:
                    SkDebugf("%s Transfer Function: Exponent 2.2\n", kRGBChannelNames[i]);
                    return;
                case kLinear_SkGammaNamed:
                    SkDebugf("%s Transfer Function: Linear\n", kRGBChannelNames[i]);
                    return;
                default:
                    SkASSERT(false);
                    continue;
            }
        } else if (gammas.isValue(i)) {
            SkDebugf("%s Transfer Function: Exponent %.3f\n", kRGBChannelNames[i],
                     gammas.data(i).fValue);
        } else if (gammas.isParametric(i)) {
            const SkColorSpaceTransferFn& fn = gammas.data(i).params(&gammas);
            SkDebugf("%s Transfer Function: Parametric A = %.3f, B = %.3f, C = %.3f, D = %.3f, "
                     "E = %.3f, F = %.3f, G = %.3f\n", kRGBChannelNames[i], fn.fA, fn.fB, fn.fC,
                     fn.fD, fn.fE, fn.fF, fn.fG);
        } else {
            SkASSERT(gammas.isTable(i));
            SkDebugf("%s Transfer Function: Table (%d entries)\n", kRGBChannelNames[i],
                    gammas.data(i).fTable.fSize);
        }
    }
}

static inline float parametric(const SkColorSpaceTransferFn& fn, float x) {
    return x >= fn.fD ? powf(fn.fA*x + fn.fB, fn.fG) + fn.fE
                      : fn.fC*x + fn.fF;
}

static void draw_transfer_fn(SkCanvas* canvas, SkGammaNamed gammaNamed, const SkGammas* gammas,
                             SkColor color, int col) {
    SkColorSpaceTransferFn fn[4];
    struct TableInfo {
        const float* fTable;
        int          fSize;
    };
    TableInfo table[4];
    bool isTable[4] = {false, false, false, false};
    const int channels = gammas ? gammas->channels() : 1;
    SkASSERT(channels <= 4);
    if (kNonStandard_SkGammaNamed != gammaNamed) {
        dump_transfer_fn(gammaNamed);
        for (int i = 0; i < channels; ++i) {
            named_to_parametric(&fn[i], gammaNamed);
        }
    } else {
        SkASSERT(gammas);
        dump_transfer_fn(*gammas);
        for (int i = 0; i < channels; ++i) {
            if (gammas->isTable(i)) {
                table[i].fTable = gammas->table(i);
                table[i].fSize = gammas->data(i).fTable.fSize;
                isTable[i] = true;
            } else {
                switch (gammas->type(i)) {
                    case SkGammas::Type::kNamed_Type:
                        named_to_parametric(&fn[i], gammas->data(i).fNamed);
                        break;
                    case SkGammas::Type::kValue_Type:
                        value_to_parametric(&fn[i], gammas->data(i).fValue);
                        break;
                    case SkGammas::Type::kParam_Type:
                        fn[i] = gammas->params(i);
                        break;
                    default:
                        SkASSERT(false);
                }
            }
        }
    }
    SkPaint paint;
    paint.setStyle(SkPaint::kStroke_Style);
    paint.setColor(color);
    paint.setStrokeWidth(2.0f);
    // note: gamma has positive values going up in this image so this origin is
    //       the bottom left and we must subtract y instead of adding.
    const float gap         = 16.0f;
    const float cellWidth   = 500.0f;
    const float cellHeight  = 500.0f;
    const float gammaWidth  = cellWidth - 2 * gap;
    const float gammaHeight = cellHeight - 2 * gap;
    // gamma origin point
    const float ox = gap + cellWidth * col;
    const float oy = gap + gammaHeight;
    for (int i = 0; i < channels; ++i) {
        if (kNonStandard_SkGammaNamed == gammaNamed) {
            paint.setColor(kRGBChannelColors[i]);
        } else {
            paint.setColor(color);
        }
        if (isTable[i]) {
            auto tx = [&table,i](int index) {
                return index / (table[i].fSize - 1.0f);
            };
            for (int ti = 1; ti < table[i].fSize; ++ti) {
                canvas->drawLine(ox + gammaWidth * tx(ti - 1),
                                 oy - gammaHeight * table[i].fTable[ti - 1],
                                 ox + gammaWidth * tx(ti),
                                 oy - gammaHeight * table[i].fTable[ti],
                                 paint);
            }
        } else {
            const float step = 0.01f;
            float yPrev = parametric(fn[i], 0.0f);
            for (float x = step; x <= 1.0f; x += step) {
                const float y = parametric(fn[i], x);
                canvas->drawLine(ox + gammaWidth * (x - step), oy - gammaHeight * yPrev,
                                 ox + gammaWidth * x, oy - gammaHeight * y,
                                 paint);
                yPrev = y;
            }
        }
    }
    paint.setColor(0xFF000000);
    paint.setStrokeWidth(3.0f);
    canvas->drawRect({ ox, oy - gammaHeight, ox + gammaWidth, oy }, paint);
}

/**
 *  Loads the triangular gamut as a set of three points.
 */
static void load_gamut(SkPoint rgb[], const SkMatrix44& xyz) {
    // rx = rX / (rX + rY + rZ)
    // ry = rX / (rX + rY + rZ)
    // gx, gy, bx, and gy are calulcated similarly.
    float rSum = xyz.get(0, 0) + xyz.get(1, 0) + xyz.get(2, 0);
    float gSum = xyz.get(0, 1) + xyz.get(1, 1) + xyz.get(2, 1);
    float bSum = xyz.get(0, 2) + xyz.get(1, 2) + xyz.get(2, 2);
    rgb[0].fX = xyz.get(0, 0) / rSum;
    rgb[0].fY = xyz.get(1, 0) / rSum;
    rgb[1].fX = xyz.get(0, 1) / gSum;
    rgb[1].fY = xyz.get(1, 1) / gSum;
    rgb[2].fX = xyz.get(0, 2) / bSum;
    rgb[2].fY = xyz.get(1, 2) / bSum;
}

/**
 *  Calculates the area of the triangular gamut.
 */
static float calculate_area(SkPoint abc[]) {
    SkPoint a = abc[0];
    SkPoint b = abc[1];
    SkPoint c = abc[2];
    return 0.5f * SkTAbs(a.fX*b.fY + b.fX*c.fY - a.fX*c.fY - c.fX*b.fY - b.fX*a.fY);
}

static void draw_gamut(SkCanvas* canvas, const SkMatrix44& xyz, const char* name, SkColor color,
                       bool label) {
    // Report the XYZ values.
    SkDebugf("%s\n", name);
    SkDebugf("       R     G     B\n");
    SkDebugf("X  %.3f %.3f %.3f\n", xyz.get(0, 0), xyz.get(0, 1), xyz.get(0, 2));
    SkDebugf("Y  %.3f %.3f %.3f\n", xyz.get(1, 0), xyz.get(1, 1), xyz.get(1, 2));
    SkDebugf("Z  %.3f %.3f %.3f\n", xyz.get(2, 0), xyz.get(2, 1), xyz.get(2, 2));

    // Calculate the points in the gamut from the XYZ values.
    SkPoint rgb[4];
    load_gamut(rgb, xyz);

    // Report the area of the gamut.
    SkDebugf("Area of Gamut: %.3f\n\n", calculate_area(rgb));

    // Magic constants that help us place the gamut triangles in the appropriate position
    // on the canvas.
    const float xScale = 2071.25f;  // Num pixels from 0 to 1 in x
    const float xOffset = 241.0f;   // Num pixels until start of x-axis
    const float yScale = 2067.78f;  // Num pixels from 0 to 1 in y
    const float yOffset = -144.78f; // Num pixels until start of y-axis
                                    // (negative because y extends beyond image bounds)

    // Now transform the points so they can be drawn on our canvas.
    // Note that y increases as we move down the canvas.
    rgb[0].fX = xOffset + xScale * rgb[0].fX;
    rgb[0].fY = yOffset + yScale * (1.0f - rgb[0].fY);
    rgb[1].fX = xOffset + xScale * rgb[1].fX;
    rgb[1].fY = yOffset + yScale * (1.0f - rgb[1].fY);
    rgb[2].fX = xOffset + xScale * rgb[2].fX;
    rgb[2].fY = yOffset + yScale * (1.0f - rgb[2].fY);

    // Repeat the first point to connect the polygon.
    rgb[3] = rgb[0];
    SkPaint paint;
    paint.setColor(color);
    paint.setStrokeWidth(6.0f);
    paint.setTextSize(75.0f);
    canvas->drawPoints(SkCanvas::kPolygon_PointMode, 4, rgb, paint);
    if (label) {
        canvas->drawString("R", rgb[0].fX + 5.0f, rgb[0].fY + 75.0f, paint);
        canvas->drawString("G", rgb[1].fX + 5.0f, rgb[1].fY - 5.0f, paint);
        canvas->drawString("B", rgb[2].fX - 75.0f, rgb[2].fY - 5.0f, paint);
    }
}

int main(int argc, char** argv) {
    SkCommandLineFlags::SetUsage(
            "Usage: colorspaceinfo --input <path to input image or icc profile> "
                                  "--gamma_output <path to output gamma image> "
                                  "--gamut_output <path to output gamut image>"
                                  "--sRGB <draw canonical sRGB gamut> "
                                  "--adobeRGB <draw canonical Adobe RGB gamut> "
                                  "--uncorrected <path to reencoded, uncorrected input image>\n"
            "Description: Writes visualizations of the color space to the output image(s)  ."
                         "Also, if a path is provided, writes uncorrected bytes to an unmarked "
                         "png, for comparison with the input image.\n");
    SkCommandLineFlags::Parse(argc, argv);
    const char* input = FLAGS_input[0];
    const char* gamut_output = FLAGS_gamut_output[0];
    const char* gamma_output = FLAGS_gamma_output[0];
    if (!input || !gamut_output || !gamma_output) {
        SkCommandLineFlags::PrintUsage();
        return -1;
    }

    sk_sp<SkData> data(SkData::MakeFromFileName(input));
    if (!data) {
        SkDebugf("Cannot find input image.\n");
        return -1;
    }
    std::unique_ptr<SkCodec> codec(SkCodec::NewFromData(data));
    sk_sp<SkColorSpace> colorSpace = nullptr;
    const bool isImage = (codec != nullptr);
    if (isImage) {
        colorSpace = sk_ref_sp(codec->getInfo().colorSpace());
    } else {
        colorSpace = SkColorSpace::MakeICC(data->bytes(), data->size());
    }

    if (!colorSpace) {
        SkDebugf("Cannot create codec or icc profile from input file.\n");
        return -1;
    }

    // Load a graph of the CIE XYZ color gamut.
    SkBitmap gamutCanvasBitmap;
    if (!GetResourceAsBitmap("gamut.png", &gamutCanvasBitmap)) {
        SkDebugf("Program failure.\n");
        return -1;
    }
    SkCanvas gamutCanvas(gamutCanvasBitmap);

    SkBitmap gammaCanvasBitmap;
    gammaCanvasBitmap.allocN32Pixels(500, 500);
    SkCanvas gammaCanvas(gammaCanvasBitmap);

    // Draw the sRGB gamut if requested.
    if (FLAGS_sRGB_gamut) {
        sk_sp<SkColorSpace> sRGBSpace = SkColorSpace::MakeSRGB();
        const SkMatrix44* mat = as_CSB(sRGBSpace)->toXYZD50();
        SkASSERT(mat);
        draw_gamut(&gamutCanvas, *mat, "sRGB", 0xFFFF9394, false);
    }

    // Draw the Adobe RGB gamut if requested.
    if (FLAGS_adobeRGB) {
        sk_sp<SkColorSpace> adobeRGBSpace =
                SkColorSpace_Base::MakeNamed(SkColorSpace_Base::kAdobeRGB_Named);
        const SkMatrix44* mat = as_CSB(adobeRGBSpace)->toXYZD50();
        SkASSERT(mat);
        draw_gamut(&gamutCanvas, *mat, "Adobe RGB", 0xFF31a9e1, false);
    }

    int gammaCol = 0;
    if (SkColorSpace_Base::Type::kXYZ == as_CSB(colorSpace)->type()) {
        const SkMatrix44* mat = as_CSB(colorSpace)->toXYZD50();
        SkASSERT(mat);
        auto xyz = static_cast<SkColorSpace_XYZ*>(colorSpace.get());
        draw_gamut(&gamutCanvas, *mat, input, 0xFF000000, true);
        if (FLAGS_sRGB_gamma) {
            draw_transfer_fn(&gammaCanvas, kSRGB_SkGammaNamed, nullptr, 0xFFFF9394, gammaCol);
        }
        draw_transfer_fn(&gammaCanvas, xyz->gammaNamed(), xyz->gammas(), 0xFF000000, gammaCol++);
    } else {
        SkDebugf("Color space is defined using an A2B tag.  It cannot be represented by "
                 "a transfer function and to D50 matrix.\n");
        return -1;
    }

    // marker to tell the web-tool the names of all images output
    SkDebugf("=========\n");
    auto saveCanvasBitmap = [](const SkBitmap& bitmap, const char *fname) {
        // Finally, encode the result to the output file.
        sk_sp<SkData> out = sk_tool_utils::EncodeImageToData(bitmap, SkEncodedImageFormat::kPNG,
                                                             100);
        if (!out) {
            SkDebugf("Failed to encode %s output.\n", fname);
            return false;
        }
        SkFILEWStream stream(fname);
        if (!stream.write(out->data(), out->size())) {
            SkDebugf("Failed to write %s output.\n", fname);
            return false;
        }
        // record name of canvas
        SkDebugf("%s\n", fname);
        return true;
    };

    // only XYZ images have a gamut visualization since the matrix in A2B is not
    // a gamut adjustment from RGB->XYZ always (or ever)
    if (SkColorSpace_Base::Type::kXYZ == as_CSB(colorSpace)->type() &&
        !saveCanvasBitmap(gamutCanvasBitmap, gamut_output)) {
        return -1;
    }
    if (gammaCol > 0 && !saveCanvasBitmap(gammaCanvasBitmap, gamma_output)) {
        return -1;
    }

    if (isImage) {
        SkDebugf("%s\n", input);
    }
    // Also, if requested, decode and reencode the uncorrected input image.
    if (!FLAGS_uncorrected.isEmpty() && isImage) {
        SkBitmap bitmap;
        int width = codec->getInfo().width();
        int height = codec->getInfo().height();
        bitmap.allocN32Pixels(width, height, kOpaque_SkAlphaType == codec->getInfo().alphaType());
        SkImageInfo decodeInfo = SkImageInfo::MakeN32(width, height, kUnpremul_SkAlphaType);
        if (SkCodec::kSuccess != codec->getPixels(decodeInfo, bitmap.getPixels(),
                                                  bitmap.rowBytes())) {
            SkDebugf("Could not decode input image.\n");
            return -1;
        }
        sk_sp<SkData> out = sk_tool_utils::EncodeImageToData(bitmap, SkEncodedImageFormat::kPNG,
                                                             100);
        if (!out) {
            SkDebugf("Failed to encode uncorrected image.\n");
            return -1;
        }
        SkFILEWStream bitmapStream(FLAGS_uncorrected[0]);
        if (!bitmapStream.write(out->data(), out->size())) {
            SkDebugf("Failed to write uncorrected image output.\n");
            return -1;
        }
        SkDebugf("%s\n", FLAGS_uncorrected[0]);
    }

    return 0;
}
