Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 PDFium Authors. All rights reserved. | 1 // Copyright 2014 PDFium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
| 6 | 6 |
| 7 #include <limits> | |
| 8 | |
| 7 #include "../../../include/fxcodec/fx_codec.h" | 9 #include "../../../include/fxcodec/fx_codec.h" |
| 8 #include "codec_int.h" | 10 #include "codec_int.h" |
| 9 #include "../fx_libopenjpeg/libopenjpeg20/openjpeg.h" | 11 #include "../fx_libopenjpeg/libopenjpeg20/openjpeg.h" |
| 10 #include "../lcms2/include/fx_lcms2.h" | 12 #include "../lcms2/include/fx_lcms2.h" |
| 13 | |
| 11 static void fx_error_callback(const char *msg, void *client_data) | 14 static void fx_error_callback(const char *msg, void *client_data) |
| 12 { | 15 { |
| 13 (void)client_data; | 16 (void)client_data; |
| 14 } | 17 } |
| 15 static void fx_warning_callback(const char *msg, void *client_data) | 18 static void fx_warning_callback(const char *msg, void *client_data) |
| 16 { | 19 { |
| 17 (void)client_data; | 20 (void)client_data; |
| 18 } | 21 } |
| 19 static void fx_info_callback(const char *msg, void *client_data) | 22 static void fx_info_callback(const char *msg, void *client_data) |
| 20 { | 23 { |
| 21 (void)client_data; | 24 (void)client_data; |
| 22 } | 25 } |
| 23 struct DecodeData { | 26 OPJ_SIZE_T opj_read_from_memory(void* p_buffer, OPJ_SIZE_T nb_bytes, void* p_use r_data) |
| 24 unsigned char* src_data; | |
| 25 OPJ_SIZE_T src_size; | |
| 26 OPJ_SIZE_T offset; | |
| 27 }; | |
| 28 static OPJ_SIZE_T opj_read_from_memory (void * p_buffer, OPJ_SIZE_T p_nb_bytes, void* p_user_data) | |
| 29 { | 27 { |
| 30 DecodeData* srcData = static_cast<DecodeData*>(p_user_data); | 28 DecodeData* srcData = static_cast<DecodeData*>(p_user_data); |
| 31 if (srcData == NULL || srcData->src_size == 0 || srcData->src_data == NULL | | srcData->offset >= srcData->src_size) { | 29 if (!srcData || !srcData->src_data || srcData->src_size == 0) { |
| 30 return -1; | |
| 31 } | |
| 32 // Reads at EOF return an error code. | |
| 33 if (srcData->offset >= srcData->src_size) { | |
| 32 return -1; | 34 return -1; |
| 33 } | 35 } |
| 34 OPJ_SIZE_T bufferLength = srcData->src_size - srcData->offset; | 36 OPJ_SIZE_T bufferLength = srcData->src_size - srcData->offset; |
| 35 OPJ_SIZE_T readlength = p_nb_bytes < bufferLength ? p_nb_bytes : bufferLengt h; | 37 OPJ_SIZE_T readlength = nb_bytes < bufferLength ? nb_bytes : bufferLength; |
| 36 memcpy(p_buffer, &srcData->src_data[srcData->offset], readlength); | 38 memcpy(p_buffer, &srcData->src_data[srcData->offset], readlength); |
| 37 srcData->offset += readlength; | 39 srcData->offset += readlength; |
| 38 return readlength; | 40 return readlength; |
| 39 } | 41 } |
| 40 static OPJ_SIZE_T opj_write_from_memory (void * p_buffer, OPJ_SIZE_T p_nb_bytes, void* p_user_data) | 42 OPJ_SIZE_T opj_write_from_memory(void* p_buffer, OPJ_SIZE_T nb_bytes, void* p_us er_data) |
| 41 { | 43 { |
| 42 DecodeData* srcData = static_cast<DecodeData*>(p_user_data); | 44 DecodeData* srcData = static_cast<DecodeData*>(p_user_data); |
| 43 if (srcData == NULL || srcData->src_size == 0 || srcData->src_data == NULL | | srcData->offset >= srcData->src_size) { | 45 if (!srcData || !srcData->src_data || srcData->src_size == 0) { |
| 46 return -1; | |
| 47 } | |
| 48 // Writes at EOF return an error code. | |
| 49 if (srcData->offset >= srcData->src_size) { | |
| 44 return -1; | 50 return -1; |
| 45 } | 51 } |
| 46 OPJ_SIZE_T bufferLength = srcData->src_size - srcData->offset; | 52 OPJ_SIZE_T bufferLength = srcData->src_size - srcData->offset; |
| 47 OPJ_SIZE_T writeLength = p_nb_bytes < bufferLength ? p_nb_bytes : bufferLeng th; | 53 OPJ_SIZE_T writeLength = nb_bytes < bufferLength ? nb_bytes : bufferLength; |
| 48 memcpy(&srcData->src_data[srcData->offset], p_buffer, writeLength); | 54 memcpy(&srcData->src_data[srcData->offset], p_buffer, writeLength); |
| 49 srcData->offset += writeLength; | 55 srcData->offset += writeLength; |
| 50 return writeLength; | 56 return writeLength; |
| 51 } | 57 } |
| 52 static OPJ_OFF_T opj_skip_from_memory (OPJ_OFF_T p_nb_bytes, void* p_user_data) | 58 OPJ_OFF_T opj_skip_from_memory(OPJ_OFF_T nb_bytes, void* p_user_data) |
| 53 { | 59 { |
| 54 DecodeData* srcData = static_cast<DecodeData*>(p_user_data); | 60 DecodeData* srcData = static_cast<DecodeData*>(p_user_data); |
| 55 if (srcData == NULL || srcData->src_size == 0 || srcData->src_data == NULL) { | 61 if (!srcData || !srcData->src_data || srcData->src_size == 0) { |
| 56 return -1; | 62 return -1; |
| 57 } | 63 } |
| 58 if (srcData->offset >= srcData->src_size) { | 64 // Offsets are signed and may indicate a negative skip. Do not support this |
| 65 // because of the strange return convention where either bytes skipped or | |
| 66 // -1 is returned. Following that convention, a successful relative seek of | |
| 67 // -1 bytes would be required to to give the same result as the error case. | |
| 68 if (nb_bytes < 0) { | |
| 69 return -1; | |
| 70 } | |
| 71 // FIXME: use std::make_unsigned<OPJ_OFF_T>::type once c++11 lib is OK'd. | |
| 72 uint64_t unsignedNbBytes = static_cast<uint64_t>(nb_bytes); | |
| 73 // Additionally, the offset may take us beyond the range of a size_t (e.g. | |
| 74 // 32-bit platforms). If so, just clamp at EOF. | |
| 75 if (unsignedNbBytes > std::numeric_limits<OPJ_SIZE_T>::max() - srcData->offs et) { | |
| 59 srcData->offset = srcData->src_size; | 76 srcData->offset = srcData->src_size; |
| 60 return p_nb_bytes; | 77 } else { |
| 78 OPJ_SIZE_T checkedNbBytes = static_cast<OPJ_SIZE_T>(unsignedNbBytes); | |
| 79 // Otherwise, mimic fseek() semantics to always succeed, even past EOF, | |
| 80 // clamping at EOF. We can get away with this since we don't actually | |
| 81 // provide negative relative skips from beyond EOF back to inside the | |
| 82 // data, which would be the only reason to need to know exactly how far | |
| 83 // beyond EOF we are. | |
| 84 srcData->offset = std::min(srcData->offset + checkedNbBytes, srcData->sr c_size); | |
|
jun_fang
2015/03/19 00:28:46
In this case, we should return the skipped bytes r
Tom Sepez
2015/03/19 00:35:16
Looking at the example code you pointed at before,
jun_fang
2015/03/19 00:48:35
I checked the code before. I suspect that there ma
| |
| 61 } | 85 } |
| 62 OPJ_SIZE_T bufferLength = srcData->src_size - srcData->offset; | 86 return nb_bytes; |
| 63 OPJ_SIZE_T skipLength = p_nb_bytes < bufferLength ? p_nb_bytes : bufferLengt h; | |
| 64 srcData->offset += skipLength; | |
| 65 return skipLength; | |
| 66 } | 87 } |
| 67 static OPJ_BOOL opj_seek_from_memory (OPJ_OFF_T p_nb_bytes, void* p_user_data) | 88 OPJ_BOOL opj_seek_from_memory(OPJ_OFF_T nb_bytes, void* p_user_data) |
| 68 { | 89 { |
| 69 DecodeData* srcData = static_cast<DecodeData*>(p_user_data); | 90 DecodeData* srcData = static_cast<DecodeData*>(p_user_data); |
| 70 if (srcData == NULL || srcData->src_size == 0 || srcData->src_data == NULL) { | 91 if (!srcData || !srcData->src_data || srcData->src_size == 0) { |
| 71 return OPJ_FALSE; | 92 return OPJ_FALSE; |
| 72 } | 93 } |
| 73 if (srcData->offset >= srcData->src_size) { | 94 // Offsets are signed and may indicate a negative position, which would |
| 74 return OPJ_TRUE; | 95 // be before the start of the file. Do not support this. |
| 75 } | 96 if (nb_bytes < 0) { |
| 76 if (p_nb_bytes >= srcData->src_size) { | |
| 77 return OPJ_FALSE; | 97 return OPJ_FALSE; |
| 78 } | 98 } |
| 79 srcData->offset = p_nb_bytes; | 99 // FIXME: use std::make_unsigned<OPJ_OFF_T>::type once c++11 lib is OK'd. |
| 100 uint64_t unsignedNbBytes = static_cast<uint64_t>(nb_bytes); | |
| 101 // Additionally, the offset may take us beyond the range of a size_t (e.g. | |
| 102 // 32-bit platforms). If so, just clamp at EOF. | |
| 103 if (unsignedNbBytes > std::numeric_limits<OPJ_SIZE_T>::max()) { | |
| 104 srcData->offset = srcData->src_size; | |
|
jun_fang
2015/03/19 00:28:46
Before the code change, it returns false when the
Tom Sepez
2015/03/19 00:35:16
Looking at the example code again,
static OPJ_BOOL
jun_fang
2015/03/19 00:48:35
OK. let's follow the implemention in open jpeg.
| |
| 105 } else { | |
| 106 OPJ_SIZE_T checkedNbBytes = static_cast<OPJ_SIZE_T>(nb_bytes); | |
| 107 // Otherwise, mimic fseek() semantics to always succeed, even past EOF, | |
| 108 // again clamping at EOF. | |
| 109 srcData->offset = std::min(checkedNbBytes, srcData->src_size); | |
| 110 } | |
| 80 return OPJ_TRUE; | 111 return OPJ_TRUE; |
| 81 } | 112 } |
| 82 opj_stream_t* fx_opj_stream_create_memory_stream (DecodeData* data, OPJ_SIZE _T p_size, OPJ_BOOL p_is_read_stream) | 113 opj_stream_t* fx_opj_stream_create_memory_stream (DecodeData* data, OPJ_SIZE _T p_size, OPJ_BOOL p_is_read_stream) |
| 83 { | 114 { |
| 84 opj_stream_t* l_stream = 00; | 115 opj_stream_t* l_stream = 00; |
| 85 if (!data || ! data->src_data || data->src_size <= 0 ) { | 116 if (!data || ! data->src_data || data->src_size <= 0 ) { |
| 86 return NULL; | 117 return NULL; |
| 87 } | 118 } |
| 88 l_stream = opj_stream_create(p_size, p_is_read_stream); | 119 l_stream = opj_stream_create(p_size, p_is_read_stream); |
| 89 if (! l_stream) { | 120 if (! l_stream) { |
| (...skipping 494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 584 } | 615 } |
| 585 FX_BOOL CJPX_Decoder::Init(const unsigned char* src_data, int src_size) | 616 FX_BOOL CJPX_Decoder::Init(const unsigned char* src_data, int src_size) |
| 586 { | 617 { |
| 587 static const unsigned char szJP2Header[] = { 0x00, 0x00, 0x00, 0x0c, 0x6a, 0 x50, 0x20, 0x20, 0x0d, 0x0a, 0x87, 0x0a }; | 618 static const unsigned char szJP2Header[] = { 0x00, 0x00, 0x00, 0x0c, 0x6a, 0 x50, 0x20, 0x20, 0x0d, 0x0a, 0x87, 0x0a }; |
| 588 if (!src_data || src_size < sizeof(szJP2Header)) { | 619 if (!src_data || src_size < sizeof(szJP2Header)) { |
| 589 return FALSE; | 620 return FALSE; |
| 590 } | 621 } |
| 591 image = NULL; | 622 image = NULL; |
| 592 m_SrcData = src_data; | 623 m_SrcData = src_data; |
| 593 m_SrcSize = src_size; | 624 m_SrcSize = src_size; |
| 594 DecodeData srcData; | 625 DecodeData srcData(const_cast<unsigned char*>(src_data), src_size); |
| 595 srcData.offset = 0; | |
| 596 srcData.src_size = src_size; | |
| 597 srcData.src_data = const_cast<unsigned char*>(src_data); | |
| 598 l_stream = fx_opj_stream_create_memory_stream(&srcData, OPJ_J2K_STREAM_CHUNK _SIZE, 1); | 626 l_stream = fx_opj_stream_create_memory_stream(&srcData, OPJ_J2K_STREAM_CHUNK _SIZE, 1); |
| 599 if (l_stream == NULL) { | 627 if (l_stream == NULL) { |
| 600 return FALSE; | 628 return FALSE; |
| 601 } | 629 } |
| 602 opj_dparameters_t parameters; | 630 opj_dparameters_t parameters; |
| 603 opj_set_default_decoder_parameters(¶meters); | 631 opj_set_default_decoder_parameters(¶meters); |
| 604 parameters.decod_format = 0; | 632 parameters.decod_format = 0; |
| 605 parameters.cod_format = 3; | 633 parameters.cod_format = 3; |
| 606 if(FXSYS_memcmp32(m_SrcData, szJP2Header, sizeof(szJP2Header)) == 0) { | 634 if(FXSYS_memcmp32(m_SrcData, szJP2Header, sizeof(szJP2Header)) == 0) { |
| 607 l_codec = opj_create_decompress(OPJ_CODEC_JP2); | 635 l_codec = opj_create_decompress(OPJ_CODEC_JP2); |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 792 FX_BOOL CCodec_JpxModule::Decode(void* ctx, FX_LPBYTE dest_data, int pitch, FX_B OOL bTranslateColor, FX_LPBYTE offsets) | 820 FX_BOOL CCodec_JpxModule::Decode(void* ctx, FX_LPBYTE dest_data, int pitch, FX_B OOL bTranslateColor, FX_LPBYTE offsets) |
| 793 { | 821 { |
| 794 CJPX_Decoder* pDecoder = (CJPX_Decoder*)ctx; | 822 CJPX_Decoder* pDecoder = (CJPX_Decoder*)ctx; |
| 795 return pDecoder->Decode(dest_data, pitch, bTranslateColor, offsets); | 823 return pDecoder->Decode(dest_data, pitch, bTranslateColor, offsets); |
| 796 } | 824 } |
| 797 void CCodec_JpxModule::DestroyDecoder(void* ctx) | 825 void CCodec_JpxModule::DestroyDecoder(void* ctx) |
| 798 { | 826 { |
| 799 CJPX_Decoder* pDecoder = (CJPX_Decoder*)ctx; | 827 CJPX_Decoder* pDecoder = (CJPX_Decoder*)ctx; |
| 800 delete pDecoder; | 828 delete pDecoder; |
| 801 } | 829 } |
| OLD | NEW |