1a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk/*
2a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk * Copyright (C) 2013 The Android Open Source Project
3a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk *
4a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk * Licensed under the Apache License, Version 2.0 (the "License");
5a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk * you may not use this file except in compliance with the License.
6a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk * You may obtain a copy of the License at
7a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk *
8a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk *      http://www.apache.org/licenses/LICENSE-2.0
9a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk *
10a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk * Unless required by applicable law or agreed to in writing, software
11a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk * distributed under the License is distributed on an "AS IS" BASIS,
12a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk * See the License for the specific language governing permissions and
14a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk * limitations under the License.
15a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk */
16a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk
17a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk#include "jpeg_reader.h"
18a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk#include "error_codes.h"
19a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk#include "jpeg_hook.h"
20a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk
21a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk#include <setjmp.h>
22a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk
23a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben BrunkJpegReader::JpegReader() :
24a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk                mInfo(),
25a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk                mErrorManager(),
26a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk                mScanlineBuf(NULL),
27a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk                mScanlineIter(NULL),
28a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk                mScanlineBuflen(0),
29a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk                mScanlineUnformattedBuflen(0),
30a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk                mScanlineBytesRemaining(0),
31a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk                mFormat(),
32a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk                mFinished(false),
33a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk                mSetup(false) {}
34a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk
35a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben BrunkJpegReader::~JpegReader() {
36a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    if (reset() != J_SUCCESS) {
37a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        LOGE("Failed to destroy compress object, JpegReader may leak memory.");
38a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    }
39a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk}
40a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk
41a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunkint32_t JpegReader::setup(JNIEnv *env, jobject in, int32_t* width, int32_t* height,
42a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        Jpeg_Config::Format format) {
43a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    if (mFinished || mSetup) {
44a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        return J_ERROR_FATAL;
45a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    }
46a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    if (env->ExceptionCheck()) {
47a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        return J_EXCEPTION;
48a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    }
49a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk
50a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    // Setup error handler
51a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    SetupErrMgr(reinterpret_cast<j_common_ptr>(&mInfo), &mErrorManager);
52a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    // Set jump address for error handling
53a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    if (setjmp(mErrorManager.setjmp_buf)) {
54a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        return J_ERROR_FATAL;
55a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    }
56a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk
57a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    // Call libjpeg setup
58a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    jpeg_create_decompress(&mInfo);
59a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk
60a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    // Setup our data source object, this allocates java global references
61a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    int32_t flags = MakeSrc(&mInfo, env, in);
62a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    if (flags != J_SUCCESS) {
63a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        LOGE("Failed to make source with error code: %d ", flags);
64a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        return flags;
65a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    }
66a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk
67a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    // Reads jpeg file header
68a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    jpeg_read_header(&mInfo, TRUE);
69a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    jpeg_calc_output_dimensions(&mInfo);
70a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk
71a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    const int components = (static_cast<int>(format) & 0xff);
72a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk
73a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    // Do setup for input format
74a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    switch (components) {
75a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    case 1:
76a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        mInfo.out_color_space = JCS_GRAYSCALE;
77a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        mScanlineUnformattedBuflen = mInfo.output_width;
78a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        break;
79a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    case 3:
80a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    case 4:
81a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        mScanlineUnformattedBuflen = mInfo.output_width * components;
82a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        if (mInfo.jpeg_color_space == JCS_CMYK
83a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk                || mInfo.jpeg_color_space == JCS_YCCK) {
84a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            // Always use cmyk for output in a 4 channel jpeg.
85a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            // libjpeg has a builtin cmyk->rgb decoder.
86a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            mScanlineUnformattedBuflen = mInfo.output_width * 4;
87a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            mInfo.out_color_space = JCS_CMYK;
88a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        } else {
89a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            mInfo.out_color_space = JCS_RGB;
90a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        }
91a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        break;
92a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    default:
93a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        return J_ERROR_BAD_ARGS;
94a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    }
95a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk
96a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    mScanlineBuflen = mInfo.output_width * components;
97a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    mScanlineBytesRemaining = mScanlineBuflen;
98a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    mScanlineBuf = (JSAMPLE *) (mInfo.mem->alloc_small)(
99a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            reinterpret_cast<j_common_ptr>(&mInfo), JPOOL_PERMANENT,
100a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            mScanlineUnformattedBuflen * sizeof(JSAMPLE));
101a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    mScanlineIter = mScanlineBuf;
102a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    jpeg_start_decompress(&mInfo);
103a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk
104a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    // Output image dimensions
105a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    if (width != NULL) {
106a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        *width = mInfo.output_width;
107a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    }
108a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    if (height != NULL) {
109a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        *height = mInfo.output_height;
110a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    }
111a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk
112a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    mFormat = format;
113a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    mSetup = true;
114a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    return J_SUCCESS;
115a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk}
116a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk
117a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunkint32_t JpegReader::read(int8_t* bytes, int32_t offset, int32_t count) {
118a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    if (!mSetup) {
119a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        return J_ERROR_FATAL;
120a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    }
121a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    if (mFinished) {
122a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        return J_DONE;
123a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    }
124a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    // Set jump address for error handling
125a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    if (setjmp(mErrorManager.setjmp_buf)) {
126a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        return J_ERROR_FATAL;
127a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    }
128a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    if (count <= 0) {
129a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        return J_ERROR_BAD_ARGS;
130a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    }
131a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    int32_t total_length = count;
132a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    while (mInfo.output_scanline < mInfo.output_height) {
133a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        if (count < mScanlineBytesRemaining) {
134a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            // read partial scanline and return
135a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            if (bytes != NULL) {
136a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk                // Treat NULL bytes as a skip
137a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk                memcpy((void*) (bytes + offset), (void*) mScanlineIter,
138a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk                        count * sizeof(int8_t));
139a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            }
140a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            mScanlineBytesRemaining -= count;
141a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            mScanlineIter += count;
142a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            return total_length;
143a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        } else if (count > 0) {
144a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            // read full scanline
145a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            if (bytes != NULL) {
146a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk                // Treat NULL bytes as a skip
147a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk                memcpy((void*) (bytes + offset), (void*) mScanlineIter,
148a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk                        mScanlineBytesRemaining * sizeof(int8_t));
149a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk                bytes += mScanlineBytesRemaining;
150a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            }
151a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            count -= mScanlineBytesRemaining;
152a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            mScanlineBytesRemaining = 0;
153a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        }
154a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        // Scanline buffer exhausted, read next scanline
155a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        if (jpeg_read_scanlines(&mInfo, &mScanlineBuf, 1) != 1) {
156a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            // Always read full scanline, no IO suspension
157a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            return J_ERROR_FATAL;
158a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        }
159a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        // Do in-place pixel formatting
160a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        formatPixels(static_cast<uint8_t*>(mScanlineBuf),
161a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk                mScanlineUnformattedBuflen);
162a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk
163a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        // Reset iterators
164a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        mScanlineIter = mScanlineBuf;
165a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        mScanlineBytesRemaining = mScanlineBuflen;
166a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    }
167a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk
168a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    // Read all of the scanlines
169a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    jpeg_finish_decompress(&mInfo);
170a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    mFinished = true;
171a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    return total_length - count;
172a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk}
173a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk
174a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunkvoid JpegReader::updateEnv(JNIEnv *env) {
175a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    UpdateSrcEnv(&mInfo, env);
176a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk}
177a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk
178a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk// Does in-place pixel formatting
179a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunkvoid JpegReader::formatPixels(uint8_t* buf, int32_t len) {
180a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    uint8_t *iter = buf;
181a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk
182a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    // Do cmyk->rgb conversion if necessary
183a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    switch (mInfo.out_color_space) {
184a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    case JCS_CMYK:
185a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        // Convert CMYK to RGB
186a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        int r, g, b, c, m, y, k;
187a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        for (int i = 0; i < len; i += 4) {
188a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            c = buf[i + 0];
189a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            m = buf[i + 1];
190a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            y = buf[i + 2];
191a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            k = buf[i + 3];
192a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            // Handle fmt for weird photoshop markers
193a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            if (mInfo.saw_Adobe_marker) {
194a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk                r = (k * c) / 255;
195a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk                g = (k * m) / 255;
196a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk                b = (k * y) / 255;
197a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            } else {
198a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk                r = (255 - k) * (255 - c) / 255;
199a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk                g = (255 - k) * (255 - m) / 255;
200a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk                b = (255 - k) * (255 - y) / 255;
201a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            }
202a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            *iter++ = r;
203a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            *iter++ = g;
204a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            *iter++ = b;
205a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        }
206a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        break;
207a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    case JCS_RGB:
208a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        iter += (len * 3 / 4);
209a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        break;
210a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    case JCS_GRAYSCALE:
211a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    default:
212a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        return;
213a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    }
214a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk
215a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    // Do endianness and alpha for output format
216a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    if (mFormat == Jpeg_Config::FORMAT_RGBA) {
217a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        // Set alphas to 255
218a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        for (int i = len - 1; i >= 0; i -= 4) {
219a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            buf[i] = 255;
220a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            buf[i - 1] = *--iter;
221a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            buf[i - 2] = *--iter;
222a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            buf[i - 3] = *--iter;
223a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        }
224a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    } else if (mFormat == Jpeg_Config::FORMAT_ABGR) {
225a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        // Reverse endianness and set alphas to 255
226a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        int r, g, b;
227a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        for (int i = len - 1; i >= 0; i -= 4) {
228a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            b = *--iter;
229a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            g = *--iter;
230a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            r = *--iter;
231a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            buf[i] = r;
232a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            buf[i - 1] = g;
233a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            buf[i - 2] = b;
234a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk            buf[i - 3] = 255;
235a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        }
236a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    }
237a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk}
238a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk
239a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunkint32_t JpegReader::reset() {
240a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    // Set jump address for error handling
241a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    if (setjmp(mErrorManager.setjmp_buf)) {
242a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk        return J_ERROR_FATAL;
243a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    }
244a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    // Clean up global java references
245a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    CleanSrc(&mInfo);
246a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    // Wipe decompress struct, free memory pools
247a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    jpeg_destroy_decompress(&mInfo);
248a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    mFinished = false;
249a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    mSetup = false;
250a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk    return J_SUCCESS;
251a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk}
252a8221bbdb8ece9b02dbf7b72565f9fbc5b314f7cRuben Brunk
253