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

#include "SkCodec.h"
#include "SkJpegCodec.h"
#include "SkJpegDecoderMgr.h"
#include "SkJpegUtility_codec.h"
#include "SkCodecPriv.h"
#include "SkColorPriv.h"
#include "SkScaledCodec.h"
#include "SkScanlineDecoder.h"
#include "SkStream.h"
#include "SkTemplates.h"
#include "SkTypes.h"

// stdio is needed for libjpeg-turbo
#include <stdio.h>

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

/*
 * Convert a row of CMYK samples to RGBA in place.
 * Note that this method moves the row pointer.
 * @param width the number of pixels in the row that is being converted
 *              CMYK is stored as four bytes per pixel
 */
static void convert_CMYK_to_RGBA(uint8_t* row, uint32_t width) {
    // We will implement a crude conversion from CMYK -> RGB using formulas
    // from easyrgb.com.
    //
    // CMYK -> CMY
    // C = C * (1 - K) + K
    // M = M * (1 - K) + K
    // Y = Y * (1 - K) + K
    //
    // libjpeg actually gives us inverted CMYK, so we must subtract the
    // original terms from 1.
    // CMYK -> CMY
    // C = (1 - C) * (1 - (1 - K)) + (1 - K)
    // M = (1 - M) * (1 - (1 - K)) + (1 - K)
    // Y = (1 - Y) * (1 - (1 - K)) + (1 - K)
    //
    // Simplifying the above expression.
    // CMYK -> CMY
    // C = 1 - CK
    // M = 1 - MK
    // Y = 1 - YK
    //
    // CMY -> RGB
    // R = (1 - C) * 255
    // G = (1 - M) * 255
    // B = (1 - Y) * 255
    //
    // Therefore the full conversion is below.  This can be verified at
    // www.rapidtables.com (assuming inverted CMYK).
    // CMYK -> RGB
    // R = C * K * 255
    // G = M * K * 255
    // B = Y * K * 255
    //
    // As a final note, we have treated the CMYK values as if they were on
    // a scale from 0-1, when in fact they are 8-bit ints scaling from 0-255.
    // We must divide each CMYK component by 255 to obtain the true conversion
    // we should perform.
    // CMYK -> RGB
    // R = C * K / 255
    // G = M * K / 255
    // B = Y * K / 255
    for (uint32_t x = 0; x < width; x++, row += 4) {
#if defined(SK_PMCOLOR_IS_RGBA)
        row[0] = SkMulDiv255Round(row[0], row[3]);
        row[1] = SkMulDiv255Round(row[1], row[3]);
        row[2] = SkMulDiv255Round(row[2], row[3]);
#else
        uint8_t tmp = row[0];
        row[0] = SkMulDiv255Round(row[2], row[3]);
        row[1] = SkMulDiv255Round(row[1], row[3]);
        row[2] = SkMulDiv255Round(tmp, row[3]);
#endif
        row[3] = 0xFF;
    }
}

bool SkJpegCodec::IsJpeg(SkStream* stream) {
    static const uint8_t jpegSig[] = { 0xFF, 0xD8, 0xFF };
    char buffer[sizeof(jpegSig)];
    return stream->read(buffer, sizeof(jpegSig)) == sizeof(jpegSig) &&
            !memcmp(buffer, jpegSig, sizeof(jpegSig));
}

bool SkJpegCodec::ReadHeader(SkStream* stream, SkCodec** codecOut,
        JpegDecoderMgr** decoderMgrOut) {

    // Create a JpegDecoderMgr to own all of the decompress information
    SkAutoTDelete<JpegDecoderMgr> decoderMgr(SkNEW_ARGS(JpegDecoderMgr, (stream)));

    // libjpeg errors will be caught and reported here
    if (setjmp(decoderMgr->getJmpBuf())) {
        return decoderMgr->returnFalse("setjmp");
    }

    // Initialize the decompress info and the source manager
    decoderMgr->init();

    // Read the jpeg header
    if (JPEG_HEADER_OK != chromium_jpeg_read_header(decoderMgr->dinfo(), true)) {
        return decoderMgr->returnFalse("read_header");
    }

    if (NULL != codecOut) {
        // Recommend the color type to decode to
        const SkColorType colorType = decoderMgr->getColorType();

        // Create image info object and the codec
        const SkImageInfo& imageInfo = SkImageInfo::Make(decoderMgr->dinfo()->image_width,
                decoderMgr->dinfo()->image_height, colorType, kOpaque_SkAlphaType);
        *codecOut = SkNEW_ARGS(SkJpegCodec, (imageInfo, stream, decoderMgr.detach()));
    } else {
        SkASSERT(NULL != decoderMgrOut);
        *decoderMgrOut = decoderMgr.detach();
    }
    return true;
}

SkCodec* SkJpegCodec::NewFromStream(SkStream* stream) {
    SkAutoTDelete<SkStream> streamDeleter(stream);
    SkCodec* codec = NULL;
    if (ReadHeader(stream,  &codec, NULL)) {
        // Codec has taken ownership of the stream, we do not need to delete it
        SkASSERT(codec);
        streamDeleter.detach();
        return codec;
    }
    return NULL;
}

SkJpegCodec::SkJpegCodec(const SkImageInfo& srcInfo, SkStream* stream,
        JpegDecoderMgr* decoderMgr)
    : INHERITED(srcInfo, stream)
    , fDecoderMgr(decoderMgr)
{}

/*
 * Return the row bytes of a particular image type and width
 */
static int get_row_bytes(const j_decompress_ptr dinfo) {
    int colorBytes = (dinfo->out_color_space == JCS_RGB565) ? 2 : dinfo->out_color_components;
    return dinfo->output_width * colorBytes;

}
/*
 * Return a valid set of output dimensions for this decoder, given an input scale
 */
SkISize SkJpegCodec::onGetScaledDimensions(float desiredScale) const {
    // libjpeg-turbo supports scaling by 1/8, 1/4, 3/8, 1/2, 5/8, 3/4, 7/8, and 1/1, so we will
    // support these as well
    long num;
    long denom = 8;
    if (desiredScale > 0.875f) {
        num = 8;
    } else if (desiredScale > 0.75f) {
        num = 7;
    } else if (desiredScale > 0.625f) {
        num = 6;
    } else if (desiredScale > 0.5f) {
        num = 5;
    } else if (desiredScale > 0.375f) {
        num = 4;
    } else if (desiredScale > 0.25f) {
        num = 3;
    } else if (desiredScale > 0.125f) {
        num = 2;
    } else {
        num = 1;
    }

    // Set up a fake decompress struct in order to use libjpeg to calculate output dimensions
    jpeg_decompress_struct dinfo;
    sk_bzero(&dinfo, sizeof(dinfo));
    dinfo.image_width = this->getInfo().width();
    dinfo.image_height = this->getInfo().height();
    dinfo.global_state = DSTATE_READY;
    dinfo.num_components = 0;
    dinfo.scale_num = num;
    dinfo.scale_denom = denom;
    chromium_jpeg_calc_output_dimensions(&dinfo);

    // Return the calculated output dimensions for the given scale
    return SkISize::Make(dinfo.output_width, dinfo.output_height);
}

bool SkJpegCodec::onRewind() {
    JpegDecoderMgr* decoderMgr = NULL;
    if (!ReadHeader(this->stream(), NULL, &decoderMgr)) {
        return fDecoderMgr->returnFalse("could not rewind");
    }
    SkASSERT(NULL != decoderMgr);
    fDecoderMgr.reset(decoderMgr);
    return true;
}

/*
 * Checks if the conversion between the input image and the requested output
 * image has been implemented
 * Sets the output color space
 */
bool SkJpegCodec::setOutputColorSpace(const SkImageInfo& dst) {
    const SkImageInfo& src = this->getInfo();

    // Ensure that the profile type is unchanged
    if (dst.profileType() != src.profileType()) {
        return false;
    }

    // Ensure that the alpha type is opaque
    if (kOpaque_SkAlphaType != dst.alphaType()) {
        return false;
    }

    // Check if we will decode to CMYK because a conversion to RGBA is not supported
    J_COLOR_SPACE colorSpace = fDecoderMgr->dinfo()->jpeg_color_space;
    bool isCMYK = JCS_CMYK == colorSpace || JCS_YCCK == colorSpace;

    // Check for valid color types and set the output color space
    switch (dst.colorType()) {
        case kN32_SkColorType:
            if (isCMYK) {
                fDecoderMgr->dinfo()->out_color_space = JCS_CMYK;
            } else {
                // Check the byte ordering of the RGBA color space for the
                // current platform
#if defined(SK_PMCOLOR_IS_RGBA)
                fDecoderMgr->dinfo()->out_color_space = JCS_EXT_RGBA;
#else
                fDecoderMgr->dinfo()->out_color_space = JCS_EXT_BGRA;
#endif
            }
            return true;
        case kRGB_565_SkColorType:
            if (isCMYK) {
                return false;
            } else {
                fDecoderMgr->dinfo()->out_color_space = JCS_RGB565;
            }
            return true;
        case kGray_8_SkColorType:
            if (isCMYK) {
                return false;
            } else {
                // We will enable decodes to gray even if the image is color because this is
                // much faster than decoding to color and then converting
                fDecoderMgr->dinfo()->out_color_space = JCS_GRAYSCALE;
            }
            return true;
        default:
            return false;
    }
}

/*
 * Checks if we can natively scale to the requested dimensions and natively scales the 
 * dimensions if possible
 */
bool SkJpegCodec::nativelyScaleToDimensions(uint32_t dstWidth, uint32_t dstHeight) {
    // libjpeg-turbo can scale to 1/8, 1/4, 3/8, 1/2, 5/8, 3/4, 7/8, and 1/1
    fDecoderMgr->dinfo()->scale_denom = 8;
    fDecoderMgr->dinfo()->scale_num = 8;
    chromium_jpeg_calc_output_dimensions(fDecoderMgr->dinfo());
    while (fDecoderMgr->dinfo()->output_width != dstWidth ||
            fDecoderMgr->dinfo()->output_height != dstHeight) {

        // Return a failure if we have tried all of the possible scales
        if (1 == fDecoderMgr->dinfo()->scale_num ||
                dstWidth > fDecoderMgr->dinfo()->output_width ||
                dstHeight > fDecoderMgr->dinfo()->output_height) {
            // reset native scale settings on failure because this may be supported by the swizzler 
            this->fDecoderMgr->dinfo()->scale_num = 8;
            chromium_jpeg_calc_output_dimensions(this->fDecoderMgr->dinfo());
            return false;
        }

        // Try the next scale
        fDecoderMgr->dinfo()->scale_num -= 1;
        chromium_jpeg_calc_output_dimensions(fDecoderMgr->dinfo());
    }
    return true;
}

/*
 * Performs the jpeg decode
 */
SkCodec::Result SkJpegCodec::onGetPixels(const SkImageInfo& dstInfo,
                                         void* dst, size_t dstRowBytes,
                                         const Options& options, SkPMColor*, int*) {
    // Rewind the stream if needed
    if (!this->rewindIfNeeded()) {
        return fDecoderMgr->returnFailure("could not rewind stream", kCouldNotRewind);
    }

    if (options.fSubset) {
        // Subsets are not supported.
        return kUnimplemented;
    }

    // Get a pointer to the decompress info since we will use it quite frequently
    jpeg_decompress_struct* dinfo = fDecoderMgr->dinfo();

    // Set the jump location for libjpeg errors
    if (setjmp(fDecoderMgr->getJmpBuf())) {
        return fDecoderMgr->returnFailure("setjmp", kInvalidInput);
    }

    // Check if we can decode to the requested destination and set the output color space
    if (!this->setOutputColorSpace(dstInfo)) {
        return fDecoderMgr->returnFailure("conversion_possible", kInvalidConversion);
    }

    // Perform the necessary scaling
    if (!this->nativelyScaleToDimensions(dstInfo.width(), dstInfo.height())) {
        return fDecoderMgr->returnFailure("cannot scale to requested dims", kInvalidScale);
    }

    // Now, given valid output dimensions, we can start the decompress
    if (!chromium_jpeg_start_decompress(dinfo)) {
        return fDecoderMgr->returnFailure("startDecompress", kInvalidInput);
    }

    // The recommended output buffer height should always be 1 in high quality modes.
    // If it's not, we want to know because it means our strategy is not optimal.
    SkASSERT(1 == dinfo->rec_outbuf_height);

    // Perform the decode a single row at a time
    uint32_t dstHeight = dstInfo.height();
    JSAMPLE* dstRow = (JSAMPLE*) dst;
    for (uint32_t y = 0; y < dstHeight; y++) {
        // Read rows of the image
        uint32_t rowsDecoded = chromium_jpeg_read_scanlines(dinfo, &dstRow, 1);

        // If we cannot read enough rows, assume the input is incomplete
        if (rowsDecoded != 1) {
            // Fill the remainder of the image with black. This error handling
            // behavior is unspecified but SkCodec consistently uses black as
            // the fill color for opaque images.  If the destination is kGray,
            // the low 8 bits of SK_ColorBLACK will be used.  Conveniently,
            // these are zeros, which is the representation for black in kGray.
            // If the destination is kRGB_565, the low 16 bits of SK_ColorBLACK
            // will be used.  Conveniently, these are zeros, which is the
            // representation for black in kRGB_565.
            if (kNo_ZeroInitialized == options.fZeroInitialized ||
                    kN32_SkColorType == dstInfo.colorType()) {
                SkSwizzler::Fill(dstRow, dstInfo, dstRowBytes, dstHeight - y,
                        SK_ColorBLACK, NULL);
            }

            // Prevent libjpeg from failing on incomplete decode
            dinfo->output_scanline = dstHeight;

            // Finish the decode and indicate that the input was incomplete.
            chromium_jpeg_finish_decompress(dinfo);
            return fDecoderMgr->returnFailure("Incomplete image data", kIncompleteInput);
        }

        // Convert to RGBA if necessary
        if (JCS_CMYK == dinfo->out_color_space) {
            convert_CMYK_to_RGBA(dstRow, dstInfo.width());
        }

        // Move to the next row
        dstRow = SkTAddOffset<JSAMPLE>(dstRow, dstRowBytes);
    }
    chromium_jpeg_finish_decompress(dinfo);

    return kSuccess;
}

/*
 * Enable scanline decoding for jpegs
 */
class SkJpegScanlineDecoder : public SkScanlineDecoder {
public:
    SkJpegScanlineDecoder(const SkImageInfo& srcInfo, SkJpegCodec* codec)
        : INHERITED(srcInfo)
        , fCodec(codec)
        , fOpts()
    {}

    /*
    * Return a valid set of output dimensions for this decoder, given an input scale
    */  
    SkISize onGetScaledDimensions(float desiredScale) override {
        return fCodec->onGetScaledDimensions(desiredScale);
    }

    /*
     * Create the swizzler based on the encoded format.
     * The swizzler is only used for sampling in the x direction.
     */

    SkCodec::Result initializeSwizzler(const SkImageInfo& info, const SkCodec::Options& options) {
        SkSwizzler::SrcConfig srcConfig;
        switch (info.colorType()) {
            case kGray_8_SkColorType:
                srcConfig = SkSwizzler::kGray;
                break;
            case kRGBA_8888_SkColorType:
                srcConfig = SkSwizzler::kRGBX;
                break;
            case kBGRA_8888_SkColorType:
                srcConfig = SkSwizzler::kBGRX;
                break;
            case kRGB_565_SkColorType:
                srcConfig = SkSwizzler::kRGB_565;
                break;
            default:
                //would have exited before now if the colorType was supported by jpeg
                SkASSERT(false);
        }

        fSwizzler.reset(SkSwizzler::CreateSwizzler(srcConfig, NULL, info, options.fZeroInitialized, 
                                                   this->getInfo()));
        if (!fSwizzler) {
            // FIXME: CreateSwizzler could fail for another reason.
            return SkCodec::kUnimplemented;
        }
        return SkCodec::kSuccess;
    }

    SkCodec::Result onStart(const SkImageInfo& dstInfo, const SkCodec::Options& options,
                            SkPMColor ctable[], int* ctableCount) override {

        // Rewind the stream if needed
        if (!fCodec->rewindIfNeeded()) {
            return SkCodec::kCouldNotRewind;
        }

        // Set the jump location for libjpeg errors
        if (setjmp(fCodec->fDecoderMgr->getJmpBuf())) {
            SkCodecPrintf("setjmp: Error from libjpeg\n");
            return SkCodec::kInvalidInput;
        }

        // Check if we can decode to the requested destination and set the output color space
        if (!fCodec->setOutputColorSpace(dstInfo)) {
            return SkCodec::kInvalidConversion;
        }

        // Perform the necessary scaling
        if (!fCodec->nativelyScaleToDimensions(dstInfo.width(), dstInfo.height())) {
            // full native scaling to dstInfo dimensions not supported

            if (!SkScaledCodec::DimensionsSupportedForSampling(this->getInfo(), dstInfo)) {
                return SkCodec::kInvalidScale;
            }
            // create swizzler for sampling
            SkCodec::Result result = this->initializeSwizzler(dstInfo, options);
            if (SkCodec::kSuccess != result) {
                SkCodecPrintf("failed to initialize the swizzler.\n");
                return result;
            }
            fStorage.reset(get_row_bytes(fCodec->fDecoderMgr->dinfo()));
            fSrcRow = static_cast<uint8_t*>(fStorage.get());
        } else {
            fSrcRow = NULL;
            fSwizzler.reset(NULL);
        }

        // Now, given valid output dimensions, we can start the decompress
        if (!chromium_jpeg_start_decompress(fCodec->fDecoderMgr->dinfo())) {
            SkCodecPrintf("start decompress failed\n");
            return SkCodec::kInvalidInput;
        }

        fOpts = options;

        return SkCodec::kSuccess;
    }

    virtual ~SkJpegScanlineDecoder() {
        if (setjmp(fCodec->fDecoderMgr->getJmpBuf())) {
            SkCodecPrintf("setjmp: Error in libjpeg finish_decompress\n");
            return;
        }

        // We may not have decoded the entire image.  Prevent libjpeg-turbo from failing on a
        // partial decode.
        fCodec->fDecoderMgr->dinfo()->output_scanline = fCodec->getInfo().height();
        chromium_jpeg_finish_decompress(fCodec->fDecoderMgr->dinfo());
    }

    SkCodec::Result onGetScanlines(void* dst, int count, size_t rowBytes) override {
        // Set the jump location for libjpeg errors
        if (setjmp(fCodec->fDecoderMgr->getJmpBuf())) {
            return fCodec->fDecoderMgr->returnFailure("setjmp", SkCodec::kInvalidInput);
        }
        // Read rows one at a time
        JSAMPLE* dstRow;
        if (fSwizzler) {
            // write data to storage row, then sample using swizzler         
            dstRow = fSrcRow;
        } else {
            // write data directly to dst
            dstRow = (JSAMPLE*) dst;
        }

        for (int y = 0; y < count; y++) {
            // Read row of the image
            uint32_t rowsDecoded =
                    chromium_jpeg_read_scanlines(fCodec->fDecoderMgr->dinfo(), &dstRow, 1);
            if (rowsDecoded != 1) {
                if (SkCodec::kNo_ZeroInitialized == fOpts.fZeroInitialized ||
                        kN32_SkColorType == this->dstInfo().colorType()) {
                    SkSwizzler::Fill(dstRow, this->dstInfo(), rowBytes,
                            count - y, SK_ColorBLACK, NULL);
                }
                fCodec->fDecoderMgr->dinfo()->output_scanline = this->dstInfo().height();
                return SkCodec::kIncompleteInput;
            }

            // Convert to RGBA if necessary
            if (JCS_CMYK == fCodec->fDecoderMgr->dinfo()->out_color_space) {
                convert_CMYK_to_RGBA(dstRow, fCodec->fDecoderMgr->dinfo()->output_width);
            }

            if(fSwizzler) {
                // use swizzler to sample row
                fSwizzler->swizzle(dst, dstRow);
                dst = SkTAddOffset<JSAMPLE>(dst, rowBytes);
            } else {
                dstRow = SkTAddOffset<JSAMPLE>(dstRow, rowBytes);
            }
        }
        return SkCodec::kSuccess;
    }

#ifndef TURBO_HAS_SKIP
// TODO (msarett): Make this a member function and avoid reallocating the
//                 memory buffer on each call to skip.
#define chromium_jpeg_skip_scanlines(dinfo, count)                           \
    SkAutoMalloc storage(get_row_bytes(dinfo));                              \
    uint8_t* storagePtr = static_cast<uint8_t*>(storage.get());              \
    for (int y = 0; y < count; y++) {                                        \
        chromium_jpeg_read_scanlines(dinfo, &storagePtr, 1);                 \
    }
#endif

    SkCodec::Result onSkipScanlines(int count) override {
        // Set the jump location for libjpeg errors
        if (setjmp(fCodec->fDecoderMgr->getJmpBuf())) {
            return fCodec->fDecoderMgr->returnFailure("setjmp", SkCodec::kInvalidInput);
        }

        chromium_jpeg_skip_scanlines(fCodec->fDecoderMgr->dinfo(), count);

        return SkCodec::kSuccess;
    }

    SkEncodedFormat onGetEncodedFormat() const override {
        return kJPEG_SkEncodedFormat;
    }

private:
    SkAutoTDelete<SkJpegCodec> fCodec;
    SkAutoMalloc               fStorage;    // Only used if sampling is needed
    uint8_t*                   fSrcRow;     // Only used if sampling is needed
    SkCodec::Options           fOpts;
    SkAutoTDelete<SkSwizzler>  fSwizzler;

    typedef SkScanlineDecoder INHERITED;
};

SkScanlineDecoder* SkJpegCodec::NewSDFromStream(SkStream* stream) {
    SkAutoTDelete<SkJpegCodec> codec(static_cast<SkJpegCodec*>(SkJpegCodec::NewFromStream(stream)));
    if (!codec) {
        return NULL;
    }

    const SkImageInfo& srcInfo = codec->getInfo();

    // Return the new scanline decoder
    return SkNEW_ARGS(SkJpegScanlineDecoder, (srcInfo, codec.detach()));
}
