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