/*
 * 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 "jerror.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(new 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 != jpeg_read_header(decoderMgr->dinfo(), true)) {
        return decoderMgr->returnFalse("read_header");
    }

    if (nullptr != 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 = new SkJpegCodec(imageInfo, stream, decoderMgr.detach());
    } else {
        SkASSERT(nullptr != decoderMgrOut);
        *decoderMgrOut = decoderMgr.detach();
    }
    return true;
}

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

SkJpegCodec::SkJpegCodec(const SkImageInfo& srcInfo, SkStream* stream,
        JpegDecoderMgr* decoderMgr)
    : INHERITED(srcInfo, stream)
    , fDecoderMgr(decoderMgr)
    , fReadyState(decoderMgr->dinfo()->global_state)
{}

/*
 * 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 = fReadyState;
    dinfo.num_components = 0;
    dinfo.scale_num = num;
    dinfo.scale_denom = denom;
    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 = nullptr;
    if (!ReadHeader(this->stream(), nullptr, &decoderMgr)) {
        return fDecoderMgr->returnFalse("could not rewind");
    }
    SkASSERT(nullptr != 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;
    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;
            jpeg_calc_output_dimensions(this->fDecoderMgr->dinfo());
            return false;
        }

        // Try the next scale
        fDecoderMgr->dinfo()->scale_num -= 1;
        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 (!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 = 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.
            SkSwizzler::Fill(dstRow, dstInfo, dstRowBytes, dstHeight - y,
                    SK_ColorBLACK, nullptr, options.fZeroInitialized);

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

            // Finish the decode and indicate that the input was incomplete.
            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);
    }
    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, nullptr, 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 = nullptr;
            fSwizzler.reset(nullptr);
        }

        // Now, given valid output dimensions, we can start the decompress
        if (!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();
        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 = jpeg_read_scanlines(fCodec->fDecoderMgr->dinfo(), &dstRow, 1);
            if (rowsDecoded != 1) {
                SkSwizzler::Fill(dstRow, this->dstInfo(), rowBytes, count - y,
                        SK_ColorBLACK, nullptr, fOpts.fZeroInitialized);
                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 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++) {                                        \
        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);
        }

        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 nullptr;
    }

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

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