1ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Copyright 2014 PDFium Authors. All rights reserved. 2ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Use of this source code is governed by a BSD-style license that can be 3ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// found in the LICENSE file. 4ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 5ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 7ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../../include/fxcodec/fx_codec.h" 8ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "codec_int.h" 9ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../fx_libopenjpeg/libopenjpeg20/openjpeg.h" 10ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../lcms2/include/fx_lcms2.h" 11ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic void fx_error_callback(const char *msg, void *client_data) 12ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 13ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (void)client_data; 14ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 15ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic void fx_warning_callback(const char *msg, void *client_data) 16ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 17ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (void)client_data; 18ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 19ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic void fx_info_callback(const char *msg, void *client_data) 20ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 21ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (void)client_data; 22ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 23ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovtypedef struct { 24ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const unsigned char* src_data; 25ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int src_size; 26ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int offset; 27ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} decodeData; 28ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic OPJ_SIZE_T opj_read_from_memory (void * p_buffer, OPJ_SIZE_T p_nb_bytes, decodeData* srcData) 29ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 30ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if(srcData == NULL || srcData->src_size == 0 || srcData->src_data == NULL || srcData->offset >= srcData->src_size) { 31ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 32ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 33ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov OPJ_SIZE_T readlength = p_nb_bytes; 34ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov OPJ_SIZE_T bufferLength = (OPJ_SIZE_T)(srcData->src_size - srcData->offset); 35ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if(bufferLength <= 0) { 36ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 37ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 38ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if(bufferLength <= p_nb_bytes) { 39ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov readlength = bufferLength; 40ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 41ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memcpy(p_buffer, &(srcData->src_data[srcData->offset]), readlength); 42ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov srcData->offset += (int)readlength; 43ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return readlength; 44ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 45ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic OPJ_SIZE_T opj_write_from_memory (void * p_buffer, OPJ_SIZE_T p_nb_bytes, decodeData* srcData) 46ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 47ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if(srcData == NULL || srcData->src_size == 0 || srcData->src_data == NULL || srcData->offset >= srcData->src_size) { 48ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 49ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 50ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov OPJ_SIZE_T writeLength = p_nb_bytes; 51ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov OPJ_SIZE_T bufferLength = (OPJ_SIZE_T)(srcData->src_size - srcData->offset); 52ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if(bufferLength <= p_nb_bytes) { 53ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov writeLength = bufferLength; 54ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 55ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memcpy((void*&)(srcData->src_data[srcData->offset]), p_buffer, writeLength); 56ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov srcData->offset += (int)writeLength; 57ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return writeLength; 58ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 59ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic OPJ_OFF_T opj_skip_from_memory (OPJ_OFF_T p_nb_bytes, decodeData* srcData) 60ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 61ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if(srcData == NULL || srcData->src_size == 0 || srcData->src_data == NULL || srcData->offset >= srcData->src_size) { 62ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 63ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 64ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov OPJ_OFF_T postion = srcData->offset + p_nb_bytes; 65ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if(postion < 0 ) { 66ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov postion = 0; 67ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else if (postion > srcData->src_size) { 68ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 69ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov srcData->offset = (int)postion; 70ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return p_nb_bytes; 71ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 72ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic OPJ_BOOL opj_seek_from_memory (OPJ_OFF_T p_nb_bytes, decodeData * srcData) 73ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 74ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if(srcData == NULL || srcData->src_size == 0 || srcData->src_data == NULL || srcData->offset >= srcData->src_size) { 75ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 76ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 77ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov srcData->offset = (int)p_nb_bytes; 78ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if(srcData->offset < 0) { 79ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov srcData->offset = 0; 80ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else if(srcData->offset > srcData->src_size) { 81ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov srcData->offset = srcData->src_size; 82ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 83ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return OPJ_TRUE; 84ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 85ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovopj_stream_t* fx_opj_stream_create_memory_stream (decodeData* data, OPJ_SIZE_T p_size, OPJ_BOOL p_is_read_stream) 86ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 87ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov opj_stream_t* l_stream = 00; 88ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!data || ! data->src_data || data->src_size <= 0 ) { 89ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 90ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 91ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov l_stream = opj_stream_create(p_size, p_is_read_stream); 92ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (! l_stream) { 93ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 94ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 95ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov opj_stream_set_user_data_v3(l_stream, data, NULL); 96ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov opj_stream_set_user_data_length(l_stream, data->src_size); 97ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov opj_stream_set_read_function(l_stream, (opj_stream_read_fn) opj_read_from_memory); 98ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov opj_stream_set_write_function(l_stream, (opj_stream_write_fn) opj_write_from_memory); 99ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov opj_stream_set_skip_function(l_stream, (opj_stream_skip_fn) opj_skip_from_memory); 100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov opj_stream_set_seek_function(l_stream, (opj_stream_seek_fn) opj_seek_from_memory); 101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return l_stream; 102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic void sycc_to_rgb(int offset, int upb, int y, int cb, int cr, 104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int *out_r, int *out_g, int *out_b) 105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int r, g, b; 107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cb -= offset; 108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cr -= offset; 109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov r = y + (int)(1.402 * (float)cr); 110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if(r < 0) { 111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov r = 0; 112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else if(r > upb) { 113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov r = upb; 114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } *out_r = r; 115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov g = y - (int)(0.344 * (float)cb + 0.714 * (float)cr); 116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if(g < 0) { 117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov g = 0; 118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else if(g > upb) { 119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov g = upb; 120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } *out_g = g; 121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov b = y + (int)(1.772 * (float)cb); 122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if(b < 0) { 123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov b = 0; 124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else if(b > upb) { 125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov b = upb; 126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } *out_b = b; 127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic void sycc444_to_rgb(opj_image_t *img) 129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int *d0, *d1, *d2, *r, *g, *b; 131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const int *y, *cb, *cr; 132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int maxw, maxh, max, i, offset, upb; 133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov i = (int)img->comps[0].prec; 134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov offset = 1 << (i - 1); 135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov upb = (1 << i) - 1; 136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov maxw = (int)img->comps[0].w; 137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov maxh = (int)img->comps[0].h; 138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov max = maxw * maxh; 139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y = img->comps[0].data; 140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cb = img->comps[1].data; 141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cr = img->comps[2].data; 142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov d0 = r = FX_Alloc(int, (size_t)max); 143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov d1 = g = FX_Alloc(int, (size_t)max); 144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov d2 = b = FX_Alloc(int, (size_t)max); 145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for(i = 0; i < max; ++i) { 146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b); 147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++y; 148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++cb; 149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++cr; 150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++r; 151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++g; 152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++b; 153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_Free(img->comps[0].data); 155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov img->comps[0].data = d0; 156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_Free(img->comps[1].data); 157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov img->comps[1].data = d1; 158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_Free(img->comps[2].data); 159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov img->comps[2].data = d2; 160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic void sycc422_to_rgb(opj_image_t *img) 162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int *d0, *d1, *d2, *r, *g, *b; 164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const int *y, *cb, *cr; 165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int maxw, maxh, max, offset, upb; 166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int i, j; 167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov i = (int)img->comps[0].prec; 168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov offset = 1 << (i - 1); 169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov upb = (1 << i) - 1; 170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov maxw = (int)img->comps[0].w; 171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov maxh = (int)img->comps[0].h; 172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov max = maxw * maxh; 173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y = img->comps[0].data; 174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cb = img->comps[1].data; 175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cr = img->comps[2].data; 176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov d0 = r = FX_Alloc(int, (size_t)max); 177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov d1 = g = FX_Alloc(int, (size_t)max); 178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov d2 = b = FX_Alloc(int, (size_t)max); 179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for(i = 0; i < maxh; ++i) { 180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for(j = 0; j < maxw; j += 2) { 181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b); 182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++y; 183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++r; 184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++g; 185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++b; 186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b); 187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++y; 188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++r; 189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++g; 190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++b; 191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++cb; 192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++cr; 193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_Free(img->comps[0].data); 196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov img->comps[0].data = d0; 197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_Free(img->comps[1].data); 198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov img->comps[1].data = d1; 199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_Free(img->comps[2].data); 200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov img->comps[2].data = d2; 201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov img->comps[1].w = maxw; 202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov img->comps[1].h = maxh; 203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov img->comps[2].w = maxw; 204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov img->comps[2].h = maxh; 205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov img->comps[1].w = (OPJ_UINT32)maxw; 206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov img->comps[1].h = (OPJ_UINT32)maxh; 207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov img->comps[2].w = (OPJ_UINT32)maxw; 208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov img->comps[2].h = (OPJ_UINT32)maxh; 209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov img->comps[1].dx = img->comps[0].dx; 210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov img->comps[2].dx = img->comps[0].dx; 211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov img->comps[1].dy = img->comps[0].dy; 212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov img->comps[2].dy = img->comps[0].dy; 213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic void sycc420_to_rgb(opj_image_t *img) 215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int *d0, *d1, *d2, *r, *g, *b, *nr, *ng, *nb; 217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const int *y, *cb, *cr, *ny; 218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int maxw, maxh, max, offset, upb; 219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int i, j; 220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov i = (int)img->comps[0].prec; 221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov offset = 1 << (i - 1); 222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov upb = (1 << i) - 1; 223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov maxw = (int)img->comps[0].w; 224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov maxh = (int)img->comps[0].h; 225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov max = maxw * maxh; 226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y = img->comps[0].data; 227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cb = img->comps[1].data; 228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cr = img->comps[2].data; 229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov d0 = r = FX_Alloc(int, (size_t)max); 230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov d1 = g = FX_Alloc(int, (size_t)max); 231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov d2 = b = FX_Alloc(int, (size_t)max); 232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for(i = 0; i < maxh; i += 2) { 233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ny = y + maxw; 234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov nr = r + maxw; 235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ng = g + maxw; 236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov nb = b + maxw; 237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for(j = 0; j < maxw; j += 2) { 238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b); 239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++y; 240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++r; 241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++g; 242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++b; 243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b); 244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++y; 245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++r; 246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++g; 247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++b; 248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb); 249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++ny; 250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++nr; 251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++ng; 252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++nb; 253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb); 254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++ny; 255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++nr; 256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++ng; 257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++nb; 258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++cb; 259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++cr; 260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y += maxw; 262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov r += maxw; 263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov g += maxw; 264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov b += maxw; 265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_Free(img->comps[0].data); 267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov img->comps[0].data = d0; 268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_Free(img->comps[1].data); 269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov img->comps[1].data = d1; 270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_Free(img->comps[2].data); 271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov img->comps[2].data = d2; 272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov img->comps[1].w = maxw; 273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov img->comps[1].h = maxh; 274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov img->comps[2].w = maxw; 275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov img->comps[2].h = maxh; 276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov img->comps[1].w = (OPJ_UINT32)maxw; 277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov img->comps[1].h = (OPJ_UINT32)maxh; 278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov img->comps[2].w = (OPJ_UINT32)maxw; 279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov img->comps[2].h = (OPJ_UINT32)maxh; 280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov img->comps[1].dx = img->comps[0].dx; 281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov img->comps[2].dx = img->comps[0].dx; 282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov img->comps[1].dy = img->comps[0].dy; 283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov img->comps[2].dy = img->comps[0].dy; 284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid color_sycc_to_rgb(opj_image_t *img) 286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if(img->numcomps < 3) { 288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov img->color_space = OPJ_CLRSPC_GRAY; 289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if((img->comps[0].dx == 1) 292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov && (img->comps[1].dx == 2) 293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov && (img->comps[2].dx == 2) 294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov && (img->comps[0].dy == 1) 295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov && (img->comps[1].dy == 2) 296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov && (img->comps[2].dy == 2)) { 297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sycc420_to_rgb(img); 298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else if((img->comps[0].dx == 1) 299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov && (img->comps[1].dx == 2) 300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov && (img->comps[2].dx == 2) 301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov && (img->comps[0].dy == 1) 302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov && (img->comps[1].dy == 1) 303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov && (img->comps[2].dy == 1)) { 304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sycc422_to_rgb(img); 305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else if((img->comps[0].dx == 1) 306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov && (img->comps[1].dx == 1) 307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov && (img->comps[2].dx == 1) 308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov && (img->comps[0].dy == 1) 309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov && (img->comps[1].dy == 1) 310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov && (img->comps[2].dy == 1)) { 311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sycc444_to_rgb(img); 312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else { 313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov img->color_space = OPJ_CLRSPC_SRGB; 316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid color_apply_icc_profile(opj_image_t *image) 318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsHPROFILE in_prof, out_prof; 320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsHTRANSFORM transform; 321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsColorSpaceSignature in_space, out_space; 322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number intent, in_type, out_type, nr_samples; 323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int *r, *g, *b; 324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int prec, i, max, max_w, max_h; 325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov OPJ_COLOR_SPACE oldspace; 326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov in_prof = 327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsOpenProfileFromMem(image->icc_profile_buf, image->icc_profile_len); 328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if(in_prof == NULL) { 329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov in_space = cmsGetPCS(in_prof); 332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov out_space = cmsGetColorSpace(in_prof); 333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov intent = cmsGetHeaderRenderingIntent(in_prof); 334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov max_w = (int)image->comps[0].w; 335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov max_h = (int)image->comps[0].h; 336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov prec = (int)image->comps[0].prec; 337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov oldspace = image->color_space; 338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if(out_space == cmsSigRgbData) { 339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if( prec <= 8 ) { 340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov in_type = TYPE_RGB_8; 341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov out_type = TYPE_RGB_8; 342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else { 343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov in_type = TYPE_RGB_16; 344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov out_type = TYPE_RGB_16; 345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov out_prof = cmsCreate_sRGBProfile(); 347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov image->color_space = OPJ_CLRSPC_SRGB; 348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else if(out_space == cmsSigGrayData) { 349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if( prec <= 8 ) { 350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov in_type = TYPE_GRAY_8; 351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov out_type = TYPE_RGB_8; 352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else { 353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov in_type = TYPE_GRAY_16; 354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov out_type = TYPE_RGB_16; 355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov out_prof = cmsCreate_sRGBProfile(); 357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov image->color_space = OPJ_CLRSPC_SRGB; 358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else if(out_space == cmsSigYCbCrData) { 359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov in_type = TYPE_YCbCr_16; 360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov out_type = TYPE_RGB_16; 361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov out_prof = cmsCreate_sRGBProfile(); 362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov image->color_space = OPJ_CLRSPC_SRGB; 363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else { 364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov transform = cmsCreateTransform(in_prof, in_type, 367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov out_prof, out_type, intent, 0); 368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsCloseProfile(in_prof); 369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsCloseProfile(out_prof); 370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if(transform == NULL) { 371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov image->color_space = oldspace; 372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if(image->numcomps > 2) { 375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if( prec <= 8 ) { 376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov unsigned char *inbuf, *outbuf, *in, *out; 377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov max = max_w * max_h; 378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov nr_samples = (cmsUInt32Number)max * 3 * (cmsUInt32Number)sizeof(unsigned char); 379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov in = inbuf = FX_Alloc(unsigned char, nr_samples); 380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov out = outbuf = FX_Alloc(unsigned char, nr_samples); 381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov r = image->comps[0].data; 382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov g = image->comps[1].data; 383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov b = image->comps[2].data; 384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for(i = 0; i < max; ++i) { 385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *in++ = (unsigned char) * r++; 386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *in++ = (unsigned char) * g++; 387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *in++ = (unsigned char) * b++; 388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max); 390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov r = image->comps[0].data; 391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov g = image->comps[1].data; 392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov b = image->comps[2].data; 393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for(i = 0; i < max; ++i) { 394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *r++ = (int) * out++; 395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *g++ = (int) * out++; 396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *b++ = (int) * out++; 397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_Free(inbuf); 399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_Free(outbuf); 400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else { 401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov unsigned short *inbuf, *outbuf, *in, *out; 402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov max = max_w * max_h; 403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov nr_samples = (cmsUInt32Number)max * 3 * (cmsUInt32Number)sizeof(unsigned short); 404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov in = inbuf = FX_Alloc(unsigned short, nr_samples); 405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov out = outbuf = FX_Alloc(unsigned short, nr_samples); 406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov r = image->comps[0].data; 407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov g = image->comps[1].data; 408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov b = image->comps[2].data; 409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for(i = 0; i < max; ++i) { 410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *in++ = (unsigned short) * r++; 411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *in++ = (unsigned short) * g++; 412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *in++ = (unsigned short) * b++; 413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max); 415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov r = image->comps[0].data; 416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov g = image->comps[1].data; 417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov b = image->comps[2].data; 418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for(i = 0; i < max; ++i) { 419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *r++ = (int) * out++; 420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *g++ = (int) * out++; 421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *b++ = (int) * out++; 422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_Free(inbuf); 424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_Free(outbuf); 425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else { 427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov unsigned char *in, *inbuf, *out, *outbuf; 428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov max = max_w * max_h; 429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov nr_samples = (cmsUInt32Number)max * 3 * sizeof(unsigned char); 430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov in = inbuf = FX_Alloc(unsigned char, nr_samples); 431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov out = outbuf = FX_Alloc(unsigned char, nr_samples); 432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov image->comps = (opj_image_comp_t*) 433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov realloc(image->comps, (image->numcomps + 2) * sizeof(opj_image_comp_t)); 434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if(image->numcomps == 2) { 435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov image->comps[3] = image->comps[1]; 436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov image->comps[1] = image->comps[0]; 438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov image->comps[2] = image->comps[0]; 439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov image->comps[1].data = FX_Alloc(int, (size_t)max); 440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FXSYS_memset8(image->comps[1].data, 0, sizeof(int) * (size_t)max); 441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov image->comps[2].data = FX_Alloc(int, (size_t)max); 442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FXSYS_memset8(image->comps[2].data, 0, sizeof(int) * (size_t)max); 443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov image->numcomps += 2; 444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov r = image->comps[0].data; 445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for(i = 0; i < max; ++i) { 446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *in++ = (unsigned char) * r++; 447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max); 449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov r = image->comps[0].data; 450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov g = image->comps[1].data; 451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov b = image->comps[2].data; 452ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for(i = 0; i < max; ++i) { 453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *r++ = (int) * out++; 454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *g++ = (int) * out++; 455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *b++ = (int) * out++; 456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_Free(inbuf); 458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_Free(outbuf); 459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsDeleteTransform(transform); 461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid color_apply_conversion(opj_image_t *image) 463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int *row; 465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int enumcs, numcomps; 466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov numcomps = image->numcomps; 467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if(numcomps < 3) { 468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov row = (int*)image->icc_profile_buf; 471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov enumcs = row[0]; 472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if(enumcs == 14) { 473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int *L, *a, *b, *red, *green, *blue, *src0, *src1, *src2; 474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov double rl, ol, ra, oa, rb, ob, prec0, prec1, prec2; 475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov double minL, maxL, mina, maxa, minb, maxb; 476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov unsigned int default_type, il; 477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov unsigned int i, max, illu; 478ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsHPROFILE in, out; 479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsHTRANSFORM transform; 480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt16Number RGB[3]; 481ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsCIELab Lab; 482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov illu = 0; 483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov il = 0; 484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov in = cmsCreateLab4Profile(NULL); 485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov out = cmsCreate_sRGBProfile(); 486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov transform = 487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsCreateTransform(in, TYPE_Lab_DBL, out, TYPE_RGB_16, 488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov INTENT_PERCEPTUAL, 0); 489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsCloseProfile(in); 490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsCloseProfile(out); 491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if(transform == NULL) { 492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 494ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov prec0 = (double)image->comps[0].prec; 495ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov prec1 = (double)image->comps[1].prec; 496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov prec2 = (double)image->comps[2].prec; 497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov default_type = row[1]; 498ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if(default_type == 0x44454600) { 499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov rl = 100; 500ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ra = 170; 501ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov rb = 200; 502ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ol = 0; 503ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov oa = pow(2, prec1 - 1); 504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ob = pow(2, prec2 - 2) + pow(2, prec2 - 3); 505ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else { 506ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov rl = row[2]; 507ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ra = row[4]; 508ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov rb = row[6]; 509ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ol = row[3]; 510ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov oa = row[5]; 511ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ob = row[7]; 512ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 513ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov L = src0 = image->comps[0].data; 514ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov a = src1 = image->comps[1].data; 515ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov b = src2 = image->comps[2].data; 516ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov max = image->comps[0].w * image->comps[0].h; 517ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov red = FX_Alloc(int, max); 518ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov image->comps[0].data = red; 519ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov green = FX_Alloc(int, max); 520ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov image->comps[1].data = green; 521ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov blue = FX_Alloc(int, max); 522ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov image->comps[2].data = blue; 523ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov minL = -(rl * ol) / (pow(2, prec0) - 1); 524ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov maxL = minL + rl; 525ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mina = -(ra * oa) / (pow(2, prec1) - 1); 526ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov maxa = mina + ra; 527ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov minb = -(rb * ob) / (pow(2, prec2) - 1); 528ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov maxb = minb + rb; 529ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for(i = 0; i < max; ++i) { 530ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Lab.L = minL + (double)(*L) * (maxL - minL) / (pow(2, prec0) - 1); 531ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++L; 532ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Lab.a = mina + (double)(*a) * (maxa - mina) / (pow(2, prec1) - 1); 533ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++a; 534ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Lab.b = minb + (double)(*b) * (maxb - minb) / (pow(2, prec2) - 1); 535ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ++b; 536ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsDoTransform(transform, &Lab, RGB, 1); 537ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *red++ = RGB[0]; 538ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *green++ = RGB[1]; 539ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *blue++ = RGB[2]; 540ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 541ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsDeleteTransform(transform); 542ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_Free(src0); 543ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_Free(src1); 544ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_Free(src2); 545ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov image->color_space = OPJ_CLRSPC_SRGB; 546ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov image->comps[0].prec = 16; 547ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov image->comps[1].prec = 16; 548ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov image->comps[2].prec = 16; 549ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 550ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 551ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 552ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovclass CJPX_Decoder : public CFX_Object 553ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 554ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovpublic: 555ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CJPX_Decoder(); 556ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ~CJPX_Decoder(); 557ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BOOL Init(const unsigned char* src_data, int src_size); 558ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov void GetInfo(FX_DWORD& width, FX_DWORD& height, FX_DWORD& codestream_nComps, FX_DWORD& output_nComps); 559ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BOOL Decode(FX_LPBYTE dest_buf, int pitch, FX_BOOL bTranslateColor, FX_LPBYTE offsets); 560ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_LPCBYTE m_SrcData; 561ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int m_SrcSize; 562ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov opj_image_t *image; 563ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov opj_codec_t* l_codec; 564ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov opj_stream_t *l_stream; 565ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BOOL m_useColorSpace; 566ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}; 567ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovCJPX_Decoder::CJPX_Decoder(): image(NULL), l_codec(NULL), l_stream(NULL), m_useColorSpace(FALSE) 568ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 569ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 570ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovCJPX_Decoder::~CJPX_Decoder() 571ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 572ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if(l_codec) { 573ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov opj_destroy_codec(l_codec); 574ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 575ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if(l_stream) { 576ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov opj_stream_destroy(l_stream); 577ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 578ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if(image) { 579ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov opj_image_destroy(image); 580ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 581ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 582ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CJPX_Decoder::Init(const unsigned char* src_data, int src_size) 583ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 584ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov opj_dparameters_t parameters; 585ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov try { 586ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov image = NULL; 587ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_SrcData = src_data; 588ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_SrcSize = src_size; 589ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov decodeData srcData; 590ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov srcData.offset = 0; 591ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov srcData.src_size = src_size; 592ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov srcData.src_data = src_data; 593ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov l_stream = fx_opj_stream_create_memory_stream(&srcData, OPJ_J2K_STREAM_CHUNK_SIZE, 1); 594ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (l_stream == NULL) { 595ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 596ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 597ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov opj_set_default_decoder_parameters(¶meters); 598ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov parameters.decod_format = 0; 599ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov parameters.cod_format = 3; 600ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if(FXSYS_memcmp32(m_SrcData, "\x00\x00\x00\x0c\x6a\x50\x20\x20\x0d\x0a\x87\x0a", 12) == 0) { 601ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov l_codec = opj_create_decompress(OPJ_CODEC_JP2); 602ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov parameters.decod_format = 1; 603ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else { 604ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov l_codec = opj_create_decompress(OPJ_CODEC_J2K); 605ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 606ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if(!l_codec) { 607ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 608ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 609ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov opj_set_info_handler(l_codec, fx_info_callback, 00); 610ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov opj_set_warning_handler(l_codec, fx_warning_callback, 00); 611ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov opj_set_error_handler(l_codec, fx_error_callback, 00); 612ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !opj_setup_decoder(l_codec, ¶meters) ) { 613ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 614ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 615ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if(! opj_read_header(l_stream, l_codec, &image)) { 616ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov image = NULL; 617ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 618ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 619ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if(this->m_useColorSpace) { 620ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov image->useColorSpace = 1; 621ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else { 622ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov image->useColorSpace = 0; 623ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 624ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!parameters.nb_tile_to_decode) { 625ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!opj_set_decode_area(l_codec, image, parameters.DA_x0, 626ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov parameters.DA_y0, parameters.DA_x1, parameters.DA_y1)) { 627ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov opj_image_destroy(image); 628ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov image = NULL; 629ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 630ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 631ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!(opj_decode(l_codec, l_stream, image) && opj_end_decompress(l_codec, l_stream))) { 632ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov opj_image_destroy(image); 633ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov image = NULL; 634ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 635ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 636ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else { 637ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!opj_get_decoded_tile(l_codec, l_stream, image, parameters.tile_index)) { 638ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 639ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 640ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 641ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov opj_stream_destroy(l_stream); 642ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov l_stream = NULL; 643ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if( image->color_space != OPJ_CLRSPC_SYCC 644ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov && image->numcomps == 3 && image->comps[0].dx == image->comps[0].dy 645ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov && image->comps[1].dx != 1 ) { 646ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov image->color_space = OPJ_CLRSPC_SYCC; 647ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else if (image->numcomps <= 2) { 648ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov image->color_space = OPJ_CLRSPC_GRAY; 649ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 650ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if(image->color_space == OPJ_CLRSPC_SYCC) { 651ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov color_sycc_to_rgb(image); 652ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 653ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if(image->icc_profile_buf && !image->useColorSpace) { 654ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_Free(image->icc_profile_buf); 655ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov image->icc_profile_buf = NULL; 656ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov image->icc_profile_len = 0; 657ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 658ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if(!image) { 659ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 660ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 661ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } catch (...) { 662ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 663ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 664ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return TRUE; 665ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 666ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CJPX_Decoder::GetInfo(FX_DWORD& width, FX_DWORD& height, FX_DWORD& codestream_nComps, FX_DWORD& output_nComps) 667ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 668ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov width = (FX_DWORD)image->x1; 669ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov height = (FX_DWORD)image->y1; 670ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov output_nComps = codestream_nComps = (FX_DWORD)image->numcomps; 671ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 672ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CJPX_Decoder::Decode(FX_LPBYTE dest_buf, int pitch, FX_BOOL bTranslateColor, FX_LPBYTE offsets) 673ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 674ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BYTE** channel_bufs; 675ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int* adjust_comps; 676ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int i, wid, hei, row, col, channel, src; 677ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BOOL flag; 678ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_LPBYTE pChannel, pScanline, pPixel; 679ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov try { 680ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if(image->comps[0].w != image->x1 || image->comps[0].h != image->y1) { 681ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 682ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 683ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if(pitch < (int)(image->comps[0].w * 8 * image->numcomps + 31) >> 5 << 2) { 684ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 685ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 686ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FXSYS_memset8(dest_buf, 0xff, image->y1 * pitch); 687ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov channel_bufs = FX_Alloc(FX_BYTE*, image->numcomps); 688ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (channel_bufs == NULL) { 689ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 690ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 691ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov adjust_comps = FX_Alloc(int, image->numcomps); 692ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (adjust_comps == NULL) { 693ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_Free(channel_bufs); 694ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 695ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 696ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov flag = TRUE; 697ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (i = 0; i < (int)image->numcomps; i ++) { 698ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov channel_bufs[i] = dest_buf + offsets[i]; 699ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov adjust_comps[i] = image->comps[i].prec - 8; 700ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if(i > 0) { 701ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if(image->comps[i].dx != image->comps[i - 1].dx 702ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov || image->comps[i].dy != image->comps[i - 1].dy 703ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov || image->comps[i].prec != image->comps[i - 1].prec) { 704ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov flag = FALSE; 705ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto failed; 706ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 707ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 708ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 709ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov wid = image->comps[0].w; 710ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov hei = image->comps[0].h; 711ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (channel = 0; channel < (int)image->numcomps; channel++) { 712ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pChannel = channel_bufs[channel]; 713ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if(adjust_comps[channel] < 0) { 714ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for(row = 0; row < hei; row++) { 715ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pScanline = pChannel + row * pitch; 716ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (col = 0; col < wid; col++) { 717ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pPixel = pScanline + col * image->numcomps; 718ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov src = image->comps[channel].data[row * wid + col]; 719ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov src += image->comps[channel].sgnd ? 1 << (image->comps[channel].prec - 1) : 0; 720ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (adjust_comps[channel] > 0) { 721ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *pPixel = 0; 722ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else { 723ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *pPixel = (FX_BYTE)(src << -adjust_comps[channel]); 724ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 725ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 726ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 727ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else { 728ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for(row = 0; row < hei; row++) { 729ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pScanline = pChannel + row * pitch; 730ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (col = 0; col < wid; col++) { 731ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pPixel = pScanline + col * image->numcomps; 732ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!image->comps[channel].data) continue; 733ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov src = image->comps[channel].data[row * wid + col]; 734ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov src += image->comps[channel].sgnd ? 1 << (image->comps[channel].prec - 1) : 0; 735ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (adjust_comps[channel] - 1 < 0) { 736ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *pPixel = (FX_BYTE)((src >> adjust_comps[channel])); 737ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else { 738ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int tmpPixel = (src >> adjust_comps[channel]) + ((src >> (adjust_comps[channel] - 1)) % 2); 739ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (tmpPixel > 255) { 740ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tmpPixel = 255; 741ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else if (tmpPixel < 0) { 742ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tmpPixel = 0; 743ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 744ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *pPixel = (FX_BYTE)tmpPixel; 745ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 746ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 747ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 748ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 749ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 750ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } catch (...) { 751ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (channel_bufs) { 752ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_Free(channel_bufs); 753ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 754ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_Free(adjust_comps); 755ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 756ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 757ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_Free(channel_bufs); 758ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_Free(adjust_comps); 759ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return TRUE; 760ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovfailed: 761ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_Free(channel_bufs); 762ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_Free(adjust_comps); 763ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 764ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 765ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid initialize_transition_table(); 766ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid initialize_significance_luts(); 767ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid initialize_sign_lut(); 768ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovCCodec_JpxModule::CCodec_JpxModule() 769ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 770ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 771ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid* CCodec_JpxModule::CreateDecoder(FX_LPCBYTE src_buf, FX_DWORD src_size , FX_BOOL useColorSpace) 772ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 773ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CJPX_Decoder* pDecoder = FX_NEW CJPX_Decoder; 774ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (pDecoder == NULL) { 775ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 776ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 777ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pDecoder->m_useColorSpace = useColorSpace; 778ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!pDecoder->Init(src_buf, src_size)) { 779ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov delete pDecoder; 780ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 781ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 782ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return pDecoder; 783ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 784ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CCodec_JpxModule::GetImageInfo(FX_LPVOID ctx, FX_DWORD& width, FX_DWORD& height, 785ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_DWORD& codestream_nComps, FX_DWORD& output_nComps) 786ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 787ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CJPX_Decoder* pDecoder = (CJPX_Decoder*)ctx; 788ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pDecoder->GetInfo(width, height, codestream_nComps, output_nComps); 789ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 790ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CCodec_JpxModule::Decode(void* ctx, FX_LPBYTE dest_data, int pitch, FX_BOOL bTranslateColor, FX_LPBYTE offsets) 791ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 792ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CJPX_Decoder* pDecoder = (CJPX_Decoder*)ctx; 793ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return pDecoder->Decode(dest_data, pitch, bTranslateColor, offsets); 794ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 795ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CCodec_JpxModule::DestroyDecoder(void* ctx) 796ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 797ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CJPX_Decoder* pDecoder = (CJPX_Decoder*)ctx; 798ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov delete pDecoder; 799ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 800