OLD | NEW |
| (Empty) |
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. | |
4 | |
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | |
6 | |
7 #include "core/include/fxcodec/fx_codec.h" | |
8 #include "core/include/fxge/fx_dib.h" | |
9 #include "core/src/fxcodec/codec/codec_int.h" | |
10 | |
11 extern "C" { | |
12 #include "third_party/libtiff/tiffiop.h" | |
13 } | |
14 | |
15 void* IccLib_CreateTransform_sRGB(const unsigned char* pProfileData, | |
16 unsigned int dwProfileSize, | |
17 int nComponents, | |
18 int intent, | |
19 FX_DWORD dwSrcFormat = Icc_FORMAT_DEFAULT); | |
20 void IccLib_TranslateImage(void* pTransform, | |
21 unsigned char* pDest, | |
22 const unsigned char* pSrc, | |
23 int pixels); | |
24 void IccLib_DestroyTransform(void* pTransform); | |
25 class CCodec_TiffContext { | |
26 public: | |
27 CCodec_TiffContext(); | |
28 ~CCodec_TiffContext(); | |
29 | |
30 FX_BOOL InitDecoder(IFX_FileRead* file_ptr); | |
31 void GetFrames(int32_t& frames); | |
32 FX_BOOL LoadFrameInfo(int32_t frame, | |
33 FX_DWORD& width, | |
34 FX_DWORD& height, | |
35 FX_DWORD& comps, | |
36 FX_DWORD& bpc, | |
37 CFX_DIBAttribute* pAttribute); | |
38 FX_BOOL Decode(CFX_DIBitmap* pDIBitmap); | |
39 | |
40 union { | |
41 IFX_FileRead* in; | |
42 IFX_FileStream* out; | |
43 } io; | |
44 | |
45 FX_DWORD offset; | |
46 | |
47 TIFF* tif_ctx; | |
48 void* icc_ctx; | |
49 int32_t frame_num; | |
50 int32_t frame_cur; | |
51 FX_BOOL isDecoder; | |
52 | |
53 private: | |
54 FX_BOOL isSupport(CFX_DIBitmap* pDIBitmap); | |
55 void SetPalette(CFX_DIBitmap* pDIBitmap, uint16_t bps); | |
56 FX_BOOL Decode1bppRGB(CFX_DIBitmap* pDIBitmap, | |
57 int32_t height, | |
58 int32_t width, | |
59 uint16_t bps, | |
60 uint16_t spp); | |
61 FX_BOOL Decode8bppRGB(CFX_DIBitmap* pDIBitmap, | |
62 int32_t height, | |
63 int32_t width, | |
64 uint16_t bps, | |
65 uint16_t spp); | |
66 FX_BOOL Decode24bppRGB(CFX_DIBitmap* pDIBitmap, | |
67 int32_t height, | |
68 int32_t width, | |
69 uint16_t bps, | |
70 uint16_t spp); | |
71 }; | |
72 CCodec_TiffContext::CCodec_TiffContext() { | |
73 offset = 0; | |
74 frame_num = 0; | |
75 frame_cur = 0; | |
76 io.in = NULL; | |
77 tif_ctx = NULL; | |
78 icc_ctx = NULL; | |
79 isDecoder = TRUE; | |
80 } | |
81 CCodec_TiffContext::~CCodec_TiffContext() { | |
82 if (icc_ctx) { | |
83 IccLib_DestroyTransform(icc_ctx); | |
84 icc_ctx = NULL; | |
85 } | |
86 if (tif_ctx) { | |
87 TIFFClose(tif_ctx); | |
88 } | |
89 } | |
90 static tsize_t _tiff_read(thandle_t context, tdata_t buf, tsize_t length) { | |
91 CCodec_TiffContext* pTiffContext = (CCodec_TiffContext*)context; | |
92 FX_BOOL ret = FALSE; | |
93 if (pTiffContext->isDecoder) { | |
94 ret = pTiffContext->io.in->ReadBlock(buf, pTiffContext->offset, length); | |
95 } else { | |
96 ret = pTiffContext->io.out->ReadBlock(buf, pTiffContext->offset, length); | |
97 } | |
98 if (!ret) { | |
99 return 0; | |
100 } | |
101 pTiffContext->offset += (FX_DWORD)length; | |
102 return length; | |
103 } | |
104 static tsize_t _tiff_write(thandle_t context, tdata_t buf, tsize_t length) { | |
105 CCodec_TiffContext* pTiffContext = (CCodec_TiffContext*)context; | |
106 ASSERT(!pTiffContext->isDecoder); | |
107 if (!pTiffContext->io.out->WriteBlock(buf, pTiffContext->offset, length)) { | |
108 return 0; | |
109 } | |
110 pTiffContext->offset += (FX_DWORD)length; | |
111 return length; | |
112 } | |
113 static toff_t _tiff_seek(thandle_t context, toff_t offset, int whence) { | |
114 CCodec_TiffContext* pTiffContext = (CCodec_TiffContext*)context; | |
115 switch (whence) { | |
116 case 0: | |
117 pTiffContext->offset = (FX_DWORD)offset; | |
118 break; | |
119 case 1: | |
120 pTiffContext->offset += (FX_DWORD)offset; | |
121 break; | |
122 case 2: | |
123 if (pTiffContext->isDecoder) { | |
124 if (pTiffContext->io.in->GetSize() < (FX_FILESIZE)offset) { | |
125 return -1; | |
126 } | |
127 pTiffContext->offset = | |
128 (FX_DWORD)(pTiffContext->io.in->GetSize() - offset); | |
129 } else { | |
130 if (pTiffContext->io.out->GetSize() < (FX_FILESIZE)offset) { | |
131 return -1; | |
132 } | |
133 pTiffContext->offset = | |
134 (FX_DWORD)(pTiffContext->io.out->GetSize() - offset); | |
135 } | |
136 break; | |
137 default: | |
138 return -1; | |
139 } | |
140 ASSERT(pTiffContext->isDecoder ? (pTiffContext->offset <= | |
141 (FX_DWORD)pTiffContext->io.in->GetSize()) | |
142 : TRUE); | |
143 return pTiffContext->offset; | |
144 } | |
145 static int _tiff_close(thandle_t context) { | |
146 return 0; | |
147 } | |
148 static toff_t _tiff_get_size(thandle_t context) { | |
149 CCodec_TiffContext* pTiffContext = (CCodec_TiffContext*)context; | |
150 return pTiffContext->isDecoder ? (toff_t)pTiffContext->io.in->GetSize() | |
151 : (toff_t)pTiffContext->io.out->GetSize(); | |
152 } | |
153 static int _tiff_map(thandle_t context, tdata_t*, toff_t*) { | |
154 return 0; | |
155 } | |
156 static void _tiff_unmap(thandle_t context, tdata_t, toff_t) {} | |
157 TIFF* _tiff_open(void* context, const char* mode) { | |
158 TIFF* tif = TIFFClientOpen("Tiff Image", mode, (thandle_t)context, _tiff_read, | |
159 _tiff_write, _tiff_seek, _tiff_close, | |
160 _tiff_get_size, _tiff_map, _tiff_unmap); | |
161 if (tif) { | |
162 tif->tif_fd = (int)(intptr_t)context; | |
163 } | |
164 return tif; | |
165 } | |
166 void* _TIFFmalloc(tmsize_t size) { | |
167 return FXMEM_DefaultAlloc(size, 0); | |
168 } | |
169 void _TIFFfree(void* ptr) { | |
170 FXMEM_DefaultFree(ptr, 0); | |
171 } | |
172 void* _TIFFrealloc(void* ptr, tmsize_t size) { | |
173 return FXMEM_DefaultRealloc(ptr, size, 0); | |
174 } | |
175 void _TIFFmemset(void* ptr, int val, tmsize_t size) { | |
176 FXSYS_memset(ptr, val, (size_t)size); | |
177 } | |
178 void _TIFFmemcpy(void* des, const void* src, tmsize_t size) { | |
179 FXSYS_memcpy(des, src, (size_t)size); | |
180 } | |
181 int _TIFFmemcmp(const void* ptr1, const void* ptr2, tmsize_t size) { | |
182 return FXSYS_memcmp(ptr1, ptr2, (size_t)size); | |
183 } | |
184 | |
185 TIFFErrorHandler _TIFFwarningHandler = nullptr; | |
186 TIFFErrorHandler _TIFFerrorHandler = nullptr; | |
187 | |
188 int TIFFCmyk2Rgb(thandle_t context, | |
189 uint8 c, | |
190 uint8 m, | |
191 uint8 y, | |
192 uint8 k, | |
193 uint8* r, | |
194 uint8* g, | |
195 uint8* b) { | |
196 if (context == NULL) { | |
197 return 0; | |
198 } | |
199 CCodec_TiffContext* p = (CCodec_TiffContext*)context; | |
200 if (p->icc_ctx) { | |
201 unsigned char cmyk[4], bgr[3]; | |
202 cmyk[0] = c, cmyk[1] = m, cmyk[2] = y, cmyk[3] = k; | |
203 IccLib_TranslateImage(p->icc_ctx, bgr, cmyk, 1); | |
204 *r = bgr[2], *g = bgr[1], *b = bgr[0]; | |
205 } else { | |
206 AdobeCMYK_to_sRGB1(c, m, y, k, *r, *g, *b); | |
207 } | |
208 return 1; | |
209 } | |
210 FX_BOOL CCodec_TiffContext::InitDecoder(IFX_FileRead* file_ptr) { | |
211 io.in = file_ptr; | |
212 tif_ctx = _tiff_open(this, "r"); | |
213 if (tif_ctx == NULL) { | |
214 return FALSE; | |
215 } | |
216 return TRUE; | |
217 } | |
218 void CCodec_TiffContext::GetFrames(int32_t& frames) { | |
219 frames = frame_num = TIFFNumberOfDirectories(tif_ctx); | |
220 } | |
221 #define TIFF_EXIF_GETINFO(key, T, tag) \ | |
222 { \ | |
223 T val = (T)0; \ | |
224 TIFFGetField(tif_ctx, tag, &val); \ | |
225 if (val) { \ | |
226 (key) = FX_Alloc(uint8_t, sizeof(T)); \ | |
227 if ((key)) { \ | |
228 T* ptr = (T*)(key); \ | |
229 *ptr = val; \ | |
230 pExif->m_TagVal.SetAt(tag, (key)); \ | |
231 } \ | |
232 } \ | |
233 } \ | |
234 (key) = NULL; | |
235 #define TIFF_EXIF_GETSTRINGINFO(key, tag) \ | |
236 { \ | |
237 FX_DWORD size = 0; \ | |
238 uint8_t* buf = NULL; \ | |
239 TIFFGetField(tif_ctx, tag, &size, &buf); \ | |
240 if (size && buf) { \ | |
241 (key) = FX_Alloc(uint8_t, size); \ | |
242 if ((key)) { \ | |
243 FXSYS_memcpy((key), buf, size); \ | |
244 pExif->m_TagVal.SetAt(tag, (key)); \ | |
245 } \ | |
246 } \ | |
247 } \ | |
248 (key) = NULL; | |
249 | |
250 namespace { | |
251 | |
252 template <class T> | |
253 FX_BOOL Tiff_Exif_GetInfo(TIFF* tif_ctx, ttag_t tag, CFX_DIBAttribute* pAttr) { | |
254 T val = 0; | |
255 TIFFGetField(tif_ctx, tag, &val); | |
256 if (!val) | |
257 return FALSE; | |
258 T* ptr = FX_Alloc(T, 1); | |
259 *ptr = val; | |
260 pAttr->m_Exif[tag] = (void*)ptr; | |
261 return TRUE; | |
262 } | |
263 void Tiff_Exif_GetStringInfo(TIFF* tif_ctx, | |
264 ttag_t tag, | |
265 CFX_DIBAttribute* pAttr) { | |
266 FX_CHAR* buf = nullptr; | |
267 TIFFGetField(tif_ctx, tag, &buf); | |
268 if (!buf) | |
269 return; | |
270 FX_STRSIZE size = FXSYS_strlen(buf); | |
271 uint8_t* ptr = FX_Alloc(uint8_t, size + 1); | |
272 FXSYS_memcpy(ptr, buf, size); | |
273 ptr[size] = 0; | |
274 pAttr->m_Exif[tag] = ptr; | |
275 } | |
276 | |
277 } // namespace | |
278 | |
279 FX_BOOL CCodec_TiffContext::LoadFrameInfo(int32_t frame, | |
280 FX_DWORD& width, | |
281 FX_DWORD& height, | |
282 FX_DWORD& comps, | |
283 FX_DWORD& bpc, | |
284 CFX_DIBAttribute* pAttribute) { | |
285 if (!TIFFSetDirectory(tif_ctx, (uint16)frame)) { | |
286 return FALSE; | |
287 } | |
288 FX_WORD tif_cs; | |
289 FX_DWORD tif_icc_size = 0; | |
290 uint8_t* tif_icc_buf = NULL; | |
291 FX_WORD tif_bpc = 0; | |
292 FX_WORD tif_cps; | |
293 FX_DWORD tif_rps; | |
294 width = height = comps = 0; | |
295 TIFFGetField(tif_ctx, TIFFTAG_IMAGEWIDTH, &width); | |
296 TIFFGetField(tif_ctx, TIFFTAG_IMAGELENGTH, &height); | |
297 TIFFGetField(tif_ctx, TIFFTAG_SAMPLESPERPIXEL, &comps); | |
298 TIFFGetField(tif_ctx, TIFFTAG_BITSPERSAMPLE, &tif_bpc); | |
299 TIFFGetField(tif_ctx, TIFFTAG_PHOTOMETRIC, &tif_cs); | |
300 TIFFGetField(tif_ctx, TIFFTAG_COMPRESSION, &tif_cps); | |
301 TIFFGetField(tif_ctx, TIFFTAG_ROWSPERSTRIP, &tif_rps); | |
302 TIFFGetField(tif_ctx, TIFFTAG_ICCPROFILE, &tif_icc_size, &tif_icc_buf); | |
303 if (pAttribute) { | |
304 pAttribute->m_wDPIUnit = FXCODEC_RESUNIT_INCH; | |
305 if (TIFFGetField(tif_ctx, TIFFTAG_RESOLUTIONUNIT, | |
306 &pAttribute->m_wDPIUnit)) { | |
307 pAttribute->m_wDPIUnit -= 1; | |
308 } | |
309 Tiff_Exif_GetInfo<FX_WORD>(tif_ctx, TIFFTAG_ORIENTATION, pAttribute); | |
310 if (Tiff_Exif_GetInfo<FX_FLOAT>(tif_ctx, TIFFTAG_XRESOLUTION, pAttribute)) { | |
311 void* val = pAttribute->m_Exif[TIFFTAG_XRESOLUTION]; | |
312 FX_FLOAT fDpi = val ? *reinterpret_cast<FX_FLOAT*>(val) : 0; | |
313 pAttribute->m_nXDPI = (int32_t)(fDpi + 0.5f); | |
314 } | |
315 if (Tiff_Exif_GetInfo<FX_FLOAT>(tif_ctx, TIFFTAG_YRESOLUTION, pAttribute)) { | |
316 void* val = pAttribute->m_Exif[TIFFTAG_YRESOLUTION]; | |
317 FX_FLOAT fDpi = val ? *reinterpret_cast<FX_FLOAT*>(val) : 0; | |
318 pAttribute->m_nYDPI = (int32_t)(fDpi + 0.5f); | |
319 } | |
320 Tiff_Exif_GetStringInfo(tif_ctx, TIFFTAG_IMAGEDESCRIPTION, pAttribute); | |
321 Tiff_Exif_GetStringInfo(tif_ctx, TIFFTAG_MAKE, pAttribute); | |
322 Tiff_Exif_GetStringInfo(tif_ctx, TIFFTAG_MODEL, pAttribute); | |
323 } | |
324 bpc = tif_bpc; | |
325 if (tif_rps > height) { | |
326 TIFFSetField(tif_ctx, TIFFTAG_ROWSPERSTRIP, tif_rps = height); | |
327 } | |
328 return TRUE; | |
329 } | |
330 void _TiffBGRA2RGBA(uint8_t* pBuf, int32_t pixel, int32_t spp) { | |
331 for (int32_t n = 0; n < pixel; n++) { | |
332 uint8_t tmp = pBuf[0]; | |
333 pBuf[0] = pBuf[2]; | |
334 pBuf[2] = tmp; | |
335 pBuf += spp; | |
336 } | |
337 } | |
338 FX_BOOL CCodec_TiffContext::isSupport(CFX_DIBitmap* pDIBitmap) { | |
339 if (TIFFIsTiled(tif_ctx)) { | |
340 return FALSE; | |
341 } | |
342 uint16_t photometric; | |
343 if (!TIFFGetField(tif_ctx, TIFFTAG_PHOTOMETRIC, &photometric)) { | |
344 return FALSE; | |
345 } | |
346 switch (pDIBitmap->GetBPP()) { | |
347 case 1: | |
348 case 8: | |
349 if (photometric != PHOTOMETRIC_PALETTE) { | |
350 return FALSE; | |
351 } | |
352 break; | |
353 case 24: | |
354 if (photometric != PHOTOMETRIC_RGB) { | |
355 return FALSE; | |
356 } | |
357 break; | |
358 default: | |
359 return FALSE; | |
360 } | |
361 uint16_t planarconfig; | |
362 if (!TIFFGetFieldDefaulted(tif_ctx, TIFFTAG_PLANARCONFIG, &planarconfig)) { | |
363 return FALSE; | |
364 } | |
365 if (planarconfig == PLANARCONFIG_SEPARATE) { | |
366 return FALSE; | |
367 } | |
368 return TRUE; | |
369 } | |
370 void CCodec_TiffContext::SetPalette(CFX_DIBitmap* pDIBitmap, uint16_t bps) { | |
371 uint16_t *red_orig, *green_orig, *blue_orig; | |
372 TIFFGetField(tif_ctx, TIFFTAG_COLORMAP, &red_orig, &green_orig, &blue_orig); | |
373 for (int32_t i = (1L << bps) - 1; i >= 0; i--) { | |
374 #define CVT(x) ((uint16_t)((x) >> 8)) | |
375 red_orig[i] = CVT(red_orig[i]); | |
376 green_orig[i] = CVT(green_orig[i]); | |
377 blue_orig[i] = CVT(blue_orig[i]); | |
378 #undef CVT | |
379 } | |
380 int32_t len = 1 << bps; | |
381 for (int32_t index = 0; index < len; index++) { | |
382 FX_DWORD r = red_orig[index] & 0xFF; | |
383 FX_DWORD g = green_orig[index] & 0xFF; | |
384 FX_DWORD b = blue_orig[index] & 0xFF; | |
385 FX_DWORD color = (uint32_t)b | ((uint32_t)g << 8) | ((uint32_t)r << 16) | | |
386 (((uint32)0xffL) << 24); | |
387 pDIBitmap->SetPaletteEntry(index, color); | |
388 } | |
389 } | |
390 FX_BOOL CCodec_TiffContext::Decode1bppRGB(CFX_DIBitmap* pDIBitmap, | |
391 int32_t height, | |
392 int32_t width, | |
393 uint16_t bps, | |
394 uint16_t spp) { | |
395 if (pDIBitmap->GetBPP() != 1 || spp != 1 || bps != 1 || | |
396 !isSupport(pDIBitmap)) { | |
397 return FALSE; | |
398 } | |
399 SetPalette(pDIBitmap, bps); | |
400 int32_t size = (int32_t)TIFFScanlineSize(tif_ctx); | |
401 uint8_t* buf = (uint8_t*)_TIFFmalloc(size); | |
402 if (buf == NULL) { | |
403 TIFFError(TIFFFileName(tif_ctx), "No space for scanline buffer"); | |
404 return FALSE; | |
405 } | |
406 uint8_t* bitMapbuffer = (uint8_t*)pDIBitmap->GetBuffer(); | |
407 FX_DWORD pitch = pDIBitmap->GetPitch(); | |
408 for (int32_t row = 0; row < height; row++) { | |
409 TIFFReadScanline(tif_ctx, buf, row, 0); | |
410 for (int32_t j = 0; j < size; j++) { | |
411 bitMapbuffer[row * pitch + j] = buf[j]; | |
412 } | |
413 } | |
414 _TIFFfree(buf); | |
415 return TRUE; | |
416 } | |
417 FX_BOOL CCodec_TiffContext::Decode8bppRGB(CFX_DIBitmap* pDIBitmap, | |
418 int32_t height, | |
419 int32_t width, | |
420 uint16_t bps, | |
421 uint16_t spp) { | |
422 if (pDIBitmap->GetBPP() != 8 || spp != 1 || (bps != 4 && bps != 8) || | |
423 !isSupport(pDIBitmap)) { | |
424 return FALSE; | |
425 } | |
426 SetPalette(pDIBitmap, bps); | |
427 int32_t size = (int32_t)TIFFScanlineSize(tif_ctx); | |
428 uint8_t* buf = (uint8_t*)_TIFFmalloc(size); | |
429 if (buf == NULL) { | |
430 TIFFError(TIFFFileName(tif_ctx), "No space for scanline buffer"); | |
431 return FALSE; | |
432 } | |
433 uint8_t* bitMapbuffer = (uint8_t*)pDIBitmap->GetBuffer(); | |
434 FX_DWORD pitch = pDIBitmap->GetPitch(); | |
435 for (int32_t row = 0; row < height; row++) { | |
436 TIFFReadScanline(tif_ctx, buf, row, 0); | |
437 for (int32_t j = 0; j < size; j++) { | |
438 switch (bps) { | |
439 case 4: | |
440 bitMapbuffer[row * pitch + 2 * j + 0] = (buf[j] & 0xF0) >> 4; | |
441 bitMapbuffer[row * pitch + 2 * j + 1] = (buf[j] & 0x0F) >> 0; | |
442 break; | |
443 case 8: | |
444 bitMapbuffer[row * pitch + j] = buf[j]; | |
445 break; | |
446 } | |
447 } | |
448 } | |
449 _TIFFfree(buf); | |
450 return TRUE; | |
451 } | |
452 FX_BOOL CCodec_TiffContext::Decode24bppRGB(CFX_DIBitmap* pDIBitmap, | |
453 int32_t height, | |
454 int32_t width, | |
455 uint16_t bps, | |
456 uint16_t spp) { | |
457 if (pDIBitmap->GetBPP() != 24 || !isSupport(pDIBitmap)) { | |
458 return FALSE; | |
459 } | |
460 int32_t size = (int32_t)TIFFScanlineSize(tif_ctx); | |
461 uint8_t* buf = (uint8_t*)_TIFFmalloc(size); | |
462 if (buf == NULL) { | |
463 TIFFError(TIFFFileName(tif_ctx), "No space for scanline buffer"); | |
464 return FALSE; | |
465 } | |
466 uint8_t* bitMapbuffer = (uint8_t*)pDIBitmap->GetBuffer(); | |
467 FX_DWORD pitch = pDIBitmap->GetPitch(); | |
468 for (int32_t row = 0; row < height; row++) { | |
469 TIFFReadScanline(tif_ctx, buf, row, 0); | |
470 for (int32_t j = 0; j < size - 2; j += 3) { | |
471 bitMapbuffer[row * pitch + j + 0] = buf[j + 2]; | |
472 bitMapbuffer[row * pitch + j + 1] = buf[j + 1]; | |
473 bitMapbuffer[row * pitch + j + 2] = buf[j + 0]; | |
474 } | |
475 } | |
476 _TIFFfree(buf); | |
477 return TRUE; | |
478 } | |
479 FX_BOOL CCodec_TiffContext::Decode(CFX_DIBitmap* pDIBitmap) { | |
480 FX_DWORD img_wid = pDIBitmap->GetWidth(); | |
481 FX_DWORD img_hei = pDIBitmap->GetHeight(); | |
482 FX_DWORD width = 0; | |
483 FX_DWORD height = 0; | |
484 TIFFGetField(tif_ctx, TIFFTAG_IMAGEWIDTH, &width); | |
485 TIFFGetField(tif_ctx, TIFFTAG_IMAGELENGTH, &height); | |
486 if (img_wid != width || img_hei != height) { | |
487 return FALSE; | |
488 } | |
489 if (pDIBitmap->GetBPP() == 32) { | |
490 FX_WORD rotation = ORIENTATION_TOPLEFT; | |
491 TIFFGetField(tif_ctx, TIFFTAG_ORIENTATION, &rotation); | |
492 if (TIFFReadRGBAImageOriented(tif_ctx, img_wid, img_hei, | |
493 (uint32*)pDIBitmap->GetBuffer(), rotation, | |
494 1)) { | |
495 for (FX_DWORD row = 0; row < img_hei; row++) { | |
496 uint8_t* row_buf = (uint8_t*)pDIBitmap->GetScanline(row); | |
497 _TiffBGRA2RGBA(row_buf, img_wid, 4); | |
498 } | |
499 return TRUE; | |
500 } | |
501 } | |
502 uint16_t spp, bps; | |
503 TIFFGetField(tif_ctx, TIFFTAG_SAMPLESPERPIXEL, &spp); | |
504 TIFFGetField(tif_ctx, TIFFTAG_BITSPERSAMPLE, &bps); | |
505 FX_DWORD bpp = bps * spp; | |
506 if (bpp == 1) { | |
507 return Decode1bppRGB(pDIBitmap, height, width, bps, spp); | |
508 } else if (bpp <= 8) { | |
509 return Decode8bppRGB(pDIBitmap, height, width, bps, spp); | |
510 } else if (bpp <= 24) { | |
511 return Decode24bppRGB(pDIBitmap, height, width, bps, spp); | |
512 } | |
513 return FALSE; | |
514 } | |
515 void* CCodec_TiffModule::CreateDecoder(IFX_FileRead* file_ptr) { | |
516 CCodec_TiffContext* pDecoder = new CCodec_TiffContext; | |
517 if (!pDecoder->InitDecoder(file_ptr)) { | |
518 delete pDecoder; | |
519 return NULL; | |
520 } | |
521 return pDecoder; | |
522 } | |
523 void CCodec_TiffModule::GetFrames(void* ctx, int32_t& frames) { | |
524 CCodec_TiffContext* pDecoder = (CCodec_TiffContext*)ctx; | |
525 pDecoder->GetFrames(frames); | |
526 } | |
527 FX_BOOL CCodec_TiffModule::LoadFrameInfo(void* ctx, | |
528 int32_t frame, | |
529 FX_DWORD& width, | |
530 FX_DWORD& height, | |
531 FX_DWORD& comps, | |
532 FX_DWORD& bpc, | |
533 CFX_DIBAttribute* pAttribute) { | |
534 CCodec_TiffContext* pDecoder = (CCodec_TiffContext*)ctx; | |
535 return pDecoder->LoadFrameInfo(frame, width, height, comps, bpc, pAttribute); | |
536 } | |
537 FX_BOOL CCodec_TiffModule::Decode(void* ctx, class CFX_DIBitmap* pDIBitmap) { | |
538 CCodec_TiffContext* pDecoder = (CCodec_TiffContext*)ctx; | |
539 return pDecoder->Decode(pDIBitmap); | |
540 } | |
541 void CCodec_TiffModule::DestroyDecoder(void* ctx) { | |
542 CCodec_TiffContext* pDecoder = (CCodec_TiffContext*)ctx; | |
543 delete pDecoder; | |
544 } | |
OLD | NEW |