bool JPEGImageEncoder::encodeWithPreInitializedState(PassOwnPtr<JPEGImageEncoderState> encoderState, const unsigned char* inputPixels)
{
    JPEGImageEncoderStateImpl* encoderStateImpl = static_cast<JPEGImageEncoderStateImpl*>(encoderState.get());

    Vector<JSAMPLE> row;
    row.resize(encoderStateImpl->cinfo()->image_width * encoderStateImpl->cinfo()->input_components);

    jmp_buf jumpBuffer;
    encoderStateImpl->cinfo()->client_data = &jumpBuffer;

    if (setjmp(jumpBuffer)) {
        return false;
    }

    unsigned char* pixels = const_cast<unsigned char*>(inputPixels);
    const size_t pixelRowStride = encoderStateImpl->cinfo()->image_width * 4;
    while (encoderStateImpl->cinfo()->next_scanline < encoderStateImpl->cinfo()->image_height) {
        JSAMPLE* rowData = row.data();
        RGBAtoRGB(pixels, encoderStateImpl->cinfo()->image_width, rowData);
        jpeg_write_scanlines(encoderStateImpl->cinfo(), &rowData, 1);
        pixels += pixelRowStride;
    }

    jpeg_finish_compress(encoderStateImpl->cinfo());
    return true;
}
bool JPEGImageEncoder::encodeWithPreInitializedState(std::unique_ptr<JPEGImageEncoderState> encoderState, const unsigned char* inputPixels, int numRowsCompleted)
{
    JPEGImageEncoderStateImpl* encoderStateImpl = static_cast<JPEGImageEncoderStateImpl*>(encoderState.get());

    Vector<JSAMPLE> row;
    row.resize(encoderStateImpl->cinfo()->image_width * encoderStateImpl->cinfo()->input_components);

    SET_JUMP_BUFFER(encoderStateImpl->cinfo(), false);

    const size_t pixelRowStride = encoderStateImpl->cinfo()->image_width * 4;
    unsigned char* pixels = const_cast<unsigned char*>(inputPixels) + pixelRowStride * numRowsCompleted;
    while (encoderStateImpl->cinfo()->next_scanline < encoderStateImpl->cinfo()->image_height) {
        JSAMPLE* rowData = row.data();
        RGBAtoRGB(pixels, encoderStateImpl->cinfo()->image_width, rowData);
        jpeg_write_scanlines(encoderStateImpl->cinfo(), &rowData, 1);
        pixels += pixelRowStride;
    }

    jpeg_finish_compress(encoderStateImpl->cinfo());
    return true;
}
int JPEGImageEncoder::progressiveEncodeRowsJpegHelper(JPEGImageEncoderState* encoderState, unsigned char* data, int currentRowsCompleted, const double SlackBeforeDeadline, double deadlineSeconds)
{
    JPEGImageEncoderStateImpl* encoderStateImpl = static_cast<JPEGImageEncoderStateImpl*>(encoderState);
    Vector<JSAMPLE> row(encoderStateImpl->cinfo()->image_width * encoderStateImpl->cinfo()->input_components);
    SET_JUMP_BUFFER(encoderStateImpl->cinfo(), ProgressiveEncodeFailed);

    const size_t pixelRowStride = encoderStateImpl->cinfo()->image_width * 4;
    unsigned char* pixels = data + pixelRowStride * currentRowsCompleted;

    while (encoderStateImpl->cinfo()->next_scanline < encoderStateImpl->cinfo()->image_height) {
        JSAMPLE* rowData = row.data();
        RGBAtoRGB(pixels, encoderStateImpl->cinfo()->image_width, rowData);
        jpeg_write_scanlines(encoderStateImpl->cinfo(), &rowData, 1);
        pixels += pixelRowStride;
        currentRowsCompleted++;

        if (deadlineSeconds - SlackBeforeDeadline - monotonicallyIncreasingTime() <= 0) {
            return currentRowsCompleted;
        }
    }

    jpeg_finish_compress(encoderStateImpl->cinfo());
    return currentRowsCompleted;
}