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