/*
 * Copyright (C) 2009 Torch Mobile, Inc. All rights reserved.
 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public License
 *  along with this library; see the file COPYING.LIB.  If not, write to
 *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 *  Boston, MA 02110-1301, USA.
 */


#include "config.h"
#include "JPEGImageEncoder.h"

#include "IntSize.h"
// FIXME: jpeglib.h requires stdio.h to be included first for FILE
#include <stdio.h>
#include <jpeglib.h>
#include <setjmp.h>

namespace WebCore {

class JPEGDestinationManager : public jpeg_destination_mgr {
public:
    explicit JPEGDestinationManager(Vector<char>& toDump)
        : m_dump(toDump)
    {
        // Zero base class memory.
        jpeg_destination_mgr* base = this;
        memset(base, 0, sizeof(jpeg_destination_mgr));
    }
    Vector<char> m_buffer;
    Vector<char>& m_dump;
};

class JPEGCompressErrorMgr : public jpeg_error_mgr {
public:
    JPEGCompressErrorMgr()
    {
        // Zero memory
        memset(this, 0, sizeof(JPEGCompressErrorMgr));
    }

    jmp_buf m_setjmpBuffer;
};

static void jpegInitializeDestination(j_compress_ptr compressData)
{
    JPEGDestinationManager* dest = static_cast<JPEGDestinationManager*>(compressData->dest);
    dest->m_buffer.resize(4096);
    dest->next_output_byte = reinterpret_cast<JOCTET*>(dest->m_buffer.data());
    dest->free_in_buffer = dest->m_buffer.size();
}

static boolean jpegEmptyOutputBuffer(j_compress_ptr compressData)
{
    JPEGDestinationManager* dest = static_cast<JPEGDestinationManager*>(compressData->dest);
    dest->m_dump.append(dest->m_buffer.data(), dest->m_buffer.size());
    dest->next_output_byte  = reinterpret_cast<JOCTET*>(dest->m_buffer.data());
    dest->free_in_buffer    = dest->m_buffer.size();
    return TRUE;
}

static void jpegTerminateDestination(j_compress_ptr compressData)
{
    JPEGDestinationManager* dest = static_cast<JPEGDestinationManager*>(compressData->dest);
    dest->m_dump.append(dest->m_buffer.data(), dest->m_buffer.size() - dest->free_in_buffer);
}

static void jpegErrorExit(j_common_ptr compressData)
{
    JPEGCompressErrorMgr* err = static_cast<JPEGCompressErrorMgr*>(compressData->err);
    longjmp(err->m_setjmpBuffer, -1);
}

bool compressRGBABigEndianToJPEG(unsigned char* rgbaBigEndianData, const IntSize& size, Vector<char>& jpegData, std::optional<double> quality)
{
    struct jpeg_compress_struct compressData;
    JPEGCompressErrorMgr err;
    compressData.err = jpeg_std_error(&err);
    err.error_exit = jpegErrorExit;

    jpeg_create_compress(&compressData);

    JPEGDestinationManager dest(jpegData);
    compressData.dest = &dest;
    dest.init_destination = jpegInitializeDestination;
    dest.empty_output_buffer = jpegEmptyOutputBuffer;
    dest.term_destination = jpegTerminateDestination;

    compressData.image_width = size.width();
    compressData.image_height = size.height();
    compressData.input_components = 3;
    compressData.in_color_space = JCS_RGB;
    jpeg_set_defaults(&compressData);
    int compressionQuality = 65;

    if (quality && *quality >= 0.0 && *quality <= 1.0)
        compressionQuality = static_cast<int>(*quality * 100 + 0.5);

    jpeg_set_quality(&compressData, compressionQuality, TRUE);

    // rowBuffer must be defined here so that its destructor is always called even when "setjmp" catches an error.
    Vector<JSAMPLE, 600 * 3> rowBuffer;

    if (setjmp(err.m_setjmpBuffer)) {
        jpeg_destroy_compress(&compressData);
        return false;
    }

    jpeg_start_compress(&compressData, TRUE);
    rowBuffer.grow(compressData.image_width * 3);

    // add offset to prevent clobbered error caused by setjmp and longjmp.
    unsigned offset = 0;
    const unsigned char* pixel = rgbaBigEndianData;
    const unsigned char* pixelEnd = pixel + compressData.image_width * compressData.image_height * 4;
    while (pixel + offset < pixelEnd) {
        JSAMPLE* output = rowBuffer.data();
        for (const unsigned char* rowEnd = pixel + offset + compressData.image_width * 4; pixel + offset < rowEnd;) {
            *output++ = static_cast<JSAMPLE>(*(pixel + offset++) & 0xFF); // red
            *output++ = static_cast<JSAMPLE>(*(pixel + offset++) & 0xFF); // green
            *output++ = static_cast<JSAMPLE>(*(pixel + offset++) & 0xFF); // blue
            ++offset; // skip alpha
        }
        output = rowBuffer.data();
        jpeg_write_scanlines(&compressData, &output, 1);
    }

    jpeg_finish_compress(&compressData);
    jpeg_destroy_compress(&compressData);
    return true;
}

} // namespace WebCore
