OLD | NEW |
1 // Copyright 2014 PDFium Authors. All rights reserved. | 1 // Copyright 2014 PDFium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
6 | 6 |
7 #include "../../../include/fpdfapi/fpdf_module.h" | 7 #include "../../../include/fpdfapi/fpdf_module.h" |
8 #include "../../../include/fpdfapi/fpdf_page.h" | 8 #include "../../../include/fpdfapi/fpdf_page.h" |
9 #include "../../../include/fxcodec/fx_codec.h" | 9 #include "../../../include/fxcodec/fx_codec.h" |
10 #include "../../../include/fpdfapi/fpdf_render.h" | 10 #include "../../../include/fpdfapi/fpdf_render.h" |
11 #include "../fpdf_page/pageint.h" | 11 #include "../fpdf_page/pageint.h" |
12 #include "../fpdf_render/render_int.h" | 12 #include "../fpdf_render/render_int.h" |
13 CPDF_Dictionary* CPDF_Image::InitJPEG(uint8_t* pData, FX_DWORD size) | 13 CPDF_Dictionary* CPDF_Image::InitJPEG(uint8_t* pData, FX_DWORD size) { |
14 { | 14 int32_t width; |
15 int32_t width; | 15 int32_t height; |
16 int32_t height; | 16 int32_t num_comps; |
17 int32_t num_comps; | 17 int32_t bits; |
18 int32_t bits; | 18 FX_BOOL color_trans; |
19 FX_BOOL color_trans; | 19 if (!CPDF_ModuleMgr::Get()->GetJpegModule()->LoadInfo( |
20 if (!CPDF_ModuleMgr::Get()->GetJpegModule()-> | 20 pData, size, width, height, num_comps, bits, color_trans)) { |
21 LoadInfo(pData, size, width, height, num_comps, bits, color_trans))
{ | 21 return NULL; |
22 return NULL; | 22 } |
23 } | 23 CPDF_Dictionary* pDict = new CPDF_Dictionary; |
24 CPDF_Dictionary* pDict = new CPDF_Dictionary; | 24 pDict->SetAtName("Type", "XObject"); |
25 pDict->SetAtName("Type", "XObject"); | 25 pDict->SetAtName("Subtype", "Image"); |
26 pDict->SetAtName("Subtype", "Image"); | 26 pDict->SetAtInteger("Width", width); |
27 pDict->SetAtInteger("Width", width); | 27 pDict->SetAtInteger("Height", height); |
28 pDict->SetAtInteger("Height", height); | 28 const FX_CHAR* csname = NULL; |
29 const FX_CHAR* csname = NULL; | 29 if (num_comps == 1) { |
30 if (num_comps == 1) { | 30 csname = "DeviceGray"; |
31 csname = "DeviceGray"; | 31 } else if (num_comps == 3) { |
32 } else if (num_comps == 3) { | 32 csname = "DeviceRGB"; |
33 csname = "DeviceRGB"; | 33 } else if (num_comps == 4) { |
34 } else if (num_comps == 4) { | 34 csname = "DeviceCMYK"; |
35 csname = "DeviceCMYK"; | 35 CPDF_Array* pDecode = CPDF_Array::Create(); |
36 CPDF_Array* pDecode = CPDF_Array::Create(); | 36 for (int n = 0; n < 4; n++) { |
37 for (int n = 0; n < 4; n ++) { | 37 pDecode->AddInteger(1); |
38 pDecode->AddInteger(1); | 38 pDecode->AddInteger(0); |
39 pDecode->AddInteger(0); | 39 } |
| 40 pDict->SetAt(FX_BSTRC("Decode"), pDecode); |
| 41 } |
| 42 pDict->SetAtName("ColorSpace", csname); |
| 43 pDict->SetAtInteger("BitsPerComponent", bits); |
| 44 pDict->SetAtName("Filter", "DCTDecode"); |
| 45 if (!color_trans) { |
| 46 CPDF_Dictionary* pParms = new CPDF_Dictionary; |
| 47 pDict->SetAt("DecodeParms", pParms); |
| 48 pParms->SetAtInteger("ColorTransform", 0); |
| 49 } |
| 50 m_bIsMask = FALSE; |
| 51 m_Width = width; |
| 52 m_Height = height; |
| 53 if (m_pStream == NULL) { |
| 54 m_pStream = new CPDF_Stream(NULL, 0, NULL); |
| 55 } |
| 56 return pDict; |
| 57 } |
| 58 void CPDF_Image::SetJpegImage(uint8_t* pData, FX_DWORD size) { |
| 59 CPDF_Dictionary* pDict = InitJPEG(pData, size); |
| 60 if (!pDict) { |
| 61 return; |
| 62 } |
| 63 m_pStream->InitStream(pData, size, pDict); |
| 64 } |
| 65 void CPDF_Image::SetJpegImage(IFX_FileRead* pFile) { |
| 66 FX_DWORD size = (FX_DWORD)pFile->GetSize(); |
| 67 if (!size) { |
| 68 return; |
| 69 } |
| 70 FX_DWORD dwEstimateSize = size; |
| 71 if (dwEstimateSize > 8192) { |
| 72 dwEstimateSize = 8192; |
| 73 } |
| 74 uint8_t* pData = FX_Alloc(uint8_t, dwEstimateSize); |
| 75 pFile->ReadBlock(pData, 0, dwEstimateSize); |
| 76 CPDF_Dictionary* pDict = InitJPEG(pData, dwEstimateSize); |
| 77 FX_Free(pData); |
| 78 if (!pDict && size > dwEstimateSize) { |
| 79 pData = FX_Alloc(uint8_t, size); |
| 80 pFile->ReadBlock(pData, 0, size); |
| 81 pDict = InitJPEG(pData, size); |
| 82 FX_Free(pData); |
| 83 } |
| 84 if (!pDict) { |
| 85 return; |
| 86 } |
| 87 m_pStream->InitStream(pFile, pDict); |
| 88 } |
| 89 void _DCTEncodeBitmap(CPDF_Dictionary* pBitmapDict, |
| 90 const CFX_DIBitmap* pBitmap, |
| 91 int quality, |
| 92 uint8_t*& buf, |
| 93 FX_STRSIZE& size) {} |
| 94 void _JBIG2EncodeBitmap(CPDF_Dictionary* pBitmapDict, |
| 95 const CFX_DIBitmap* pBitmap, |
| 96 CPDF_Document* pDoc, |
| 97 uint8_t*& buf, |
| 98 FX_STRSIZE& size, |
| 99 FX_BOOL bLossLess) {} |
| 100 void CPDF_Image::SetImage(const CFX_DIBitmap* pBitmap, |
| 101 int32_t iCompress, |
| 102 IFX_FileWrite* pFileWrite, |
| 103 IFX_FileRead* pFileRead, |
| 104 const CFX_DIBitmap* pMask, |
| 105 const CPDF_ImageSetParam* pParam) { |
| 106 int32_t BitmapWidth = pBitmap->GetWidth(); |
| 107 int32_t BitmapHeight = pBitmap->GetHeight(); |
| 108 if (BitmapWidth < 1 || BitmapHeight < 1) { |
| 109 return; |
| 110 } |
| 111 uint8_t* src_buf = pBitmap->GetBuffer(); |
| 112 int32_t src_pitch = pBitmap->GetPitch(); |
| 113 int32_t bpp = pBitmap->GetBPP(); |
| 114 FX_BOOL bUseMatte = |
| 115 pParam && pParam->pMatteColor && (pBitmap->GetFormat() == FXDIB_Argb); |
| 116 CPDF_Dictionary* pDict = new CPDF_Dictionary; |
| 117 pDict->SetAtName(FX_BSTRC("Type"), FX_BSTRC("XObject")); |
| 118 pDict->SetAtName(FX_BSTRC("Subtype"), FX_BSTRC("Image")); |
| 119 pDict->SetAtInteger(FX_BSTRC("Width"), BitmapWidth); |
| 120 pDict->SetAtInteger(FX_BSTRC("Height"), BitmapHeight); |
| 121 uint8_t* dest_buf = NULL; |
| 122 FX_STRSIZE dest_pitch = 0, dest_size = 0, opType = -1; |
| 123 if (bpp == 1) { |
| 124 int32_t reset_a = 0, reset_r = 0, reset_g = 0, reset_b = 0; |
| 125 int32_t set_a = 0, set_r = 0, set_g = 0, set_b = 0; |
| 126 if (!pBitmap->IsAlphaMask()) { |
| 127 ArgbDecode(pBitmap->GetPaletteArgb(0), reset_a, reset_r, reset_g, |
| 128 reset_b); |
| 129 ArgbDecode(pBitmap->GetPaletteArgb(1), set_a, set_r, set_g, set_b); |
| 130 } |
| 131 if (set_a == 0 || reset_a == 0) { |
| 132 pDict->SetAt(FX_BSTRC("ImageMask"), new CPDF_Boolean(TRUE)); |
| 133 if (reset_a == 0) { |
| 134 CPDF_Array* pArray = new CPDF_Array; |
| 135 pArray->AddInteger(1); |
| 136 pArray->AddInteger(0); |
| 137 pDict->SetAt(FX_BSTRC("Decode"), pArray); |
| 138 } |
| 139 } else { |
| 140 CPDF_Array* pCS = new CPDF_Array; |
| 141 pCS->AddName(FX_BSTRC("Indexed")); |
| 142 pCS->AddName(FX_BSTRC("DeviceRGB")); |
| 143 pCS->AddInteger(1); |
| 144 CFX_ByteString ct; |
| 145 FX_CHAR* pBuf = ct.GetBuffer(6); |
| 146 pBuf[0] = (FX_CHAR)reset_r; |
| 147 pBuf[1] = (FX_CHAR)reset_g; |
| 148 pBuf[2] = (FX_CHAR)reset_b; |
| 149 pBuf[3] = (FX_CHAR)set_r; |
| 150 pBuf[4] = (FX_CHAR)set_g; |
| 151 pBuf[5] = (FX_CHAR)set_b; |
| 152 ct.ReleaseBuffer(6); |
| 153 pCS->Add(CPDF_String::Create(ct, TRUE)); |
| 154 pDict->SetAt(FX_BSTRC("ColorSpace"), pCS); |
| 155 } |
| 156 pDict->SetAtInteger(FX_BSTRC("BitsPerComponent"), 1); |
| 157 dest_pitch = (BitmapWidth + 7) / 8; |
| 158 if ((iCompress & 0x03) == PDF_IMAGE_NO_COMPRESS) { |
| 159 opType = 1; |
| 160 } else { |
| 161 opType = 0; |
| 162 } |
| 163 } else if (bpp == 8) { |
| 164 int32_t iPalette = pBitmap->GetPaletteSize(); |
| 165 if (iPalette > 0) { |
| 166 CPDF_Array* pCS = new CPDF_Array; |
| 167 m_pDocument->AddIndirectObject(pCS); |
| 168 pCS->AddName(FX_BSTRC("Indexed")); |
| 169 pCS->AddName(FX_BSTRC("DeviceRGB")); |
| 170 pCS->AddInteger(iPalette - 1); |
| 171 uint8_t* pColorTable = FX_Alloc2D(uint8_t, iPalette, 3); |
| 172 uint8_t* ptr = pColorTable; |
| 173 for (int32_t i = 0; i < iPalette; i++) { |
| 174 FX_DWORD argb = pBitmap->GetPaletteArgb(i); |
| 175 ptr[0] = (uint8_t)(argb >> 16); |
| 176 ptr[1] = (uint8_t)(argb >> 8); |
| 177 ptr[2] = (uint8_t)argb; |
| 178 ptr += 3; |
| 179 } |
| 180 CPDF_Stream* pCTS = CPDF_Stream::Create(pColorTable, iPalette * 3, |
| 181 CPDF_Dictionary::Create()); |
| 182 m_pDocument->AddIndirectObject(pCTS); |
| 183 pCS->AddReference(m_pDocument, pCTS); |
| 184 pDict->SetAtReference(FX_BSTRC("ColorSpace"), m_pDocument, pCS); |
| 185 } else { |
| 186 pDict->SetAtName(FX_BSTRC("ColorSpace"), FX_BSTRC("DeviceGray")); |
| 187 } |
| 188 pDict->SetAtInteger(FX_BSTRC("BitsPerComponent"), 8); |
| 189 if ((iCompress & 0x03) == PDF_IMAGE_NO_COMPRESS) { |
| 190 dest_pitch = BitmapWidth; |
| 191 opType = 1; |
| 192 } else { |
| 193 opType = 0; |
| 194 } |
| 195 } else { |
| 196 pDict->SetAtName(FX_BSTRC("ColorSpace"), FX_BSTRC("DeviceRGB")); |
| 197 pDict->SetAtInteger(FX_BSTRC("BitsPerComponent"), 8); |
| 198 if ((iCompress & 0x03) == PDF_IMAGE_NO_COMPRESS) { |
| 199 dest_pitch = BitmapWidth * 3; |
| 200 opType = 2; |
| 201 } else { |
| 202 opType = 0; |
| 203 } |
| 204 } |
| 205 const CFX_DIBitmap* pMaskBitmap = NULL; |
| 206 FX_BOOL bDeleteMask = FALSE; |
| 207 if (pBitmap->HasAlpha()) { |
| 208 pMaskBitmap = pBitmap->GetAlphaMask(); |
| 209 bDeleteMask = TRUE; |
| 210 } |
| 211 if (!pMaskBitmap && pMask) { |
| 212 FXDIB_Format maskFormat = pMask->GetFormat(); |
| 213 if (maskFormat == FXDIB_1bppMask || maskFormat == FXDIB_8bppMask) { |
| 214 pMaskBitmap = pMask; |
| 215 } |
| 216 } |
| 217 if (pMaskBitmap) { |
| 218 int32_t maskWidth = pMaskBitmap->GetWidth(); |
| 219 int32_t maskHeight = pMaskBitmap->GetHeight(); |
| 220 uint8_t* mask_buf = NULL; |
| 221 FX_STRSIZE mask_size; |
| 222 CPDF_Dictionary* pMaskDict = new CPDF_Dictionary; |
| 223 pMaskDict->SetAtName(FX_BSTRC("Type"), FX_BSTRC("XObject")); |
| 224 pMaskDict->SetAtName(FX_BSTRC("Subtype"), FX_BSTRC("Image")); |
| 225 pMaskDict->SetAtInteger(FX_BSTRC("Width"), maskWidth); |
| 226 pMaskDict->SetAtInteger(FX_BSTRC("Height"), maskHeight); |
| 227 pMaskDict->SetAtName(FX_BSTRC("ColorSpace"), FX_BSTRC("DeviceGray")); |
| 228 pMaskDict->SetAtInteger(FX_BSTRC("BitsPerComponent"), 8); |
| 229 if (pMaskBitmap->GetBPP() == 8 && |
| 230 (iCompress & PDF_IMAGE_MASK_LOSSY_COMPRESS) != 0) { |
| 231 _DCTEncodeBitmap(pMaskDict, pMaskBitmap, pParam ? pParam->nQuality : 75, |
| 232 mask_buf, mask_size); |
| 233 } else if (pMaskBitmap->GetFormat() == FXDIB_1bppMask) { |
| 234 _JBIG2EncodeBitmap(pMaskDict, pMaskBitmap, m_pDocument, mask_buf, |
| 235 mask_size, TRUE); |
| 236 } else { |
| 237 mask_buf = FX_Alloc2D(uint8_t, maskHeight, maskWidth); |
| 238 mask_size = maskHeight * maskWidth; // Safe since checked alloc returned. |
| 239 for (int32_t a = 0; a < maskHeight; a++) { |
| 240 FXSYS_memcpy(mask_buf + a * maskWidth, pMaskBitmap->GetScanline(a), |
| 241 maskWidth); |
| 242 } |
| 243 } |
| 244 pMaskDict->SetAtInteger(FX_BSTRC("Length"), mask_size); |
| 245 if (bUseMatte) { |
| 246 int a, r, g, b; |
| 247 ArgbDecode(*(pParam->pMatteColor), a, r, g, b); |
| 248 CPDF_Array* pMatte = new CPDF_Array; |
| 249 pMatte->AddInteger(r); |
| 250 pMatte->AddInteger(g); |
| 251 pMatte->AddInteger(b); |
| 252 pMaskDict->SetAt(FX_BSTRC("Matte"), pMatte); |
| 253 } |
| 254 CPDF_Stream* pMaskStream = new CPDF_Stream(mask_buf, mask_size, pMaskDict); |
| 255 m_pDocument->AddIndirectObject(pMaskStream); |
| 256 pDict->SetAtReference(FX_BSTRC("SMask"), m_pDocument, pMaskStream); |
| 257 if (bDeleteMask) { |
| 258 delete pMaskBitmap; |
| 259 } |
| 260 } |
| 261 FX_BOOL bStream = pFileWrite != NULL && pFileRead != NULL; |
| 262 if (opType == 0) { |
| 263 if (iCompress & PDF_IMAGE_LOSSLESS_COMPRESS) { |
| 264 if (pBitmap->GetBPP() == 1) { |
| 265 _JBIG2EncodeBitmap(pDict, pBitmap, m_pDocument, dest_buf, dest_size, |
| 266 TRUE); |
| 267 } |
| 268 } else { |
| 269 if (pBitmap->GetBPP() == 1) { |
| 270 _JBIG2EncodeBitmap(pDict, pBitmap, m_pDocument, dest_buf, dest_size, |
| 271 FALSE); |
| 272 } else if (pBitmap->GetBPP() >= 8 && pBitmap->GetPalette() != NULL) { |
| 273 CFX_DIBitmap* pNewBitmap = new CFX_DIBitmap(); |
| 274 pNewBitmap->Copy(pBitmap); |
| 275 pNewBitmap->ConvertFormat(FXDIB_Rgb); |
| 276 SetImage(pNewBitmap, iCompress, pFileWrite, pFileRead); |
| 277 if (pDict) { |
| 278 pDict->Release(); |
| 279 pDict = NULL; |
40 } | 280 } |
41 pDict->SetAt(FX_BSTRC("Decode"), pDecode); | 281 if (dest_buf) { |
42 } | 282 FX_Free(dest_buf); |
43 pDict->SetAtName("ColorSpace", csname); | 283 dest_buf = NULL; |
44 pDict->SetAtInteger("BitsPerComponent", bits); | 284 } |
45 pDict->SetAtName("Filter", "DCTDecode"); | 285 dest_size = 0; |
46 if (!color_trans) { | 286 delete pNewBitmap; |
47 CPDF_Dictionary* pParms = new CPDF_Dictionary; | |
48 pDict->SetAt("DecodeParms", pParms); | |
49 pParms->SetAtInteger("ColorTransform", 0); | |
50 } | |
51 m_bIsMask = FALSE; | |
52 m_Width = width; | |
53 m_Height = height; | |
54 if (m_pStream == NULL) { | |
55 m_pStream = new CPDF_Stream(NULL, 0, NULL); | |
56 } | |
57 return pDict; | |
58 } | |
59 void CPDF_Image::SetJpegImage(uint8_t* pData, FX_DWORD size) | |
60 { | |
61 CPDF_Dictionary *pDict = InitJPEG(pData, size); | |
62 if (!pDict) { | |
63 return; | 287 return; |
64 } | 288 } else { |
65 m_pStream->InitStream(pData, size, pDict); | 289 if (bUseMatte) { |
66 } | 290 CFX_DIBitmap* pNewBitmap = new CFX_DIBitmap(); |
67 void CPDF_Image::SetJpegImage(IFX_FileRead *pFile) | 291 pNewBitmap->Create(BitmapWidth, BitmapHeight, FXDIB_Argb); |
68 { | 292 uint8_t* dst_buf = pNewBitmap->GetBuffer(); |
69 FX_DWORD size = (FX_DWORD)pFile->GetSize(); | 293 int32_t src_offset = 0; |
70 if (!size) { | 294 for (int32_t row = 0; row < BitmapHeight; row++) { |
71 return; | 295 src_offset = row * src_pitch; |
72 } | 296 for (int32_t column = 0; column < BitmapWidth; column++) { |
73 FX_DWORD dwEstimateSize = size; | 297 FX_FLOAT alpha = src_buf[src_offset + 3] / 255.0f; |
74 if (dwEstimateSize > 8192) { | 298 dst_buf[src_offset] = (uint8_t)(src_buf[src_offset] * alpha); |
75 dwEstimateSize = 8192; | 299 dst_buf[src_offset + 1] = |
76 } | 300 (uint8_t)(src_buf[src_offset + 1] * alpha); |
77 uint8_t* pData = FX_Alloc(uint8_t, dwEstimateSize); | 301 dst_buf[src_offset + 2] = |
78 pFile->ReadBlock(pData, 0, dwEstimateSize); | 302 (uint8_t)(src_buf[src_offset + 2] * alpha); |
79 CPDF_Dictionary *pDict = InitJPEG(pData, dwEstimateSize); | 303 dst_buf[src_offset + 3] = (uint8_t)(src_buf[src_offset + 3]); |
80 FX_Free(pData); | 304 src_offset += 4; |
81 if (!pDict && size > dwEstimateSize) { | 305 } |
82 pData = FX_Alloc(uint8_t, size); | 306 } |
83 pFile->ReadBlock(pData, 0, size); | 307 _DCTEncodeBitmap(pDict, pNewBitmap, pParam ? pParam->nQuality : 75, |
84 pDict = InitJPEG(pData, size); | 308 dest_buf, dest_size); |
85 FX_Free(pData); | 309 delete pNewBitmap; |
86 } | 310 } else { |
87 if (!pDict) { | 311 _DCTEncodeBitmap(pDict, pBitmap, pParam ? pParam->nQuality : 75, |
88 return; | 312 dest_buf, dest_size); |
89 } | |
90 m_pStream->InitStream(pFile, pDict); | |
91 } | |
92 void _DCTEncodeBitmap(CPDF_Dictionary *pBitmapDict, const CFX_DIBitmap* pBitmap,
int quality, uint8_t* &buf, FX_STRSIZE &size) | |
93 { | |
94 } | |
95 void _JBIG2EncodeBitmap(CPDF_Dictionary *pBitmapDict, const CFX_DIBitmap *pBitma
p, CPDF_Document *pDoc, uint8_t* &buf, FX_STRSIZE &size, FX_BOOL bLossLess) | |
96 { | |
97 } | |
98 void CPDF_Image::SetImage(const CFX_DIBitmap* pBitmap, int32_t iCompress, IFX_Fi
leWrite *pFileWrite, IFX_FileRead *pFileRead, const CFX_DIBitmap* pMask, const C
PDF_ImageSetParam* pParam) | |
99 { | |
100 int32_t BitmapWidth = pBitmap->GetWidth(); | |
101 int32_t BitmapHeight = pBitmap->GetHeight(); | |
102 if (BitmapWidth < 1 || BitmapHeight < 1) { | |
103 return; | |
104 } | |
105 uint8_t* src_buf = pBitmap->GetBuffer(); | |
106 int32_t src_pitch = pBitmap->GetPitch(); | |
107 int32_t bpp = pBitmap->GetBPP(); | |
108 FX_BOOL bUseMatte = pParam && pParam->pMatteColor && (pBitmap->GetFormat() =
= FXDIB_Argb); | |
109 CPDF_Dictionary* pDict = new CPDF_Dictionary; | |
110 pDict->SetAtName(FX_BSTRC("Type"), FX_BSTRC("XObject")); | |
111 pDict->SetAtName(FX_BSTRC("Subtype"), FX_BSTRC("Image")); | |
112 pDict->SetAtInteger(FX_BSTRC("Width"), BitmapWidth); | |
113 pDict->SetAtInteger(FX_BSTRC("Height"), BitmapHeight); | |
114 uint8_t* dest_buf = NULL; | |
115 FX_STRSIZE dest_pitch = 0, dest_size = 0, opType = -1; | |
116 if (bpp == 1) { | |
117 int32_t reset_a = 0, reset_r = 0, reset_g = 0, reset_b = 0; | |
118 int32_t set_a = 0, set_r = 0, set_g = 0, set_b = 0; | |
119 if (!pBitmap->IsAlphaMask()) { | |
120 ArgbDecode(pBitmap->GetPaletteArgb(0), reset_a, reset_r, reset_g, re
set_b); | |
121 ArgbDecode(pBitmap->GetPaletteArgb(1), set_a, set_r, set_g, set_b); | |
122 } | 313 } |
123 if (set_a == 0 || reset_a == 0) { | 314 } |
124 pDict->SetAt(FX_BSTRC("ImageMask"), new CPDF_Boolean(TRUE)); | 315 } |
125 if (reset_a == 0) { | 316 if (bStream) { |
126 CPDF_Array* pArray = new CPDF_Array; | 317 pFileWrite->WriteBlock(dest_buf, dest_size); |
127 pArray->AddInteger(1); | 318 FX_Free(dest_buf); |
128 pArray->AddInteger(0); | 319 dest_buf = NULL; |
129 pDict->SetAt(FX_BSTRC("Decode"), pArray); | 320 } |
130 } | 321 } else if (opType == 1) { |
131 } else { | |
132 CPDF_Array* pCS = new CPDF_Array; | |
133 pCS->AddName(FX_BSTRC("Indexed")); | |
134 pCS->AddName(FX_BSTRC("DeviceRGB")); | |
135 pCS->AddInteger(1); | |
136 CFX_ByteString ct; | |
137 FX_CHAR* pBuf = ct.GetBuffer(6); | |
138 pBuf[0] = (FX_CHAR)reset_r; | |
139 pBuf[1] = (FX_CHAR)reset_g; | |
140 pBuf[2] = (FX_CHAR)reset_b; | |
141 pBuf[3] = (FX_CHAR)set_r; | |
142 pBuf[4] = (FX_CHAR)set_g; | |
143 pBuf[5] = (FX_CHAR)set_b; | |
144 ct.ReleaseBuffer(6); | |
145 pCS->Add(CPDF_String::Create(ct, TRUE)); | |
146 pDict->SetAt(FX_BSTRC("ColorSpace"), pCS); | |
147 } | |
148 pDict->SetAtInteger(FX_BSTRC("BitsPerComponent"), 1); | |
149 dest_pitch = (BitmapWidth + 7) / 8; | |
150 if ((iCompress & 0x03) == PDF_IMAGE_NO_COMPRESS) { | |
151 opType = 1; | |
152 } else { | |
153 opType = 0; | |
154 } | |
155 } else if (bpp == 8) { | |
156 int32_t iPalette = pBitmap->GetPaletteSize(); | |
157 if (iPalette > 0) { | |
158 CPDF_Array* pCS = new CPDF_Array; | |
159 m_pDocument->AddIndirectObject(pCS); | |
160 pCS->AddName(FX_BSTRC("Indexed")); | |
161 pCS->AddName(FX_BSTRC("DeviceRGB")); | |
162 pCS->AddInteger(iPalette - 1); | |
163 uint8_t* pColorTable = FX_Alloc2D(uint8_t, iPalette, 3); | |
164 uint8_t* ptr = pColorTable; | |
165 for (int32_t i = 0; i < iPalette; i ++) { | |
166 FX_DWORD argb = pBitmap->GetPaletteArgb(i); | |
167 ptr[0] = (uint8_t)(argb >> 16); | |
168 ptr[1] = (uint8_t)(argb >> 8); | |
169 ptr[2] = (uint8_t)argb; | |
170 ptr += 3; | |
171 } | |
172 CPDF_Stream *pCTS = CPDF_Stream::Create(pColorTable, iPalette * 3, C
PDF_Dictionary::Create()); | |
173 m_pDocument->AddIndirectObject(pCTS); | |
174 pCS->AddReference(m_pDocument, pCTS); | |
175 pDict->SetAtReference(FX_BSTRC("ColorSpace"), m_pDocument, pCS); | |
176 } else { | |
177 pDict->SetAtName(FX_BSTRC("ColorSpace"), FX_BSTRC("DeviceGray")); | |
178 } | |
179 pDict->SetAtInteger(FX_BSTRC("BitsPerComponent"), 8); | |
180 if ((iCompress & 0x03) == PDF_IMAGE_NO_COMPRESS) { | |
181 dest_pitch = BitmapWidth; | |
182 opType = 1; | |
183 } else { | |
184 opType = 0; | |
185 } | |
186 } else { | |
187 pDict->SetAtName(FX_BSTRC("ColorSpace"), FX_BSTRC("DeviceRGB")); | |
188 pDict->SetAtInteger(FX_BSTRC("BitsPerComponent"), 8); | |
189 if ((iCompress & 0x03) == PDF_IMAGE_NO_COMPRESS) { | |
190 dest_pitch = BitmapWidth * 3; | |
191 opType = 2; | |
192 } else { | |
193 opType = 0; | |
194 } | |
195 } | |
196 const CFX_DIBitmap* pMaskBitmap = NULL; | |
197 FX_BOOL bDeleteMask = FALSE; | |
198 if (pBitmap->HasAlpha()) { | |
199 pMaskBitmap = pBitmap->GetAlphaMask(); | |
200 bDeleteMask = TRUE; | |
201 } | |
202 if (!pMaskBitmap && pMask) { | |
203 FXDIB_Format maskFormat = pMask->GetFormat(); | |
204 if (maskFormat == FXDIB_1bppMask || maskFormat == FXDIB_8bppMask) { | |
205 pMaskBitmap = pMask; | |
206 } | |
207 } | |
208 if (pMaskBitmap) { | |
209 int32_t maskWidth = pMaskBitmap->GetWidth(); | |
210 int32_t maskHeight = pMaskBitmap->GetHeight(); | |
211 uint8_t* mask_buf = NULL; | |
212 FX_STRSIZE mask_size; | |
213 CPDF_Dictionary* pMaskDict = new CPDF_Dictionary; | |
214 pMaskDict->SetAtName(FX_BSTRC("Type"), FX_BSTRC("XObject")); | |
215 pMaskDict->SetAtName(FX_BSTRC("Subtype"), FX_BSTRC("Image")); | |
216 pMaskDict->SetAtInteger(FX_BSTRC("Width"), maskWidth); | |
217 pMaskDict->SetAtInteger(FX_BSTRC("Height"), maskHeight); | |
218 pMaskDict->SetAtName(FX_BSTRC("ColorSpace"), FX_BSTRC("DeviceGray")); | |
219 pMaskDict->SetAtInteger(FX_BSTRC("BitsPerComponent"), 8); | |
220 if (pMaskBitmap->GetBPP() == 8 && (iCompress & PDF_IMAGE_MASK_LOSSY_COMP
RESS) != 0) { | |
221 _DCTEncodeBitmap(pMaskDict, pMaskBitmap, pParam ? pParam->nQuality :
75, mask_buf, mask_size); | |
222 } else if (pMaskBitmap->GetFormat() == FXDIB_1bppMask) { | |
223 _JBIG2EncodeBitmap(pMaskDict, pMaskBitmap, m_pDocument, mask_buf, ma
sk_size, TRUE); | |
224 } else { | |
225 mask_buf = FX_Alloc2D(uint8_t, maskHeight, maskWidth); | |
226 mask_size = maskHeight * maskWidth; // Safe since checked alloc ret
urned. | |
227 for (int32_t a = 0; a < maskHeight; a ++) { | |
228 FXSYS_memcpy(mask_buf + a * maskWidth, pMaskBitmap->GetScanline(
a), maskWidth); | |
229 } | |
230 } | |
231 pMaskDict->SetAtInteger(FX_BSTRC("Length"), mask_size); | |
232 if (bUseMatte) { | |
233 int a, r, g, b; | |
234 ArgbDecode(*(pParam->pMatteColor), a, r, g, b); | |
235 CPDF_Array* pMatte = new CPDF_Array; | |
236 pMatte->AddInteger(r); | |
237 pMatte->AddInteger(g); | |
238 pMatte->AddInteger(b); | |
239 pMaskDict->SetAt(FX_BSTRC("Matte"), pMatte); | |
240 } | |
241 CPDF_Stream* pMaskStream = new CPDF_Stream(mask_buf, mask_size, pMaskDic
t); | |
242 m_pDocument->AddIndirectObject(pMaskStream); | |
243 pDict->SetAtReference(FX_BSTRC("SMask"), m_pDocument, pMaskStream); | |
244 if (bDeleteMask) { | |
245 delete pMaskBitmap; | |
246 } | |
247 } | |
248 FX_BOOL bStream = pFileWrite != NULL && pFileRead != NULL; | |
249 if (opType == 0) { | |
250 if (iCompress & PDF_IMAGE_LOSSLESS_COMPRESS) { | |
251 if (pBitmap->GetBPP() == 1) { | |
252 _JBIG2EncodeBitmap(pDict, pBitmap, m_pDocument, dest_buf, dest_s
ize, TRUE); | |
253 } | |
254 } else { | |
255 if (pBitmap->GetBPP() == 1) { | |
256 _JBIG2EncodeBitmap(pDict, pBitmap, m_pDocument, dest_buf, dest_s
ize, FALSE); | |
257 } else if (pBitmap->GetBPP() >= 8 && pBitmap->GetPalette() != NULL)
{ | |
258 CFX_DIBitmap *pNewBitmap = new CFX_DIBitmap(); | |
259 pNewBitmap->Copy(pBitmap); | |
260 pNewBitmap->ConvertFormat(FXDIB_Rgb); | |
261 SetImage(pNewBitmap, iCompress, pFileWrite, pFileRead); | |
262 if (pDict) { | |
263 pDict->Release(); | |
264 pDict = NULL; | |
265 } | |
266 if (dest_buf) { | |
267 FX_Free(dest_buf); | |
268 dest_buf = NULL; | |
269 } | |
270 dest_size = 0; | |
271 delete pNewBitmap; | |
272 return; | |
273 } else { | |
274 if (bUseMatte) { | |
275 CFX_DIBitmap *pNewBitmap = new CFX_DIBitmap(); | |
276 pNewBitmap->Create(BitmapWidth, BitmapHeight, FXDIB_Argb); | |
277 uint8_t* dst_buf = pNewBitmap->GetBuffer(); | |
278 int32_t src_offset = 0; | |
279 for (int32_t row = 0; row < BitmapHeight; row ++) { | |
280 src_offset = row * src_pitch; | |
281 for (int32_t column = 0; column < BitmapWidth; column ++
) { | |
282 FX_FLOAT alpha = src_buf[src_offset + 3] / 255.0f; | |
283 dst_buf[src_offset] = (uint8_t)(src_buf[src_offset]
* alpha); | |
284 dst_buf[src_offset + 1] = (uint8_t)(src_buf[src_offs
et + 1] * alpha); | |
285 dst_buf[src_offset + 2] = (uint8_t)(src_buf[src_offs
et + 2] * alpha); | |
286 dst_buf[src_offset + 3] = (uint8_t)(src_buf[src_offs
et + 3]); | |
287 src_offset += 4; | |
288 } | |
289 } | |
290 _DCTEncodeBitmap(pDict, pNewBitmap, pParam ? pParam->nQualit
y : 75, dest_buf, dest_size); | |
291 delete pNewBitmap; | |
292 } else { | |
293 _DCTEncodeBitmap(pDict, pBitmap, pParam ? pParam->nQuality :
75, dest_buf, dest_size); | |
294 } | |
295 } | |
296 } | |
297 if (bStream) { | |
298 pFileWrite->WriteBlock(dest_buf, dest_size); | |
299 FX_Free(dest_buf); | |
300 dest_buf = NULL; | |
301 } | |
302 } else if (opType == 1) { | |
303 if (!bStream) { | |
304 dest_buf = FX_Alloc2D(uint8_t, dest_pitch, BitmapHeight); | |
305 dest_size = dest_pitch * BitmapHeight; // Safe since checked alloc
returned. | |
306 } | |
307 uint8_t* pDest = dest_buf; | |
308 for (int32_t i = 0; i < BitmapHeight; i ++) { | |
309 if (!bStream) { | |
310 FXSYS_memcpy(pDest, src_buf, dest_pitch); | |
311 pDest += dest_pitch; | |
312 } else { | |
313 pFileWrite->WriteBlock(src_buf, dest_pitch); | |
314 } | |
315 src_buf += src_pitch; | |
316 } | |
317 } else if (opType == 2) { | |
318 if (!bStream) { | |
319 dest_buf = FX_Alloc2D(uint8_t, dest_pitch, BitmapHeight); | |
320 dest_size = dest_pitch * BitmapHeight; // Safe since checked alloc
returned. | |
321 } else { | |
322 dest_buf = FX_Alloc(uint8_t, dest_pitch); | |
323 } | |
324 uint8_t* pDest = dest_buf; | |
325 int32_t src_offset = 0; | |
326 int32_t dest_offset = 0; | |
327 for (int32_t row = 0; row < BitmapHeight; row ++) { | |
328 src_offset = row * src_pitch; | |
329 for (int32_t column = 0; column < BitmapWidth; column ++) { | |
330 FX_FLOAT alpha = bUseMatte ? src_buf[src_offset + 3] / 255.0f :
1; | |
331 pDest[dest_offset] = (uint8_t)(src_buf[src_offset + 2] * alpha); | |
332 pDest[dest_offset + 1] = (uint8_t)(src_buf[src_offset + 1] * alp
ha); | |
333 pDest[dest_offset + 2] = (uint8_t)(src_buf[src_offset] * alpha); | |
334 dest_offset += 3; | |
335 src_offset += bpp == 24 ? 3 : 4; | |
336 } | |
337 if (bStream) { | |
338 pFileWrite->WriteBlock(pDest, dest_pitch); | |
339 pDest = dest_buf; | |
340 } else { | |
341 pDest += dest_pitch; | |
342 } | |
343 dest_offset = 0; | |
344 } | |
345 if (bStream) { | |
346 FX_Free(dest_buf); | |
347 dest_buf = NULL; | |
348 } | |
349 } | |
350 if (m_pStream == NULL) { | |
351 m_pStream = new CPDF_Stream(NULL, 0, NULL); | |
352 } | |
353 if (!bStream) { | 322 if (!bStream) { |
354 m_pStream->InitStream(dest_buf, dest_size, pDict); | 323 dest_buf = FX_Alloc2D(uint8_t, dest_pitch, BitmapHeight); |
355 } else { | 324 dest_size = |
356 pFileWrite->Flush(); | 325 dest_pitch * BitmapHeight; // Safe since checked alloc returned. |
357 m_pStream->InitStream(pFileRead, pDict); | 326 } |
358 } | 327 uint8_t* pDest = dest_buf; |
359 m_bIsMask = pBitmap->IsAlphaMask(); | 328 for (int32_t i = 0; i < BitmapHeight; i++) { |
360 m_Width = BitmapWidth; | 329 if (!bStream) { |
361 m_Height = BitmapHeight; | 330 FXSYS_memcpy(pDest, src_buf, dest_pitch); |
362 if (dest_buf) { | 331 pDest += dest_pitch; |
363 FX_Free(dest_buf); | 332 } else { |
364 } | 333 pFileWrite->WriteBlock(src_buf, dest_pitch); |
365 } | 334 } |
366 void CPDF_Image::ResetCache(CPDF_Page* pPage, const CFX_DIBitmap* pBitmap) | 335 src_buf += src_pitch; |
367 { | 336 } |
368 pPage->GetRenderCache()->ResetBitmap(m_pStream, pBitmap); | 337 } else if (opType == 2) { |
369 } | 338 if (!bStream) { |
| 339 dest_buf = FX_Alloc2D(uint8_t, dest_pitch, BitmapHeight); |
| 340 dest_size = |
| 341 dest_pitch * BitmapHeight; // Safe since checked alloc returned. |
| 342 } else { |
| 343 dest_buf = FX_Alloc(uint8_t, dest_pitch); |
| 344 } |
| 345 uint8_t* pDest = dest_buf; |
| 346 int32_t src_offset = 0; |
| 347 int32_t dest_offset = 0; |
| 348 for (int32_t row = 0; row < BitmapHeight; row++) { |
| 349 src_offset = row * src_pitch; |
| 350 for (int32_t column = 0; column < BitmapWidth; column++) { |
| 351 FX_FLOAT alpha = bUseMatte ? src_buf[src_offset + 3] / 255.0f : 1; |
| 352 pDest[dest_offset] = (uint8_t)(src_buf[src_offset + 2] * alpha); |
| 353 pDest[dest_offset + 1] = (uint8_t)(src_buf[src_offset + 1] * alpha); |
| 354 pDest[dest_offset + 2] = (uint8_t)(src_buf[src_offset] * alpha); |
| 355 dest_offset += 3; |
| 356 src_offset += bpp == 24 ? 3 : 4; |
| 357 } |
| 358 if (bStream) { |
| 359 pFileWrite->WriteBlock(pDest, dest_pitch); |
| 360 pDest = dest_buf; |
| 361 } else { |
| 362 pDest += dest_pitch; |
| 363 } |
| 364 dest_offset = 0; |
| 365 } |
| 366 if (bStream) { |
| 367 FX_Free(dest_buf); |
| 368 dest_buf = NULL; |
| 369 } |
| 370 } |
| 371 if (m_pStream == NULL) { |
| 372 m_pStream = new CPDF_Stream(NULL, 0, NULL); |
| 373 } |
| 374 if (!bStream) { |
| 375 m_pStream->InitStream(dest_buf, dest_size, pDict); |
| 376 } else { |
| 377 pFileWrite->Flush(); |
| 378 m_pStream->InitStream(pFileRead, pDict); |
| 379 } |
| 380 m_bIsMask = pBitmap->IsAlphaMask(); |
| 381 m_Width = BitmapWidth; |
| 382 m_Height = BitmapHeight; |
| 383 if (dest_buf) { |
| 384 FX_Free(dest_buf); |
| 385 } |
| 386 } |
| 387 void CPDF_Image::ResetCache(CPDF_Page* pPage, const CFX_DIBitmap* pBitmap) { |
| 388 pPage->GetRenderCache()->ResetBitmap(m_pStream, pBitmap); |
| 389 } |
OLD | NEW |