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 "../../fx_zlib.h" 8ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../../include/fxcodec/fx_codec.h" 9ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "codec_int.h" 10ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovextern "C" 11ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 12ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static void* my_alloc_func (void* opaque, unsigned int items, unsigned int size) 13ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 14ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FX_Alloc(FX_BYTE, items * size); 15ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 16ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static void my_free_func (void* opaque, void* address) 17ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 18ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_Free(address); 19ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 20ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov void* FPDFAPI_FlateInit(void* (*alloc_func)(void*, unsigned int, unsigned int), 21ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov void (*free_func)(void*, void*)) 22ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 23ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov z_stream* p = (z_stream*)alloc_func(0, 1, sizeof(z_stream)); 24ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (p == NULL) { 25ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 26ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 27ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FXSYS_memset32(p, 0, sizeof(z_stream)); 28ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p->zalloc = alloc_func; 29ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p->zfree = free_func; 30ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov inflateInit(p); 31ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return p; 32ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 33ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov void FPDFAPI_FlateInput(void* context, const unsigned char* src_buf, unsigned int src_size) 34ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 35ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ((z_stream*)context)->next_in = (unsigned char*)src_buf; 36ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ((z_stream*)context)->avail_in = src_size; 37ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 38ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int FPDFAPI_FlateGetTotalOut(void* context) 39ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 40ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return ((z_stream*)context)->total_out; 41ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 42ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int FPDFAPI_FlateOutput(void* context, unsigned char* dest_buf, unsigned int dest_size) 43ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 44ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ((z_stream*)context)->next_out = dest_buf; 45ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ((z_stream*)context)->avail_out = dest_size; 46ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov unsigned int pre_pos = (unsigned int)FPDFAPI_FlateGetTotalOut(context); 47ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int ret = inflate((z_stream*)context, Z_SYNC_FLUSH); 48ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov unsigned int post_pos = (unsigned int)FPDFAPI_FlateGetTotalOut(context); 49ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov unsigned int written = post_pos - pre_pos; 50ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (written < dest_size) { 51ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FXSYS_memset8(dest_buf + written, '\0', dest_size - written); 52ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 53ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return ret; 54ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 55ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int FPDFAPI_FlateGetTotalIn(void* context) 56ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 57ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return ((z_stream*)context)->total_in; 58ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 59ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int FPDFAPI_FlateGetAvailOut(void* context) 60ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 61ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return ((z_stream*)context)->avail_out; 62ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 63ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int FPDFAPI_FlateGetAvailIn(void* context) 64ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 65ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return ((z_stream*)context)->avail_in; 66ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 67ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov void FPDFAPI_FlateEnd(void* context) 68ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 69ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov inflateEnd((z_stream*)context); 70ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ((z_stream*)context)->zfree(0, context); 71ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 72ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov void FPDFAPI_FlateCompress(unsigned char* dest_buf, unsigned long* dest_size, const unsigned char* src_buf, unsigned long src_size) 73ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 74ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov compress(dest_buf, dest_size, src_buf, src_size); 75ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 76ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 77ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovclass CLZWDecoder : public CFX_Object 78ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 79ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovpublic: 80ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BOOL Decode(FX_LPBYTE output, FX_DWORD& outlen, const FX_BYTE* input, FX_DWORD& size, FX_BOOL bEarlyChange); 81ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovprivate: 82ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_DWORD m_InPos; 83ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_DWORD m_OutPos; 84ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_LPBYTE m_pOutput; 85ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const FX_BYTE* m_pInput; 86ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BOOL m_Early; 87ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov void AddCode(FX_DWORD prefix_code, FX_BYTE append_char); 88ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_DWORD m_CodeArray[5021]; 89ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_DWORD m_nCodes; 90ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BYTE m_DecodeStack[4000]; 91ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_DWORD m_StackLen; 92ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov void DecodeString(FX_DWORD code); 93ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int m_CodeLen; 94ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}; 95ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CLZWDecoder::AddCode(FX_DWORD prefix_code, FX_BYTE append_char) 96ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 97ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (m_nCodes + m_Early == 4094) { 98ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 99ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_CodeArray[m_nCodes ++] = (prefix_code << 16) | append_char; 101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (m_nCodes + m_Early == 512 - 258) { 102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_CodeLen = 10; 103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else if (m_nCodes + m_Early == 1024 - 258) { 104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_CodeLen = 11; 105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else if (m_nCodes + m_Early == 2048 - 258) { 106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_CodeLen = 12; 107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CLZWDecoder::DecodeString(FX_DWORD code) 110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while (1) { 112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int index = code - 258; 113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (index < 0 || index >= (int)m_nCodes) { 114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_DWORD data = m_CodeArray[index]; 117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (m_StackLen >= sizeof(m_DecodeStack)) { 118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_DecodeStack[m_StackLen++] = (FX_BYTE)data; 121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov code = data >> 16; 122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (m_StackLen >= sizeof(m_DecodeStack)) { 124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_DecodeStack[m_StackLen++] = (FX_BYTE)code; 127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovint CLZWDecoder::Decode(FX_LPBYTE dest_buf, FX_DWORD& dest_size, const FX_BYTE* src_buf, FX_DWORD& src_size, FX_BOOL bEarlyChange) 129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_CodeLen = 9; 131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_InPos = 0; 132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_OutPos = 0; 133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_pInput = src_buf; 134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_pOutput = dest_buf; 135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_Early = bEarlyChange ? 1 : 0; 136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_nCodes = 0; 137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_DWORD old_code = (FX_DWORD) - 1; 138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BYTE last_char; 139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while (1) { 140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (m_InPos + m_CodeLen > src_size * 8) { 141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int byte_pos = m_InPos / 8; 144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int bit_pos = m_InPos % 8, bit_left = m_CodeLen; 145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_DWORD code = 0; 146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (bit_pos) { 147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov bit_left -= 8 - bit_pos; 148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov code = (m_pInput[byte_pos++] & ((1 << (8 - bit_pos)) - 1)) << bit_left; 149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (bit_left < 8) { 151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov code |= m_pInput[byte_pos] >> (8 - bit_left); 152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else { 153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov bit_left -= 8; 154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov code |= m_pInput[byte_pos++] << bit_left; 155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (bit_left) { 156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov code |= m_pInput[byte_pos] >> (8 - bit_left); 157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_InPos += m_CodeLen; 160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (code < 256) { 161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (m_OutPos == dest_size) { 162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -5; 163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (m_pOutput) { 165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_pOutput[m_OutPos] = (FX_BYTE)code; 166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_OutPos ++; 168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov last_char = (FX_BYTE)code; 169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (old_code != (FX_DWORD) - 1) { 170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov AddCode(old_code, last_char); 171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov old_code = code; 173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else if (code == 256) { 174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_CodeLen = 9; 175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_nCodes = 0; 176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov old_code = (FX_DWORD) - 1; 177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else if (code == 257) { 178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else { 180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (old_code == (FX_DWORD) - 1) { 181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 2; 182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_StackLen = 0; 184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (code >= m_nCodes + 258) { 185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (m_StackLen < sizeof(m_DecodeStack)) { 186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_DecodeStack[m_StackLen++] = last_char; 187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov DecodeString(old_code); 189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else { 190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov DecodeString(code); 191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (m_OutPos + m_StackLen > dest_size) { 193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -5; 194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (m_pOutput) { 196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (FX_DWORD i = 0; i < m_StackLen; i ++) { 197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_pOutput[m_OutPos + i] = m_DecodeStack[m_StackLen - i - 1]; 198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_OutPos += m_StackLen; 201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov last_char = m_DecodeStack[m_StackLen - 1]; 202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (old_code < 256) { 203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov AddCode(old_code, last_char); 204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else if (old_code - 258 >= m_nCodes) { 205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dest_size = m_OutPos; 206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov src_size = (m_InPos + 7) / 8; 207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else { 209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov AddCode(old_code, last_char); 210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov old_code = code; 212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dest_size = m_OutPos; 215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov src_size = (m_InPos + 7) / 8; 216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic FX_BYTE PaethPredictor(int a, int b, int c) 219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int p = a + b - c; 221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int pa = FXSYS_abs(p - a); 222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int pb = FXSYS_abs(p - b); 223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int pc = FXSYS_abs(p - c); 224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (pa <= pb && pa <= pc) { 225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return (FX_BYTE)a; 226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (pb <= pc) { 228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return (FX_BYTE)b; 229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return (FX_BYTE)c; 231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic void PNG_PredictorEncode(FX_LPBYTE& data_buf, FX_DWORD& data_size, int predictor, int Colors, int BitsPerComponent, int Columns) 233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int BytesPerPixel = (Colors * BitsPerComponent + 7) / 8; 235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int row_size = (Colors * BitsPerComponent * Columns + 7) / 8; 236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int row_count = (data_size + row_size - 1) / row_size; 237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int last_row_size = data_size % row_size; 238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_LPBYTE dest_buf = FX_Alloc( FX_BYTE, (row_size + 1) * row_count); 239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (dest_buf == NULL) { 240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int byte_cnt = 0; 243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_LPBYTE pSrcData = data_buf; 244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_LPBYTE pDestData = dest_buf; 245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (int row = 0; row < row_count; row++) { 246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (predictor == 10) { 247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pDestData[0] = 0; 248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int move_size = row_size; 249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (move_size * (row + 1) > (int)data_size) { 250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov move_size = data_size - (move_size * row); 251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FXSYS_memmove32(pDestData + 1, pSrcData, move_size); 253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pDestData += (move_size + 1); 254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pSrcData += move_size; 255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov byte_cnt += move_size; 256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov continue; 257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (int byte = 0; byte < row_size && byte_cnt < (int)data_size; byte++) { 259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov switch (predictor) { 260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 11: { 261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pDestData[0] = 1; 262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BYTE left = 0; 263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (byte >= BytesPerPixel) { 264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov left = pSrcData[byte - BytesPerPixel]; 265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pDestData[byte + 1] = pSrcData[byte] - left; 267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 12: { 270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pDestData[0] = 2; 271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BYTE up = 0; 272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (row) { 273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov up = pSrcData[byte - row_size]; 274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pDestData[byte + 1] = pSrcData[byte] - up; 276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 13: { 279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pDestData[0] = 3; 280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BYTE left = 0; 281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (byte >= BytesPerPixel) { 282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov left = pSrcData[byte - BytesPerPixel]; 283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BYTE up = 0; 285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (row) { 286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov up = pSrcData[byte - row_size]; 287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pDestData[byte + 1] = pSrcData[byte] - (left + up) / 2; 289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 14: { 292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pDestData[0] = 4; 293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BYTE left = 0; 294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (byte >= BytesPerPixel) { 295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov left = pSrcData[byte - BytesPerPixel]; 296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BYTE up = 0; 298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (row) { 299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov up = pSrcData[byte - row_size]; 300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BYTE upper_left = 0; 302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (byte >= BytesPerPixel && row) { 303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov upper_left = pSrcData[byte - row_size - BytesPerPixel]; 304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pDestData[byte + 1] = pSrcData[byte] - PaethPredictor(left, up, upper_left); 306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov default: { 309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pDestData[byte + 1] = pSrcData[byte]; 310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov byte_cnt++; 314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pDestData += (row_size + 1); 316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pSrcData += row_size; 317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_Free(data_buf); 319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov data_buf = dest_buf; 320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov data_size = (row_size + 1) * row_count - (last_row_size > 0 ? (row_size - last_row_size) : 0); 321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic void PNG_PredictLine(FX_LPBYTE pDestData, FX_LPCBYTE pSrcData, FX_LPCBYTE pLastLine, 323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int bpc, int nColors, int nPixels) 324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int row_size = (nPixels * bpc * nColors + 7) / 8; 326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int BytesPerPixel = (bpc * nColors + 7) / 8; 327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BYTE tag = pSrcData[0]; 328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (tag == 0) { 329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FXSYS_memmove32(pDestData, pSrcData + 1, row_size); 330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (int byte = 0; byte < row_size; byte ++) { 333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BYTE raw_byte = pSrcData[byte + 1]; 334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov switch (tag) { 335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 1: { 336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BYTE left = 0; 337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (byte >= BytesPerPixel) { 338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov left = pDestData[byte - BytesPerPixel]; 339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pDestData[byte] = raw_byte + left; 341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 2: { 344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BYTE up = 0; 345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (pLastLine) { 346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov up = pLastLine[byte]; 347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pDestData[byte] = raw_byte + up; 349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 3: { 352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BYTE left = 0; 353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (byte >= BytesPerPixel) { 354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov left = pDestData[byte - BytesPerPixel]; 355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BYTE up = 0; 357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (pLastLine) { 358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov up = pLastLine[byte]; 359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pDestData[byte] = raw_byte + (up + left) / 2; 361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 4: { 364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BYTE left = 0; 365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (byte >= BytesPerPixel) { 366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov left = pDestData[byte - BytesPerPixel]; 367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BYTE up = 0; 369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (pLastLine) { 370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov up = pLastLine[byte]; 371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BYTE upper_left = 0; 373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (byte >= BytesPerPixel && pLastLine) { 374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov upper_left = pLastLine[byte - BytesPerPixel]; 375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pDestData[byte] = raw_byte + PaethPredictor(left, up, upper_left); 377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov default: 380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pDestData[byte] = raw_byte; 381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic void PNG_Predictor(FX_LPBYTE& data_buf, FX_DWORD& data_size, 386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int Colors, int BitsPerComponent, int Columns) 387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int BytesPerPixel = (Colors * BitsPerComponent + 7) / 8; 389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int row_size = (Colors * BitsPerComponent * Columns + 7) / 8; 390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int row_count = (data_size + row_size) / (row_size + 1); 391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int last_row_size = data_size % (row_size + 1); 392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_LPBYTE dest_buf = FX_Alloc( FX_BYTE, row_size * row_count); 393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (dest_buf == NULL) { 394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int byte_cnt = 0; 397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_LPBYTE pSrcData = data_buf; 398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_LPBYTE pDestData = dest_buf; 399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (int row = 0; row < row_count; row ++) { 400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BYTE tag = pSrcData[0]; 401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (tag == 0) { 402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int move_size = row_size; 403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ((row + 1) * (move_size + 1) > (int)data_size) { 404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov move_size = last_row_size - 1; 405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FXSYS_memmove32(pDestData, pSrcData + 1, move_size); 407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pSrcData += move_size + 1; 408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pDestData += move_size; 409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov byte_cnt += move_size + 1; 410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov continue; 411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (int byte = 0; byte < row_size && byte_cnt < (int)data_size; byte ++) { 413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BYTE raw_byte = pSrcData[byte + 1]; 414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov switch (tag) { 415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 1: { 416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BYTE left = 0; 417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (byte >= BytesPerPixel) { 418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov left = pDestData[byte - BytesPerPixel]; 419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pDestData[byte] = raw_byte + left; 421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 2: { 424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BYTE up = 0; 425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (row) { 426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov up = pDestData[byte - row_size]; 427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pDestData[byte] = raw_byte + up; 429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 3: { 432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BYTE left = 0; 433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (byte >= BytesPerPixel) { 434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov left = pDestData[byte - BytesPerPixel]; 435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BYTE up = 0; 437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (row) { 438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov up = pDestData[byte - row_size]; 439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pDestData[byte] = raw_byte + (up + left) / 2; 441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 4: { 444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BYTE left = 0; 445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (byte >= BytesPerPixel) { 446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov left = pDestData[byte - BytesPerPixel]; 447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BYTE up = 0; 449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (row) { 450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov up = pDestData[byte - row_size]; 451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 452ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BYTE upper_left = 0; 453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (byte >= BytesPerPixel && row) { 454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov upper_left = pDestData[byte - row_size - BytesPerPixel]; 455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pDestData[byte] = raw_byte + PaethPredictor(left, up, upper_left); 457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov default: 460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pDestData[byte] = raw_byte; 461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov byte_cnt++; 464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pSrcData += row_size + 1; 466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pDestData += row_size; 467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov byte_cnt++; 468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_Free(data_buf); 470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov data_buf = dest_buf; 471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov data_size = row_size * row_count - (last_row_size > 0 ? (row_size + 1 - last_row_size) : 0); 472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic void TIFF_PredictorEncodeLine(FX_LPBYTE dest_buf, int row_size, int BitsPerComponent, int Colors, int Columns) 474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int BytesPerPixel = BitsPerComponent * Colors / 8; 476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (BitsPerComponent < 8) { 477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BYTE mask = 0x01; 478ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (BitsPerComponent == 2) { 479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mask = 0x03; 480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else if (BitsPerComponent == 4) { 481ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mask = 0x0F; 482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int row_bits = Colors * BitsPerComponent * Columns; 484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (int i = row_bits - BitsPerComponent; i >= BitsPerComponent; i -= BitsPerComponent) { 485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int col = i % 8; 486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int index = i / 8; 487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int col_pre = (col == 0) ? (8 - BitsPerComponent) : (col - BitsPerComponent); 488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int index_pre = (col == 0) ? (index - 1) : index; 489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BYTE cur = (dest_buf[index] >> (8 - col - BitsPerComponent)) & mask; 490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BYTE left = (dest_buf[index_pre] >> (8 - col_pre - BitsPerComponent)) & mask; 491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cur -= left; 492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cur &= mask; 493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cur <<= (8 - col - BitsPerComponent); 494ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dest_buf[index] &= ~(mask << ((8 - col - BitsPerComponent))); 495ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dest_buf[index] |= cur; 496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else if (BitsPerComponent == 8) { 498ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (int i = row_size - 1; i >= BytesPerPixel; i--) { 499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dest_buf[i] -= dest_buf[i - BytesPerPixel]; 500ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 501ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else { 502ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (int i = row_size - BytesPerPixel; i >= BytesPerPixel; i -= BytesPerPixel) { 503ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_WORD pixel = (dest_buf[i] << 8) | dest_buf[i + 1]; 504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pixel -= (dest_buf[i - BytesPerPixel] << 8) | dest_buf[i - BytesPerPixel + 1]; 505ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dest_buf[i] = pixel >> 8; 506ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dest_buf[i + 1] = (FX_BYTE)pixel; 507ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 508ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 509ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 510ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic void TIFF_PredictorEncode(FX_LPBYTE& data_buf, FX_DWORD& data_size, 511ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int Colors, int BitsPerComponent, int Columns) 512ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 513ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int row_size = (Colors * BitsPerComponent * Columns + 7) / 8; 514ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int row_count = (data_size + row_size - 1) / row_size; 515ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int last_row_size = data_size % row_size; 516ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (int row = 0; row < row_count; row++) { 517ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_LPBYTE scan_line = data_buf + row * row_size; 518ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ((row + 1) * row_size > (int)data_size) { 519ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov row_size = last_row_size; 520ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 521ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TIFF_PredictorEncodeLine(scan_line, row_size, BitsPerComponent, Colors, Columns); 522ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 523ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 524ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic void TIFF_PredictLine(FX_LPBYTE dest_buf, int row_size, int BitsPerComponent, int Colors, int Columns) 525ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 526ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (BitsPerComponent == 1) { 527ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int row_bits = BitsPerComponent * Colors * Columns; 528ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for(int i = 1; i < row_bits; i ++) { 529ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int col = i % 8; 530ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int index = i / 8; 531ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int index_pre = (col == 0) ? (index - 1) : index; 532ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int col_pre = (col == 0) ? 8 : col; 533ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if( ((dest_buf[index] >> (7 - col)) & 1) ^ ((dest_buf[index_pre] >> (8 - col_pre)) & 1) ) { 534ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dest_buf[index] |= 1 << (7 - col); 535ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else { 536ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dest_buf[index] &= ~(1 << (7 - col)); 537ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 538ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 539ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 540ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 541ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int BytesPerPixel = BitsPerComponent * Colors / 8; 542ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (BitsPerComponent == 16) { 543ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (int i = BytesPerPixel; i < row_size; i += 2) { 544ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_WORD pixel = (dest_buf[i - BytesPerPixel] << 8) | dest_buf[i - BytesPerPixel + 1]; 545ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pixel += (dest_buf[i] << 8) | dest_buf[i + 1]; 546ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dest_buf[i] = pixel >> 8; 547ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dest_buf[i + 1] = (FX_BYTE)pixel; 548ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 549ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else { 550ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (int i = BytesPerPixel; i < row_size; i ++) { 551ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dest_buf[i] += dest_buf[i - BytesPerPixel]; 552ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 553ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 554ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 555ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic void TIFF_Predictor(FX_LPBYTE& data_buf, FX_DWORD& data_size, 556ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int Colors, int BitsPerComponent, int Columns) 557ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 558ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int row_size = (Colors * BitsPerComponent * Columns + 7) / 8; 559ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int row_count = (data_size + row_size - 1) / row_size; 560ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int last_row_size = data_size % row_size; 561ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (int row = 0; row < row_count; row ++) { 562ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_LPBYTE scan_line = data_buf + row * row_size; 563ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ((row + 1) * row_size > (int)data_size) { 564ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov row_size = last_row_size; 565ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 566ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TIFF_PredictLine(scan_line, row_size, BitsPerComponent, Colors, Columns); 567ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 568ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 569ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovclass CCodec_FlateScanlineDecoder : public CCodec_ScanlineDecoder 570ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 571ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovpublic: 572ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CCodec_FlateScanlineDecoder(); 573ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ~CCodec_FlateScanlineDecoder(); 574ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BOOL Create(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height, int nComps, int bpc, 575ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int predictor, int Colors, int BitsPerComponent, int Columns); 576ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov virtual void Destroy() 577ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 578ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov delete this; 579ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 580ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov virtual void v_DownScale(int dest_width, int dest_height) {} 581ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov virtual FX_BOOL v_Rewind(); 582ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov virtual FX_LPBYTE v_GetNextLine(); 583ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov virtual FX_DWORD GetSrcOffset(); 584ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov void* m_pFlate; 585ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_LPCBYTE m_SrcBuf; 586ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_DWORD m_SrcSize; 587ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_LPBYTE m_pScanline; 588ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_LPBYTE m_pLastLine; 589ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_LPBYTE m_pPredictBuffer; 590ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_LPBYTE m_pPredictRaw; 591ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int m_Predictor; 592ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int m_Colors, m_BitsPerComponent, m_Columns, m_PredictPitch, m_LeftOver; 593ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}; 594ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovCCodec_FlateScanlineDecoder::CCodec_FlateScanlineDecoder() 595ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 596ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_pFlate = NULL; 597ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_pScanline = NULL; 598ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_pLastLine = NULL; 599ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_pPredictBuffer = NULL; 600ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_pPredictRaw = NULL; 601ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_LeftOver = 0; 602ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 603ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovCCodec_FlateScanlineDecoder::~CCodec_FlateScanlineDecoder() 604ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 605ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (m_pScanline) { 606ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_Free(m_pScanline); 607ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 608ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (m_pLastLine) { 609ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_Free(m_pLastLine); 610ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 611ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (m_pPredictBuffer) { 612ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_Free(m_pPredictBuffer); 613ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 614ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (m_pPredictRaw) { 615ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_Free(m_pPredictRaw); 616ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 617ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (m_pFlate) { 618ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FPDFAPI_FlateEnd(m_pFlate); 619ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 620ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 621ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CCodec_FlateScanlineDecoder::Create(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height, 622ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int nComps, int bpc, int predictor, int Colors, int BitsPerComponent, int Columns) 623ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 624ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_SrcBuf = src_buf; 625ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_SrcSize = src_size; 626ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_OutputWidth = m_OrigWidth = width; 627ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_OutputHeight = m_OrigHeight = height; 628ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_nComps = nComps; 629ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_bpc = bpc; 630ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_bColorTransformed = FALSE; 631ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_Pitch = (width * nComps * bpc + 7) / 8; 632ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_pScanline = FX_Alloc(FX_BYTE, m_Pitch); 633ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (m_pScanline == NULL) { 634ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 635ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 636ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_Predictor = 0; 637ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (predictor) { 638ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (predictor >= 10) { 639ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_Predictor = 2; 640ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else if (predictor == 2) { 641ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_Predictor = 1; 642ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 643ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (m_Predictor) { 644ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (BitsPerComponent * Colors * Columns == 0) { 645ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov BitsPerComponent = m_bpc; 646ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Colors = m_nComps; 647ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Columns = m_OrigWidth; 648ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 649ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_Colors = Colors; 650ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_BitsPerComponent = BitsPerComponent; 651ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_Columns = Columns; 652ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_PredictPitch = (m_BitsPerComponent * m_Colors * m_Columns + 7) / 8; 653ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_pLastLine = FX_Alloc(FX_BYTE, m_PredictPitch); 654ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (m_pLastLine == NULL) { 655ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 656ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 657ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FXSYS_memset32(m_pLastLine, 0, m_PredictPitch); 658ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_pPredictRaw = FX_Alloc(FX_BYTE, m_PredictPitch + 1); 659ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (m_pPredictRaw == NULL) { 660ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 661ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 662ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_pPredictBuffer = FX_Alloc(FX_BYTE, m_PredictPitch); 663ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (m_pPredictBuffer == NULL) { 664ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 665ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 666ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 667ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 668ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return TRUE; 669ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 670ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CCodec_FlateScanlineDecoder::v_Rewind() 671ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 672ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (m_pFlate) { 673ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FPDFAPI_FlateEnd(m_pFlate); 674ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 675ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_pFlate = FPDFAPI_FlateInit(my_alloc_func, my_free_func); 676ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (m_pFlate == NULL) { 677ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 678ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 679ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FPDFAPI_FlateInput(m_pFlate, m_SrcBuf, m_SrcSize); 680ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_LeftOver = 0; 681ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return TRUE; 682ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 683ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_LPBYTE CCodec_FlateScanlineDecoder::v_GetNextLine() 684ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 685ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (m_Predictor) { 686ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (m_Pitch == m_PredictPitch) { 687ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (m_Predictor == 2) { 688ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FPDFAPI_FlateOutput(m_pFlate, m_pPredictRaw, m_PredictPitch + 1); 689ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov PNG_PredictLine(m_pScanline, m_pPredictRaw, m_pLastLine, m_BitsPerComponent, m_Colors, m_Columns); 690ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FXSYS_memcpy32(m_pLastLine, m_pScanline, m_PredictPitch); 691ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else { 692ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FPDFAPI_FlateOutput(m_pFlate, m_pScanline, m_Pitch); 693ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TIFF_PredictLine(m_pScanline, m_PredictPitch, m_bpc, m_nComps, m_OutputWidth); 694ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 695ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else { 696ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int bytes_to_go = m_Pitch; 697ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int read_leftover = m_LeftOver > bytes_to_go ? bytes_to_go : m_LeftOver; 698ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (read_leftover) { 699ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FXSYS_memcpy32(m_pScanline, m_pPredictBuffer + m_PredictPitch - m_LeftOver, read_leftover); 700ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_LeftOver -= read_leftover; 701ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov bytes_to_go -= read_leftover; 702ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 703ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while (bytes_to_go) { 704ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (m_Predictor == 2) { 705ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FPDFAPI_FlateOutput(m_pFlate, m_pPredictRaw, m_PredictPitch + 1); 706ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov PNG_PredictLine(m_pPredictBuffer, m_pPredictRaw, m_pLastLine, m_BitsPerComponent, m_Colors, m_Columns); 707ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FXSYS_memcpy32(m_pLastLine, m_pPredictBuffer, m_PredictPitch); 708ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else { 709ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FPDFAPI_FlateOutput(m_pFlate, m_pPredictBuffer, m_PredictPitch); 710ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TIFF_PredictLine(m_pPredictBuffer, m_PredictPitch, m_BitsPerComponent, m_Colors, m_Columns); 711ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 712ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int read_bytes = m_PredictPitch > bytes_to_go ? bytes_to_go : m_PredictPitch; 713ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FXSYS_memcpy32(m_pScanline + m_Pitch - bytes_to_go, m_pPredictBuffer, read_bytes); 714ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov m_LeftOver += m_PredictPitch - read_bytes; 715ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov bytes_to_go -= read_bytes; 716ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 717ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 718ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else { 719ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FPDFAPI_FlateOutput(m_pFlate, m_pScanline, m_Pitch); 720ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 721ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return m_pScanline; 722ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 723ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_DWORD CCodec_FlateScanlineDecoder::GetSrcOffset() 724ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 725ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FPDFAPI_FlateGetTotalIn(m_pFlate); 726ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 727ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic void FlateUncompress(FX_LPCBYTE src_buf, FX_DWORD src_size, FX_DWORD orig_size, 728ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_LPBYTE& dest_buf, FX_DWORD& dest_size, FX_DWORD& offset) 729ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 730ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_DWORD guess_size = orig_size ? orig_size : src_size * 2; 731ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_DWORD alloc_step = orig_size ? 10240 : (src_size < 10240 ? 10240 : src_size); 732ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static const FX_DWORD kMaxInitialAllocSize = 10000000; 733ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (guess_size > kMaxInitialAllocSize) { 734ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov guess_size = kMaxInitialAllocSize; 735ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov alloc_step = kMaxInitialAllocSize; 736ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 737ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_LPBYTE guess_buf = FX_Alloc(FX_BYTE, guess_size + 1); 738ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!guess_buf) { 739ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dest_buf = NULL; 740ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dest_size = 0; 741ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 742ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 743ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov guess_buf[guess_size] = '\0'; 744ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BOOL useOldImpl = src_size < 10240; 745ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov void* context = FPDFAPI_FlateInit(my_alloc_func, my_free_func); 746ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (context == NULL) { 747ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dest_buf = NULL; 748ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dest_size = 0; 749ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return ; 750ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 751ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FPDFAPI_FlateInput(context, src_buf, src_size); 752ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CFX_ArrayTemplate<FX_LPBYTE> result_tmp_bufs; 753ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_LPBYTE buf = guess_buf; 754ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_DWORD buf_size = guess_size; 755ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_DWORD last_buf_size = buf_size; 756ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while (1) { 757ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_INT32 ret = FPDFAPI_FlateOutput(context, buf, buf_size); 758ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_INT32 avail_buf_size = FPDFAPI_FlateGetAvailOut(context); 759ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!useOldImpl) { 760ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (ret != Z_OK) { 761ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov last_buf_size = buf_size - avail_buf_size; 762ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov result_tmp_bufs.Add(buf); 763ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 764ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 765ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (avail_buf_size == 0) { 766ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov result_tmp_bufs.Add(buf); 767ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov buf = NULL; 768ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov buf = FX_Alloc(FX_BYTE, buf_size + 1); 769ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!buf) { 770ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dest_buf = NULL; 771ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dest_size = 0; 772ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 773ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 774ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov buf[buf_size] = '\0'; 775ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else { 776ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov last_buf_size = buf_size - avail_buf_size; 777ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov result_tmp_bufs.Add(buf); 778ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov buf = NULL; 779ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 780ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 781ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else { 782ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (ret != Z_OK) { 783ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 784ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 785ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (avail_buf_size == 0) { 786ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_DWORD old_size = guess_size; 787ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov guess_size += alloc_step; 788ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (guess_size < old_size || guess_size + 1 < guess_size) { 789ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dest_buf = NULL; 790ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dest_size = 0; 791ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 792ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 793ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov guess_buf = FX_Realloc(FX_BYTE, guess_buf, guess_size + 1); 794ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!guess_buf) { 795ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dest_buf = NULL; 796ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dest_size = 0; 797ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 798ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 799ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov guess_buf[guess_size] = '\0'; 800ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov buf = guess_buf + old_size; 801ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov buf_size = guess_size - old_size; 802ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else { 803ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 804ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 805ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 806ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 807ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dest_size = FPDFAPI_FlateGetTotalOut(context); 808ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov offset = FPDFAPI_FlateGetTotalIn(context); 809ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!useOldImpl) { 810ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (result_tmp_bufs.GetSize() == 1) { 811ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dest_buf = result_tmp_bufs[0]; 812ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else { 813ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_LPBYTE result_buf = FX_Alloc(FX_BYTE, dest_size); 814ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!result_buf) { 815ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dest_buf = NULL; 816ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dest_size = 0; 817ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 818ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 819ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_DWORD result_pos = 0; 820ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (FX_INT32 i = 0; i < result_tmp_bufs.GetSize(); i++) { 821ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_LPBYTE tmp_buf = result_tmp_bufs[i]; 822ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_DWORD tmp_buf_size = buf_size; 823ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (i == result_tmp_bufs.GetSize() - 1) { 824ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tmp_buf_size = last_buf_size; 825ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 826ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FXSYS_memcpy32(result_buf + result_pos, tmp_buf, tmp_buf_size); 827ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov result_pos += tmp_buf_size; 828ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_Free(tmp_buf); 829ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tmp_buf = NULL; 830ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov result_tmp_bufs[i] = NULL; 831ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 832ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dest_buf = result_buf; 833ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 834ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else { 835ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (guess_size / 2 > dest_size) { 836ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov guess_buf = FX_Realloc(FX_BYTE, guess_buf, dest_size + 1); 837ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!guess_buf) { 838ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dest_buf = NULL; 839ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dest_size = 0; 840ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 841ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 842ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov guess_size = dest_size; 843ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov guess_buf[guess_size] = '\0'; 844ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 845ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dest_buf = guess_buf; 846ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 847ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FPDFAPI_FlateEnd(context); 848ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov context = NULL; 849ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 850ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovICodec_ScanlineDecoder* CCodec_FlateModule::CreateDecoder(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height, 851ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int nComps, int bpc, int predictor, int Colors, int BitsPerComponent, int Columns) 852ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 853ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CCodec_FlateScanlineDecoder* pDecoder = FX_NEW CCodec_FlateScanlineDecoder; 854ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (pDecoder == NULL) { 855ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 856ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 857ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pDecoder->Create(src_buf, src_size, width, height, nComps, bpc, predictor, Colors, BitsPerComponent, Columns); 858ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return pDecoder; 859ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 860ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_DWORD CCodec_FlateModule::FlateOrLZWDecode(FX_BOOL bLZW, const FX_BYTE* src_buf, FX_DWORD src_size, FX_BOOL bEarlyChange, 861ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int predictor, int Colors, int BitsPerComponent, int Columns, 862ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_DWORD estimated_size, FX_LPBYTE& dest_buf, FX_DWORD& dest_size) 863ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 864ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov CLZWDecoder* pDecoder = NULL; 865ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dest_buf = NULL; 866ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_DWORD offset = 0; 867ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int predictor_type = 0; 868ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (predictor) { 869ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (predictor >= 10) { 870ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov predictor_type = 2; 871ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else if (predictor == 2) { 872ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov predictor_type = 1; 873ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 874ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 875ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (bLZW) { 876ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pDecoder = FX_NEW CLZWDecoder; 877ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (pDecoder == NULL) { 878ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 879ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 880ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dest_size = (FX_DWORD) - 1; 881ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov offset = src_size; 882ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int err = pDecoder->Decode(NULL, dest_size, src_buf, offset, bEarlyChange); 883ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov delete pDecoder; 884ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (err || dest_size == 0 || dest_size + 1 < dest_size) { 885ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return (FX_DWORD) - 1; 886ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 887ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pDecoder = FX_NEW CLZWDecoder; 888ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (pDecoder == NULL) { 889ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 890ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 891ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dest_buf = FX_Alloc( FX_BYTE, dest_size + 1); 892ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (dest_buf == NULL) { 893ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 894ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 895ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dest_buf[dest_size] = '\0'; 896ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pDecoder->Decode(dest_buf, dest_size, src_buf, offset, bEarlyChange); 897ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov delete pDecoder; 898ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else { 899ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FlateUncompress(src_buf, src_size, estimated_size, dest_buf, dest_size, offset); 900ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 901ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (predictor_type == 0) { 902ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return offset; 903ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 904ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (predictor_type == 2) { 905ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov PNG_Predictor(dest_buf, dest_size, Colors, BitsPerComponent, Columns); 906ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else if (predictor_type == 1) { 907ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TIFF_Predictor(dest_buf, dest_size, Colors, BitsPerComponent, Columns); 908ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 909ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return offset; 910ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 911ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CCodec_FlateModule::Encode(const FX_BYTE* src_buf, FX_DWORD src_size, 912ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int predictor, int Colors, int BitsPerComponent, int Columns, 913ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_LPBYTE& dest_buf, FX_DWORD& dest_size) 914ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 915ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (predictor != 2 && predictor < 10) { 916ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return Encode(src_buf, src_size, dest_buf, dest_size); 917ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 918ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_BOOL ret = FALSE; 919ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_LPBYTE pSrcBuf = NULL; 920ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pSrcBuf = FX_Alloc(FX_BYTE, src_size); 921ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (pSrcBuf == NULL) { 922ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 923ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 924ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FXSYS_memcpy32(pSrcBuf, src_buf, src_size); 925ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (predictor == 2) { 926ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TIFF_PredictorEncode(pSrcBuf, src_size, Colors, BitsPerComponent, Columns); 927ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else if (predictor >= 10) { 928ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov PNG_PredictorEncode(pSrcBuf, src_size, predictor, Colors, BitsPerComponent, Columns); 929ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 930ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ret = Encode(pSrcBuf, src_size, dest_buf, dest_size); 931ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FX_Free(pSrcBuf); 932ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return ret; 933ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 934ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CCodec_FlateModule::Encode(FX_LPCBYTE src_buf, FX_DWORD src_size, FX_LPBYTE& dest_buf, FX_DWORD& dest_size) 935ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 936ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dest_size = src_size + src_size / 1000 + 12; 937ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dest_buf = FX_Alloc( FX_BYTE, dest_size); 938ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (dest_buf == NULL) { 939ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 940ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 941ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov unsigned long temp_size = dest_size; 942ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FPDFAPI_FlateCompress(dest_buf, &temp_size, src_buf, src_size); 943ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dest_size = (FX_DWORD)temp_size; 944ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return TRUE; 945ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 946