/*
 * Copyright 2007 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkImageEncoderPriv.h"

#ifdef SK_HAS_JPEG_LIBRARY

#include "SkColorPriv.h"
#include "SkJPEGWriteUtility.h"
#include "SkStream.h"
#include "SkTemplates.h"
#include "transform_scanline.h"

#include <stdio.h>

extern "C" {
    #include "jpeglib.h"
    #include "jerror.h"
}

/**
 *  Returns true if |info| is supported by the jpeg encoder and false otherwise.
 *  |jpegColorType| will be set to the proper libjpeg-turbo type for input to the library.
 *  |numComponents| will be set to the number of components in the |jpegColorType|.
 *  |proc|          will be set if we need to pre-convert the input before passing to
 *                  libjpeg-turbo.  Otherwise will be set to nullptr.
 */
// TODO (skbug.com/1501):
// Should we fail on non-opaque encodes?
// Or should we change alpha behavior (ex: unpremultiply when the input is premul)?
// Or is ignoring the alpha type and alpha channel ok here?
static bool set_encode_config(J_COLOR_SPACE* jpegColorType, int* numComponents,
                              transform_scanline_proc* proc, const SkImageInfo& info) {
    *proc = nullptr;
    switch (info.colorType()) {
        case kRGBA_8888_SkColorType:
            *jpegColorType = JCS_EXT_RGBA;
            *numComponents = 4;
            return true;
        case kBGRA_8888_SkColorType:
            *jpegColorType = JCS_EXT_BGRA;
            *numComponents = 4;
            return true;
        case kRGB_565_SkColorType:
            *proc = transform_scanline_565;
            *jpegColorType = JCS_RGB;
            *numComponents = 3;
            return true;
        case kARGB_4444_SkColorType:
            *proc = transform_scanline_444;
            *jpegColorType = JCS_RGB;
            *numComponents = 3;
            return true;
        case kIndex_8_SkColorType:
            *proc = transform_scanline_index8_opaque;
            *jpegColorType = JCS_RGB;
            *numComponents = 3;
            return true;
        case kGray_8_SkColorType:
            SkASSERT(info.isOpaque());
            *jpegColorType = JCS_GRAYSCALE;
            *numComponents = 1;
            return true;
        case kRGBA_F16_SkColorType:
            if (!info.colorSpace() || !info.colorSpace()->gammaIsLinear()) {
                return false;
            }

            *proc = transform_scanline_F16_to_8888;
            *jpegColorType = JCS_EXT_RGBA;
            *numComponents = 4;
            return true;
        default:
            return false;
    }


}

bool SkEncodeImageAsJPEG(SkWStream* stream, const SkPixmap& pixmap, const SkEncodeOptions& opts) {
    SkASSERT(!pixmap.colorSpace() || pixmap.colorSpace()->gammaCloseToSRGB() ||
            pixmap.colorSpace()->gammaIsLinear());

    SkPixmap src = pixmap;
    if (SkEncodeOptions::ColorBehavior::kLegacy == opts.fColorBehavior) {
        src.setColorSpace(nullptr);
    } else {
        // kCorrect behavior requires a color space.  It's not actually critical in the
        // jpeg case (since jpegs are opaque), but Skia color correct behavior generally
        // requires pixels to be tagged with color spaces.
        if (!src.colorSpace()) {
            return false;
        }
    }

    return SkEncodeImageAsJPEG(stream, src, 100);
}

bool SkEncodeImageAsJPEG(SkWStream* stream, const SkPixmap& pixmap, int quality) {
    if (!pixmap.addr()) {
        return false;
    }
    jpeg_compress_struct    cinfo;
    skjpeg_error_mgr        sk_err;
    skjpeg_destination_mgr  sk_wstream(stream);

    // Declare before calling setjmp.
    SkAutoTMalloc<uint8_t>  storage;

    cinfo.err = jpeg_std_error(&sk_err);
    sk_err.error_exit = skjpeg_error_exit;
    if (setjmp(sk_err.fJmpBuf)) {
        return false;
    }

    J_COLOR_SPACE jpegColorSpace;
    int numComponents;
    transform_scanline_proc proc;
    if (!set_encode_config(&jpegColorSpace, &numComponents, &proc, pixmap.info())) {
        return false;
    }

    jpeg_create_compress(&cinfo);
    cinfo.dest = &sk_wstream;
    cinfo.image_width = pixmap.width();
    cinfo.image_height = pixmap.height();
    cinfo.input_components = numComponents;
    cinfo.in_color_space = jpegColorSpace;

    jpeg_set_defaults(&cinfo);

    // Tells libjpeg-turbo to compute optimal Huffman coding tables
    // for the image.  This improves compression at the cost of
    // slower encode performance.
    cinfo.optimize_coding = TRUE;
    jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);

    jpeg_start_compress(&cinfo, TRUE);

    if (proc) {
        storage.reset(numComponents * pixmap.width());
    }

    const void* srcRow = pixmap.addr();
    const SkPMColor* colors = pixmap.ctable() ? pixmap.ctable()->readColors() : nullptr;
    while (cinfo.next_scanline < cinfo.image_height) {
        JSAMPLE* jpegSrcRow = (JSAMPLE*) srcRow;
        if (proc) {
            proc((char*)storage.get(), (const char*)srcRow, pixmap.width(), numComponents, colors);
            jpegSrcRow = storage.get();
        }

        (void) jpeg_write_scanlines(&cinfo, &jpegSrcRow, 1);
        srcRow = SkTAddOffset<const void>(srcRow, pixmap.rowBytes());
    }

    jpeg_finish_compress(&cinfo);
    jpeg_destroy_compress(&cinfo);

    return true;
}
#endif
