| 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 |