1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
7 #include "../../fx_zlib.h"
8 #include "../../../include/fpdfapi/fpdf_parser.h"
9 #include "../../../include/fxcodec/fx_codec.h"
10 #include "../../../include/fpdfapi/fpdf_module.h"
11 #include "filters_int.h"
12 CFX_DataFilter::CFX_DataFilter()
18 CFX_DataFilter::~CFX_DataFilter()
24 void CFX_DataFilter::SetDestFilter(CFX_DataFilter* pFilter)
27 m_pDestFilter->SetDestFilter(pFilter);
29 m_pDestFilter = pFilter;
32 void CFX_DataFilter::FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf)
39 CFX_BinaryBuf temp_buf;
40 temp_buf.EstimateSize(FPDF_FILTER_BUFFER_SIZE, FPDF_FILTER_BUFFER_SIZE);
41 v_FilterIn(src_buf, src_size, temp_buf);
42 m_pDestFilter->FilterIn(temp_buf.GetBuffer(), temp_buf.GetSize(), dest_buf);
44 v_FilterIn(src_buf, src_size, dest_buf);
47 void CFX_DataFilter::FilterFinish(CFX_BinaryBuf& dest_buf)
50 CFX_BinaryBuf temp_buf;
51 v_FilterFinish(temp_buf);
52 if (temp_buf.GetSize()) {
53 m_pDestFilter->FilterIn(temp_buf.GetBuffer(), temp_buf.GetSize(), dest_buf);
55 m_pDestFilter->FilterFinish(dest_buf);
57 v_FilterFinish(dest_buf);
61 void CFX_DataFilter::ReportEOF(FX_DWORD left_input)
67 m_SrcPos -= left_input;
69 CFX_DataFilter* FPDF_CreateFilter(FX_BSTR name, const CPDF_Dictionary* pParam, int width, int height)
71 FX_DWORD id = name.GetID();
73 case FXBSTR_ID('F', 'l', 'a', 't'):
74 case FXBSTR_ID('F', 'l', 0, 0):
75 case FXBSTR_ID('L', 'Z', 'W', 'D'):
76 case FXBSTR_ID('L', 'Z', 'W', 0): {
77 CFX_DataFilter* pFilter;
78 if (id == FXBSTR_ID('L', 'Z', 'W', 'D') || id == FXBSTR_ID('L', 'Z', 'W', 0)) {
79 pFilter = new CPDF_LzwFilter(pParam ? pParam->GetInteger("EarlyChange", 1) : 1);
81 pFilter = new CPDF_FlateFilter;
83 if ((pParam ? pParam->GetInteger("Predictor", 1) : 1) > 1) {
84 CFX_DataFilter* pPredictor = new CPDF_PredictorFilter(pParam->GetInteger(FX_BSTRC("Predictor"), 1),
85 pParam->GetInteger(FX_BSTRC("Colors"), 1), pParam->GetInteger(FX_BSTRC("BitsPerComponent"), 8),
86 pParam->GetInteger(FX_BSTRC("Columns"), 1));
87 pFilter->SetDestFilter(pPredictor);
91 case FXBSTR_ID('A', 'S', 'C', 'I'):
92 if (name == "ASCIIHexDecode") {
93 return new CPDF_AsciiHexFilter;
95 return new CPDF_Ascii85Filter;
96 case FXBSTR_ID('A', 'H', 'x', 0):
97 return new CPDF_AsciiHexFilter;
98 case FXBSTR_ID('A', '8', '5', 0):
99 return new CPDF_Ascii85Filter;
100 case FXBSTR_ID('R', 'u', 'n', 'L'):
101 return new CPDF_RunLenFilter;
102 case FXBSTR_ID('C', 'C', 'I', 'T'): {
104 int bEndOfLine = FALSE;
105 int bByteAlign = FALSE;
110 Encoding = pParam->GetInteger(FX_BSTRC("K"));
111 bEndOfLine = pParam->GetInteger(FX_BSTRC("EndOfLine"));
112 bByteAlign = pParam->GetInteger(FX_BSTRC("EncodedByteAlign"));
113 bBlack = pParam->GetInteger(FX_BSTRC("BlackIs1"));
114 nColumns = pParam->GetInteger(FX_BSTRC("Columns"), 1728);
115 nRows = pParam->GetInteger(FX_BSTRC("Rows"));
123 CPDF_FaxFilter* pFilter = new CPDF_FaxFilter();
124 pFilter->Initialize(Encoding, bEndOfLine, bByteAlign, bBlack, nRows, nColumns);
127 case FXBSTR_ID('D', 'C', 'T', 'D'):
128 return new CPDF_JpegFilter;
133 CFX_DataFilter* _FPDF_CreateFilterFromDict(CPDF_Dictionary* pDict)
135 CPDF_Object* pDecoder = pDict->GetElementValue("Filter");
136 if (pDecoder == NULL) {
139 CFX_DataFilter* pFirstFilter = NULL;
140 int width = pDict->GetInteger(FX_BSTRC("Width")), height = pDict->GetInteger(FX_BSTRC("Height"));
141 CPDF_Object* pParams = pDict->GetElementValue("DecodeParms");
142 if (pDecoder->GetType() == PDFOBJ_ARRAY) {
143 if (pParams && pParams->GetType() != PDFOBJ_ARRAY) {
146 for (FX_DWORD i = 0; i < ((CPDF_Array*)pDecoder)->GetCount(); i ++) {
147 CFX_ByteString name = ((CPDF_Array*)pDecoder)->GetString(i);
148 CPDF_Dictionary* pParam = NULL;
150 pParam = ((CPDF_Array*)pParams)->GetDict(i);
152 CFX_DataFilter* pDestFilter = FPDF_CreateFilter(name, pParam, width, height);
154 if (pFirstFilter == NULL) {
155 pFirstFilter = pDestFilter;
157 pFirstFilter->SetDestFilter(pDestFilter);
162 if (pParams && pParams->GetType() != PDFOBJ_DICTIONARY) {
165 pFirstFilter = FPDF_CreateFilter(pDecoder->GetString(), (CPDF_Dictionary*)pParams, width, height);
169 CPDF_StreamFilter* CPDF_Stream::GetStreamFilter(FX_BOOL bRaw) const
171 CFX_DataFilter* pFirstFilter = NULL;
172 if (m_pCryptoHandler) {
173 pFirstFilter = new CPDF_DecryptFilter(m_pCryptoHandler, m_ObjNum, m_GenNum);
176 CFX_DataFilter* pFilter = _FPDF_CreateFilterFromDict(m_pDict);
178 if (pFirstFilter == NULL) {
179 pFirstFilter = pFilter;
181 pFirstFilter->SetDestFilter(pFilter);
185 CPDF_StreamFilter* pStreamFilter = new CPDF_StreamFilter;
186 pStreamFilter->m_pStream = this;
187 pStreamFilter->m_pFilter = pFirstFilter;
188 pStreamFilter->m_pBuffer = NULL;
189 pStreamFilter->m_SrcOffset = 0;
190 return pStreamFilter;
192 CPDF_StreamFilter::~CPDF_StreamFilter()
201 #define FPDF_FILTER_BUFFER_IN_SIZE FPDF_FILTER_BUFFER_SIZE
202 FX_DWORD CPDF_StreamFilter::ReadBlock(FX_LPBYTE buffer, FX_DWORD buf_size)
204 if (m_pFilter == NULL) {
205 FX_DWORD read_size = m_pStream->GetRawSize() - m_SrcOffset;
206 if (read_size == 0) {
209 if (read_size > buf_size) {
210 read_size = buf_size;
212 m_pStream->ReadRawData(m_SrcOffset, buffer, read_size);
213 m_SrcOffset += read_size;
216 FX_DWORD read_size = 0;
218 read_size = ReadLeftOver(buffer, buf_size);
219 if (read_size == buf_size) {
223 buf_size -= read_size;
225 ASSERT(m_pBuffer == NULL);
226 if (m_pFilter->IsEOF()) {
229 m_pBuffer = new CFX_BinaryBuf;
230 m_pBuffer->EstimateSize(FPDF_FILTER_BUFFER_SIZE, FPDF_FILTER_BUFFER_SIZE);
233 int src_size = m_pStream->GetRawSize() - m_SrcOffset;
235 m_pFilter->FilterFinish(*m_pBuffer);
238 if (src_size > FPDF_FILTER_BUFFER_IN_SIZE) {
239 src_size = FPDF_FILTER_BUFFER_IN_SIZE;
241 if (!m_pStream->ReadRawData(m_SrcOffset, m_SrcBuffer, src_size)) {
244 m_SrcOffset += src_size;
245 m_pFilter->FilterIn(m_SrcBuffer, src_size, *m_pBuffer);
246 if (m_pBuffer->GetSize() >= (int)buf_size) {
250 return read_size + ReadLeftOver(buffer, buf_size);
252 FX_DWORD CPDF_StreamFilter::ReadLeftOver(FX_LPBYTE buffer, FX_DWORD buf_size)
254 FX_DWORD read_size = m_pBuffer->GetSize() - m_BufOffset;
255 if (read_size > buf_size) {
256 read_size = buf_size;
258 FXSYS_memcpy32(buffer, m_pBuffer->GetBuffer() + m_BufOffset, read_size);
259 m_BufOffset += read_size;
260 if (m_BufOffset == (FX_DWORD)m_pBuffer->GetSize()) {
266 CPDF_DecryptFilter::CPDF_DecryptFilter(CPDF_CryptoHandler* pCryptoHandler, FX_DWORD objnum, FX_DWORD gennum)
268 m_pCryptoHandler = pCryptoHandler;
273 CPDF_DecryptFilter::~CPDF_DecryptFilter()
277 m_pCryptoHandler->DecryptFinish(m_pContext, buf);
280 void CPDF_DecryptFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf)
282 if (m_pContext == NULL) {
283 m_pContext = m_pCryptoHandler->DecryptStart(m_ObjNum, m_GenNum);
285 m_pCryptoHandler->DecryptStream(m_pContext, src_buf, src_size, dest_buf);
287 void CPDF_DecryptFilter::v_FilterFinish(CFX_BinaryBuf& dest_buf)
290 if (m_pContext == NULL) {
293 m_pCryptoHandler->DecryptFinish(m_pContext, dest_buf);
297 static void* my_alloc_func (void* opaque, unsigned int items, unsigned int size)
299 return FX_Alloc(FX_BYTE, items * size);
301 static void my_free_func (void* opaque, void* address)
305 void* FPDFAPI_FlateInit(void* (*alloc_func)(void*, unsigned int, unsigned int),
306 void (*free_func)(void*, void*));
307 void FPDFAPI_FlateInput(void* context, const unsigned char* src_buf, unsigned int src_size);
308 int FPDFAPI_FlateOutput(void* context, unsigned char* dest_buf, unsigned int dest_size);
309 int FPDFAPI_FlateGetAvailIn(void* context);
310 int FPDFAPI_FlateGetAvailOut(void* context);
311 void FPDFAPI_FlateEnd(void* context);
313 CPDF_FlateFilter::CPDF_FlateFilter()
317 CPDF_FlateFilter::~CPDF_FlateFilter()
320 FPDFAPI_FlateEnd(m_pContext);
323 void CPDF_FlateFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf)
325 if (m_pContext == NULL) {
326 m_pContext = FPDFAPI_FlateInit(my_alloc_func, my_free_func);
328 FPDFAPI_FlateInput(m_pContext, src_buf, src_size);
330 int ret = FPDFAPI_FlateOutput(m_pContext, m_DestBuffer, FPDF_FILTER_BUFFER_SIZE);
331 int out_size = FPDF_FILTER_BUFFER_SIZE - FPDFAPI_FlateGetAvailOut(m_pContext);
332 dest_buf.AppendBlock(m_DestBuffer, out_size);
333 if (ret == Z_BUF_ERROR) {
337 ReportEOF(FPDFAPI_FlateGetAvailIn(m_pContext));
342 CPDF_LzwFilter::CPDF_LzwFilter(FX_BOOL bEarlyChange)
344 m_bEarlyChange = bEarlyChange ? 1 : 0;
349 m_OldCode = (FX_DWORD) - 1;
351 void CPDF_LzwFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf)
353 for (FX_DWORD i = 0; i < src_size; i ++) {
354 if (m_nLeftBits + 8 < m_CodeLen) {
356 m_LeftBits = (m_LeftBits << 8) | src_buf[i];
359 FX_DWORD new_bits = m_CodeLen - m_nLeftBits;
360 FX_DWORD code = (m_LeftBits << new_bits) | (src_buf[i] >> (8 - new_bits));
361 m_nLeftBits = 8 - new_bits;
362 m_LeftBits = src_buf[i] % (1 << m_nLeftBits);
364 dest_buf.AppendByte((FX_BYTE)code);
365 m_LastChar = (FX_BYTE)code;
366 if (m_OldCode != -1) {
367 AddCode(m_OldCode, m_LastChar);
370 } else if (code == 256) {
373 m_OldCode = (FX_DWORD) - 1;
374 } else if (code == 257) {
375 ReportEOF(src_size - i - 1);
378 if (m_OldCode == -1) {
379 ReportEOF(src_size - i - 1);
383 if (code >= m_nCodes + 258) {
384 if (m_StackLen < sizeof(m_DecodeStack)) {
385 m_DecodeStack[m_StackLen++] = m_LastChar;
387 DecodeString(m_OldCode);
391 dest_buf.AppendBlock(NULL, m_StackLen);
392 FX_LPBYTE pOutput = dest_buf.GetBuffer() + dest_buf.GetSize() - m_StackLen;
393 for (FX_DWORD cc = 0; cc < m_StackLen; cc ++) {
394 pOutput[cc] = m_DecodeStack[m_StackLen - cc - 1];
396 m_LastChar = m_DecodeStack[m_StackLen - 1];
397 if (m_OldCode < 256) {
398 AddCode(m_OldCode, m_LastChar);
399 } else if (m_OldCode - 258 >= m_nCodes) {
400 ReportEOF(src_size - i - 1);
403 AddCode(m_OldCode, m_LastChar);
409 void CPDF_LzwFilter::AddCode(FX_DWORD prefix_code, FX_BYTE append_char)
411 if (m_nCodes + m_bEarlyChange == 4094) {
414 m_CodeArray[m_nCodes ++] = (prefix_code << 16) | append_char;
415 if (m_nCodes + m_bEarlyChange == 512 - 258) {
417 } else if (m_nCodes + m_bEarlyChange == 1024 - 258) {
419 } else if (m_nCodes + m_bEarlyChange == 2048 - 258) {
423 void CPDF_LzwFilter::DecodeString(FX_DWORD code)
426 int index = code - 258;
427 if (index < 0 || index >= (int)m_nCodes) {
430 FX_DWORD data = m_CodeArray[index];
431 if (m_StackLen >= sizeof(m_DecodeStack)) {
434 m_DecodeStack[m_StackLen++] = (FX_BYTE)data;
437 if (m_StackLen >= sizeof(m_DecodeStack)) {
440 m_DecodeStack[m_StackLen++] = (FX_BYTE)code;
442 CPDF_PredictorFilter::CPDF_PredictorFilter(int predictor, int colors, int bpc, int cols)
444 m_bTiff = predictor < 10;
449 m_Bpp = (colors * bpc + 7) / 8;
450 m_Pitch = (colors * bpc * cols + 7) / 8;
455 CPDF_PredictorFilter::~CPDF_PredictorFilter()
464 static FX_BYTE PaethPredictor(int a, int b, int c)
467 int pa = FXSYS_abs(p - a);
468 int pb = FXSYS_abs(p - b);
469 int pc = FXSYS_abs(p - c);
470 if (pa <= pb && pa <= pc) {
478 static void PNG_PredictorLine(FX_LPBYTE cur_buf, FX_LPBYTE ref_buf, int pitch, int Bpp)
480 FX_BYTE tag = cur_buf[0];
488 for (int byte = 0; byte < pitch; byte ++) {
489 FX_BYTE raw_byte = cur_buf[byte];
494 left = cur_buf[byte - Bpp];
496 cur_buf[byte] = raw_byte + left;
504 cur_buf[byte] = raw_byte + up;
510 left = cur_buf[byte - Bpp];
516 cur_buf[byte] = raw_byte + (up + left) / 2;
522 left = cur_buf[byte - Bpp];
528 FX_BYTE upper_left = 0;
529 if (byte >= Bpp && ref_buf) {
530 upper_left = ref_buf[byte - Bpp];
532 cur_buf[byte] = raw_byte + PaethPredictor(left, up, upper_left);
538 void CPDF_PredictorFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf)
540 if (m_pCurLine == NULL) {
541 m_pCurLine = FX_Alloc(FX_BYTE, m_Pitch);
543 m_pRefLine = FX_Alloc(FX_BYTE, m_Pitch);
547 FX_DWORD read_size = m_Pitch - m_LineInSize;
548 if (read_size > src_size) {
549 read_size = src_size;
551 FXSYS_memcpy32(m_pCurLine + m_LineInSize, src_buf, read_size);
552 m_LineInSize += read_size;
553 if (m_LineInSize < m_Pitch) {
556 src_buf += read_size;
557 src_size -= read_size;
559 for (FX_DWORD byte = m_Bpp; byte < m_Pitch; byte ++) {
560 m_pCurLine[byte] += m_pCurLine[byte - m_Bpp];
562 dest_buf.AppendBlock(m_pCurLine, m_Pitch);
564 PNG_PredictorLine(m_pCurLine, m_iLine ? m_pRefLine : NULL, m_Pitch - 1, m_Bpp);
565 dest_buf.AppendBlock(m_pCurLine + 1, m_Pitch - 1);
567 FX_LPBYTE temp = m_pCurLine;
568 m_pCurLine = m_pRefLine;
574 CPDF_Ascii85Filter::CPDF_Ascii85Filter()
579 void CPDF_Ascii85Filter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf)
581 for (FX_DWORD i = 0; i < src_size; i ++) {
582 FX_BYTE byte = src_buf[i];
583 if (PDF_CharType[byte] == 'W') {
588 if (byte >= '!' && byte <= 'u') {
589 int digit = byte - '!';
593 } else if (byte == 'z') {
595 dest_buf.AppendBlock(&zero, 4);
596 } else if (byte == '~') {
601 if (byte >= '!' && byte <= 'u') {
602 int digit = byte - '!';
603 m_CurDWord = m_CurDWord * 85 + digit;
605 if (m_CharCount == 5) {
606 for (int i = 0; i < 4; i ++) {
607 dest_buf.AppendByte((FX_BYTE)(m_CurDWord >> (3 - i) * 8));
611 } else if (byte == '~') {
612 if (m_CharCount > 1) {
614 for (i = m_CharCount; i < 5; i ++) {
615 m_CurDWord = m_CurDWord * 85 + 84;
617 for (i = 0; i < m_CharCount - 1; i ++) {
618 dest_buf.AppendByte((FX_BYTE)(m_CurDWord >> (3 - i) * 8));
627 ReportEOF(src_size - i - 1);
634 CPDF_AsciiHexFilter::CPDF_AsciiHexFilter()
638 void CPDF_AsciiHexFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf)
640 for (FX_DWORD i = 0; i < src_size; i ++) {
641 FX_BYTE byte = src_buf[i];
642 if (PDF_CharType[byte] == 'W') {
646 if (byte >= '0' && byte <= '9') {
648 } else if (byte >= 'a' && byte <= 'f') {
649 digit = byte - 'a' + 10;
650 } else if (byte >= 'A' && byte <= 'F') {
651 digit = byte - 'A' + 10;
654 dest_buf.AppendByte(m_FirstDigit * 16);
656 ReportEOF(src_size - i - 1);
660 m_FirstDigit = digit;
663 dest_buf.AppendByte(m_FirstDigit * 16 + digit);
668 CPDF_RunLenFilter::CPDF_RunLenFilter()
673 void CPDF_RunLenFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf)
675 for (FX_DWORD i = 0; i < src_size; i ++) {
676 FX_BYTE byte = src_buf[i];
682 } else if (byte == 128) {
683 ReportEOF(src_size - i - 1);
687 m_Count = 257 - byte;
691 dest_buf.AppendByte(byte);
698 dest_buf.AppendBlock(NULL, m_Count);
699 FXSYS_memset8(dest_buf.GetBuffer() + dest_buf.GetSize() - m_Count, byte, m_Count);
706 CPDF_JpegFilter::CPDF_JpegFilter()
709 m_bGotHeader = FALSE;
713 CPDF_JpegFilter::~CPDF_JpegFilter()
716 FX_Free(m_pScanline);
719 CPDF_ModuleMgr::Get()->GetJpegModule()->Finish(m_pContext);
722 void CPDF_JpegFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf)
724 if (m_pContext == NULL) {
725 m_pContext = CPDF_ModuleMgr::Get()->GetJpegModule()->Start();
727 FX_LPCBYTE jpeg_src_buf;
728 FX_DWORD jpeg_src_size;
729 CFX_BinaryBuf temp_buf;
730 if (m_InputBuf.GetSize()) {
731 temp_buf.EstimateSize(m_InputBuf.GetSize() + src_size);
732 temp_buf.AppendBlock(m_InputBuf.GetBuffer(), m_InputBuf.GetSize());
734 temp_buf.AppendBlock(src_buf, src_size);
735 jpeg_src_buf = temp_buf.GetBuffer();
736 jpeg_src_size = temp_buf.GetSize();
738 jpeg_src_buf = src_buf;
739 jpeg_src_size = src_size;
741 CPDF_ModuleMgr::Get()->GetJpegModule()->Input(m_pContext, jpeg_src_buf, jpeg_src_size);
743 int ret = CPDF_ModuleMgr::Get()->GetJpegModule()->ReadHeader(m_pContext, &m_Width, &m_Height, &m_nComps);
744 int left_size = CPDF_ModuleMgr::Get()->GetJpegModule()->GetAvailInput(m_pContext);
746 ReportEOF(left_size);
750 m_InputBuf.AppendBlock(jpeg_src_buf + jpeg_src_size - left_size, left_size);
753 CPDF_ModuleMgr::Get()->GetJpegModule()->StartScanline(m_pContext, 1);
755 m_Pitch = m_Width * m_nComps;
757 if (m_pScanline == NULL) {
758 m_pScanline = FX_Alloc(FX_BYTE, m_Pitch + 4);
761 if (!CPDF_ModuleMgr::Get()->GetJpegModule()->ReadScanline(m_pContext, m_pScanline)) {
762 int left_size = CPDF_ModuleMgr::Get()->GetJpegModule()->GetAvailInput(m_pContext);
763 m_InputBuf.AppendBlock(jpeg_src_buf + jpeg_src_size - left_size, left_size);
766 dest_buf.AppendBlock(m_pScanline, m_Pitch);
768 if (m_iLine == m_Height) {
769 ReportEOF(CPDF_ModuleMgr::Get()->GetJpegModule()->GetAvailInput(m_pContext));
774 CPDF_FaxFilter::CPDF_FaxFilter()
777 m_bEndOfLine = FALSE;
778 m_bByteAlign = FALSE;
783 m_pScanlineBuf = NULL;
788 CPDF_FaxFilter::~CPDF_FaxFilter()
790 if (m_pScanlineBuf) {
791 FX_Free(m_pScanlineBuf);
797 FX_BOOL CPDF_FaxFilter::Initialize(int Encoding, int bEndOfLine, int bByteAlign, int bBlack, int nRows, int nColumns)
799 m_Encoding = Encoding;
800 m_bEndOfLine = bEndOfLine;
801 m_bByteAlign = bByteAlign;
804 m_nColumns = nColumns;
805 m_Pitch = (m_nColumns + 7) / 8;
806 m_pScanlineBuf = FX_Alloc(FX_BYTE, m_Pitch);
807 m_pRefBuf = FX_Alloc(FX_BYTE, m_Pitch);
808 FXSYS_memset8(m_pScanlineBuf, 0xff, m_Pitch);
809 FXSYS_memset8(m_pRefBuf, 0xff, m_Pitch);
814 void CPDF_FaxFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf)
816 FX_LPCBYTE fax_src_buf;
817 FX_DWORD fax_src_size;
818 CFX_BinaryBuf temp_buf;
820 if (m_InputBuf.GetSize()) {
821 temp_buf.EstimateSize(m_InputBuf.GetSize() + src_size);
822 temp_buf.AppendBlock(m_InputBuf.GetBuffer(), m_InputBuf.GetSize());
824 temp_buf.AppendBlock(src_buf, src_size);
825 fax_src_buf = temp_buf.GetBuffer();
826 fax_src_size = temp_buf.GetSize();
827 bitpos = m_InputBitPos;
829 fax_src_buf = src_buf;
830 fax_src_size = src_size;
833 ProcessData(fax_src_buf, fax_src_size, bitpos, FALSE, dest_buf);
834 int left_bits = fax_src_size * 8 - bitpos;
835 m_InputBuf.AppendBlock(fax_src_buf + bitpos / 8, (left_bits + 7) / 8);
836 m_InputBitPos = bitpos % 8;
838 void CPDF_FaxFilter::v_FilterFinish(CFX_BinaryBuf& dest_buf)
840 ProcessData(m_InputBuf.GetBuffer(), m_InputBuf.GetSize(), m_InputBitPos, TRUE, dest_buf);
842 FX_BOOL _FaxSkipEOL(const FX_BYTE* src_buf, int bitsize, int& bitpos);
843 FX_BOOL _FaxG4GetRow(const FX_BYTE* src_buf, int bitsize, int& bitpos, FX_LPBYTE dest_buf, const FX_BYTE* ref_buf, int columns);
844 FX_BOOL _FaxGet1DLine(const FX_BYTE* src_buf, int bitsize, int& bitpos, FX_LPBYTE dest_buf, int columns);
845 void CPDF_FaxFilter::ProcessData(FX_LPCBYTE src_buf, FX_DWORD src_size, int& bitpos, FX_BOOL bFinish,
846 CFX_BinaryBuf& dest_buf)
848 int bitsize = src_size * 8;
850 if ((bitsize < bitpos + 256) && !bFinish) {
853 int start_bitpos = bitpos;
854 FXSYS_memset8(m_pScanlineBuf, 0xff, m_Pitch);
855 if (!ReadLine(src_buf, bitsize, bitpos)) {
856 bitpos = start_bitpos;
860 FXSYS_memcpy32(m_pRefBuf, m_pScanlineBuf, m_Pitch);
863 for (int i = 0; i < m_Pitch; i ++) {
864 m_pScanlineBuf[i] = ~m_pScanlineBuf[i];
867 dest_buf.AppendBlock(m_pScanlineBuf, m_Pitch);
869 if (m_iRow == m_nRows) {
870 ReportEOF(src_size - (bitpos + 7) / 8);
875 FX_BOOL CPDF_FaxFilter::ReadLine(FX_LPCBYTE src_buf, int bitsize, int& bitpos)
877 if (!_FaxSkipEOL(src_buf, bitsize, bitpos)) {
881 if (m_Encoding < 0) {
882 ret = _FaxG4GetRow(src_buf, bitsize, bitpos, m_pScanlineBuf, m_pRefBuf, m_nColumns);
883 } else if (m_Encoding == 0) {
884 ret = _FaxGet1DLine(src_buf, bitsize, bitpos, m_pScanlineBuf, m_nColumns);
886 if (bitpos == bitsize) {
889 FX_BOOL bNext1D = src_buf[bitpos / 8] & (1 << (7 - bitpos % 8));
892 ret = _FaxGet1DLine(src_buf, bitsize, bitpos, m_pScanlineBuf, m_nColumns);
894 ret = _FaxG4GetRow(src_buf, bitsize, bitpos, m_pScanlineBuf, m_pRefBuf, m_nColumns);
901 if (!_FaxSkipEOL(src_buf, bitsize, bitpos)) {
905 bitpos = (bitpos + 7) / 8 * 8;