PageRenderTime 46ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/trunk/src/common/Gdc2/Filters/Tiff.cpp

#
C++ | 1079 lines | 935 code | 109 blank | 35 comment | 114 complexity | 760b8222e0eec43f2358086888a49c4c MD5 | raw file
Possible License(s): LGPL-2.1, Unlicense
  1. /*hdr
  2. ** FILE: Tiff.cpp
  3. ** AUTHOR: Matthew Allen
  4. ** DATE: 9/10/98
  5. ** DESCRIPTION: Tiff filter
  6. **
  7. ** Copyright (C) 1998, Matthew Allen
  8. ** fret@memecode.com
  9. */
  10. #include <stdio.h>
  11. #ifdef WIN32
  12. #include <conio.h>
  13. #endif
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include "Lgi.h"
  17. #include "Lzw.h"
  18. #include "GVariant.h"
  19. // TIFF
  20. #define TIFF_USE_LZW
  21. class TiffIo : public GFilter
  22. {
  23. public:
  24. GStream *s;
  25. TiffIo()
  26. {
  27. s = 0;
  28. }
  29. Format GetFormat()
  30. {
  31. return FmtTiff;
  32. }
  33. bool GetSwap()
  34. {
  35. return false;
  36. }
  37. bool Read(void *p, int len)
  38. {
  39. return GFilter::Read(s, p, len);
  40. }
  41. bool Write(const void *p, int len)
  42. {
  43. return GFilter::Write(s, p, len);
  44. }
  45. };
  46. class IFD
  47. {
  48. void *Data;
  49. public:
  50. ushort Tag;
  51. ushort Type;
  52. ulong Count;
  53. ulong Offset;
  54. IFD();
  55. ~IFD();
  56. void *GetData();
  57. char *Str();
  58. int ElementSize();
  59. int Value();
  60. int ArrayValue(int i);
  61. bool Read(TiffIo &f);
  62. bool Write(TiffIo &f);
  63. };
  64. class GdcTiff : public TiffIo
  65. {
  66. List<IFD> Blocks;
  67. IFD *FindTag(ushort n);
  68. int ScanLength;
  69. #ifdef TIFF_USE_LZW
  70. Lzw Lib;
  71. #endif
  72. IoStatus ProcessRead(GSurface *pDC);
  73. IoStatus ProcessWrite(GSurface *pDC);
  74. public:
  75. GView *Parent;
  76. OsView Handle();
  77. GdcTiff();
  78. ~GdcTiff();
  79. int GetCapabilites() { return FILTER_CAP_READ; }
  80. IoStatus ReadImage(GSurface *pDC, GStream *In);
  81. IoStatus WriteImage(GStream *Out, GSurface *pDC);
  82. bool GetVariant(const char *n, GVariant &v, char *a)
  83. {
  84. if (!stricmp(n, LGI_FILTER_TYPE))
  85. {
  86. v = "Tiff";
  87. }
  88. else if (!stricmp(n, LGI_FILTER_EXTENSIONS))
  89. {
  90. v = "TIF,TIFF";
  91. }
  92. else return false;
  93. return true;
  94. }
  95. };
  96. // Object Factory
  97. class GdcTiffFactory : public GFilterFactory
  98. {
  99. bool CheckFile(char *File, int Access, uchar *Hint)
  100. {
  101. if (Access == FILTER_CAP_READ)
  102. {
  103. return (File) ? stristr(File, ".tiff") != 0 OR
  104. stristr(File, ".tif") != 0 : false;
  105. }
  106. return false;
  107. }
  108. GFilter *NewObject()
  109. {
  110. return new GdcTiff;
  111. }
  112. } TiffFactory;
  113. // Tiff tag numbers
  114. #define TAG_ImageX 0x100
  115. #define TAG_ImageY 0x101
  116. #define TAG_Bits 0x102
  117. #define TAG_Palette 0x140
  118. #define TAG_Compression 0x103
  119. #define TAG_RowsPerStrip 0x116
  120. #define TAG_StripOffsets 0x111
  121. #define TAG_StripByteOffsets 0x117
  122. #define TAG_PhotometricInterpretation 0x106 // PHOTOMETRIC_????
  123. #define TAG_Predictor 0x13D
  124. #define PHOTOMETRIC_MINISWHITE 0
  125. #define PHOTOMETRIC_MINISBLACK 1
  126. #define PHOTOMETRIC_RGB 2
  127. #define PHOTOMETRIC_PALETTE 3
  128. #define PHOTOMETRIC_MASK 4
  129. #define PHOTOMETRIC_CMYK 5
  130. #define PHOTOMETRIC_YCBCR 6
  131. #define PHOTOMETRIC_CIELAB 8
  132. #define PHOTOMETRIC_ICCLAB 9
  133. #define PHOTOMETRIC_ITULAB 10
  134. #define PHOTOMETRIC_LOGL 32844
  135. #define PHOTOMETRIC_LOGLUV 32845
  136. // Tiff tag data types
  137. #define TYPE_UBYTE 1
  138. #define TYPE_USHORT 3
  139. #define TYPE_ULONG 4
  140. #define TYPE_SBYTE 6
  141. #define TYPE_SSHORT 8
  142. #define TYPE_SLONG 9
  143. #define TYPE_ASCII 2
  144. #define TYPE_URATIONAL 5
  145. #define TYPE_UNDEFINED 7
  146. #define TYPE_SRATIONAL 10
  147. #define TYPE_FLOAT 11
  148. #define TYPE_DOUBLE 12
  149. ////////////////////////////////////////////////////////////////////////////////////////////
  150. IFD::IFD()
  151. {
  152. Data = 0;
  153. }
  154. IFD::~IFD()
  155. {
  156. DeleteArray((uchar*&)Data);
  157. }
  158. void *IFD::GetData()
  159. {
  160. return (Data) ? Data : &Offset;
  161. }
  162. int IFD::ElementSize()
  163. {
  164. switch (Type)
  165. {
  166. case TYPE_UBYTE:
  167. case TYPE_SBYTE:
  168. case TYPE_ASCII:
  169. case TYPE_UNDEFINED:
  170. {
  171. return 1;
  172. }
  173. case TYPE_USHORT:
  174. case TYPE_SSHORT:
  175. {
  176. return 2;
  177. }
  178. case TYPE_ULONG:
  179. case TYPE_SLONG:
  180. case TYPE_FLOAT:
  181. {
  182. return 4;
  183. }
  184. case TYPE_URATIONAL:
  185. case TYPE_SRATIONAL:
  186. case TYPE_DOUBLE:
  187. {
  188. return 8;
  189. }
  190. }
  191. return 0;
  192. }
  193. char *IFD::Str()
  194. {
  195. if (Data)
  196. {
  197. return (char*) Data;
  198. }
  199. return (char*) &Offset;
  200. }
  201. int IFD::Value()
  202. {
  203. if (Count == 1)
  204. {
  205. switch (Type)
  206. {
  207. case TYPE_UBYTE:
  208. {
  209. return (int) ((uchar) (Offset & 0xFF));
  210. }
  211. case TYPE_USHORT:
  212. {
  213. return (int) ((ushort) (Offset & 0xFFFF));
  214. }
  215. case TYPE_ULONG:
  216. {
  217. return (int) ((ulong) Offset);
  218. }
  219. case TYPE_SBYTE:
  220. {
  221. return (int) ((signed char) (Offset & 0xFF));
  222. }
  223. case TYPE_SSHORT:
  224. {
  225. return (int) ((short) (Offset & 0xFFFF));
  226. }
  227. case TYPE_SLONG:
  228. {
  229. return (int) ((long) Offset);
  230. }
  231. case TYPE_ASCII:
  232. {
  233. char *s = Str();
  234. return (s) ? atoi(s) : 0;
  235. }
  236. case TYPE_URATIONAL:
  237. case TYPE_UNDEFINED:
  238. case TYPE_SRATIONAL:
  239. case TYPE_FLOAT:
  240. case TYPE_DOUBLE:
  241. {
  242. break;
  243. }
  244. }
  245. }
  246. return 0;
  247. }
  248. int IFD::ArrayValue(int i)
  249. {
  250. void *p = GetData();
  251. if (i < Count AND p)
  252. {
  253. switch (Type)
  254. {
  255. case TYPE_ASCII:
  256. case TYPE_UBYTE:
  257. {
  258. return (int) ((uchar*)p)[i];
  259. }
  260. case TYPE_USHORT:
  261. {
  262. return (int) ((ushort*)p)[i];
  263. }
  264. case TYPE_ULONG:
  265. {
  266. return (int) ((ulong*)p)[i];
  267. }
  268. case TYPE_SBYTE:
  269. {
  270. return (int) ((signed char*)p)[i];
  271. }
  272. case TYPE_SSHORT:
  273. {
  274. return (int) ((short*)p)[i];
  275. }
  276. case TYPE_SLONG:
  277. {
  278. return (int) ((long*)p)[i];
  279. }
  280. }
  281. }
  282. else
  283. {
  284. printf("%s:%i - IFD::ArrayValue(%i) error, Count=%i p=%p\n",
  285. __FILE__, __LINE__,
  286. i, Count, p);
  287. }
  288. return 0;
  289. }
  290. bool IFD::Read(TiffIo &f)
  291. {
  292. f.Read(&Tag, sizeof(Tag));
  293. f.Read(&Type, sizeof(Type));
  294. f.Read(&Count, sizeof(Count));
  295. f.Read(&Offset, sizeof(Offset));
  296. int Size = Count * ElementSize();
  297. if (Size > 4)
  298. {
  299. Data = new uchar[Size];
  300. if (Data)
  301. {
  302. int Pos = f.s->GetPos();
  303. f.s->SetPos(Offset);
  304. switch (Type)
  305. {
  306. case TYPE_USHORT:
  307. {
  308. uint16 *p = (uint16*)Data;
  309. for (int i=0; i<Count; i++)
  310. {
  311. f.Read(p+i, sizeof(p[i]));
  312. }
  313. break;
  314. }
  315. case TYPE_ULONG:
  316. {
  317. uint32 *p = (uint32*)Data;
  318. for (int i=0; i<Count; i++)
  319. {
  320. f.Read(p+i, sizeof(p[i]));
  321. }
  322. break;
  323. }
  324. case TYPE_SSHORT:
  325. {
  326. int16 *p = (int16*)Data;
  327. for (int i=0; i<Count; i++)
  328. {
  329. f.Read(p+i, sizeof(p[i]));
  330. }
  331. break;
  332. }
  333. case TYPE_SLONG:
  334. {
  335. int32 *p = (int32*)Data;
  336. for (int i=0; i<Count; i++)
  337. {
  338. f.Read(p+i, sizeof(p[i]));
  339. }
  340. break;
  341. }
  342. default:
  343. {
  344. f.s->Read(Data, Size);
  345. break;
  346. }
  347. }
  348. f.s->SetPos(Pos);
  349. }
  350. }
  351. else if (f.GetSwap())
  352. {
  353. switch (Type)
  354. {
  355. case TYPE_UBYTE:
  356. case TYPE_SBYTE:
  357. {
  358. Offset >>= 24;
  359. break;
  360. }
  361. case TYPE_USHORT:
  362. case TYPE_SSHORT:
  363. {
  364. Offset >>= 16;
  365. break;
  366. }
  367. }
  368. }
  369. return true;
  370. }
  371. bool IFD::Write(TiffIo &f)
  372. {
  373. f.Write(&Tag, sizeof(Tag));
  374. f.Write(&Type, sizeof(Type));
  375. f.Write(&Count, sizeof(Count));
  376. f.Write(&Offset, sizeof(Offset));
  377. return true;
  378. }
  379. ////////////////////////////////////////////////////////////////////////////////////////////
  380. GdcTiff::GdcTiff()
  381. {
  382. Parent = 0;
  383. }
  384. GdcTiff::~GdcTiff()
  385. {
  386. }
  387. OsView GdcTiff::Handle()
  388. {
  389. return (Parent) ? Parent->Handle() : 0;
  390. }
  391. IFD *GdcTiff::FindTag(ushort n)
  392. {
  393. for (IFD *i = Blocks.First(); i; i = Blocks.Next())
  394. {
  395. if (i->Tag == n)
  396. {
  397. return i;
  398. }
  399. }
  400. return NULL;
  401. }
  402. class TiffPipe : public GBytePipe
  403. {
  404. Progress *p;
  405. int Scansize;
  406. int Last;
  407. int64 Size;
  408. public:
  409. TiffPipe(Progress *prog, int scansize, int size) : GBytePipe(size)
  410. {
  411. p = prog;
  412. Last = 0;
  413. Size = 0;
  414. Scansize = scansize;
  415. }
  416. int Write(const void *buf, int size, int flags)
  417. {
  418. int Status = GBytePipe::Write(buf, size, flags);
  419. Size += size;
  420. if (p)
  421. {
  422. int y = Size / Scansize;
  423. if (y > Last + 64)
  424. {
  425. p->Value(y);
  426. Last = y;
  427. LgiTrace("y=%i\n", y);
  428. }
  429. }
  430. return Status;
  431. }
  432. };
  433. GFilter::IoStatus GdcTiff::ProcessRead(GSurface *pDC)
  434. {
  435. GFilter::IoStatus Status = IoError;
  436. bool Error = false;
  437. IFD *x = FindTag(TAG_ImageX);
  438. IFD *y = FindTag(TAG_ImageY);
  439. IFD *BitTag = FindTag(TAG_Bits);
  440. int Bits = 1;
  441. int Pos = s->GetPos();
  442. if (BitTag)
  443. {
  444. switch (BitTag->Count)
  445. {
  446. case 1:
  447. {
  448. Bits = BitTag->Value();
  449. break;
  450. }
  451. case 3:
  452. {
  453. ushort *Depth = (ushort*) BitTag->GetData();
  454. if (Depth AND
  455. BitTag->Type == TYPE_USHORT)
  456. {
  457. // Baseline RGB image
  458. Bits = Depth[0] + Depth[1] + Depth[2];
  459. }
  460. break;
  461. }
  462. case 4:
  463. {
  464. // Maybe a 32-bit image?
  465. ushort *Depth = (ushort*) BitTag->GetData();
  466. if (Depth AND
  467. BitTag->Type == TYPE_USHORT)
  468. {
  469. // CMYK image?
  470. Bits = Depth[0] + Depth[1] + Depth[2] + Depth[3];
  471. }
  472. break;
  473. }
  474. }
  475. }
  476. int X = x ? x->Value() : 0;
  477. int Y = y ? y->Value() : 0;
  478. int B = 0;
  479. bool DownSam = false;
  480. if (Bits > 32)
  481. {
  482. B = 32;
  483. DownSam = true;
  484. }
  485. else
  486. {
  487. B = Bits >= 8 ? Bits : 8;
  488. }
  489. #ifdef MAC
  490. if (B == 24)
  491. B = 32;
  492. #endif
  493. if (pDC AND
  494. pDC->Create(X, Y, B))
  495. {
  496. if (Meter)
  497. {
  498. // Set the meter block to the size of a scanline
  499. Lib.MeterBlock = (X * Bits) >> (DownSam ? 2 : 3);
  500. Lib.Meter = Meter;
  501. Meter->SetDescription("scanlines");
  502. Meter->SetLimits(0, Y-1);
  503. }
  504. pDC->Colour(0);
  505. pDC->Rectangle();
  506. // Read Palette
  507. IFD *Palette = FindTag(TAG_Palette);
  508. if (Palette)
  509. {
  510. ushort *s = (ushort*) Palette->GetData();
  511. if (s AND Palette->Type == TYPE_USHORT)
  512. {
  513. int Colours = Palette->Count / 3;
  514. GPalette *Pal = new GPalette(0, Colours);
  515. if (Pal)
  516. {
  517. for (int i=0; i<Colours; i++)
  518. {
  519. GdcRGB *d = (*Pal)[i];
  520. if (d)
  521. {
  522. d->R = s[(0*Colours)+i] >> 8;
  523. d->G = s[(1*Colours)+i] >> 8;
  524. d->B = s[(2*Colours)+i] >> 8;
  525. }
  526. }
  527. pDC->Palette(Pal);
  528. }
  529. }
  530. }
  531. // Read Image
  532. IFD *Compression = FindTag(TAG_Compression);
  533. IFD *RowsPerStrip = FindTag(TAG_RowsPerStrip);
  534. IFD *StripOffsets = FindTag(TAG_StripOffsets);
  535. IFD *StripByteCounts = FindTag(TAG_StripByteOffsets);
  536. IFD *PhotometricInterpretation = FindTag(TAG_PhotometricInterpretation);
  537. if (Compression AND
  538. StripOffsets AND
  539. StripByteCounts)
  540. {
  541. int Comp = Compression->Value();
  542. int Rows = RowsPerStrip ? RowsPerStrip->Value() : Y;
  543. int Interpretation = PhotometricInterpretation->Value();
  544. int Cy = 0;
  545. switch (Bits)
  546. {
  547. case 1:
  548. case 8:
  549. case 24:
  550. case 32:
  551. case 64:
  552. {
  553. int Strip = 0;
  554. ScanLength = ((pDC->X() * Bits) + 7) / 8;
  555. for ( ;
  556. !Error AND
  557. Cy<pDC->Y() AND
  558. Strip < StripOffsets->Count;
  559. Strip++)
  560. {
  561. int Offset = StripOffsets->ArrayValue(Strip);
  562. if (Offset)
  563. {
  564. Lib.SetBufSize(Offset);
  565. }
  566. else
  567. {
  568. Error = true;
  569. break;
  570. }
  571. int Limit = min(pDC->Y() - Cy, Rows);
  572. s->SetPos(Offset);
  573. switch (Comp)
  574. {
  575. case 1: // uncompressed
  576. {
  577. for (int i=0; i<Limit; i++, Cy++)
  578. {
  579. uchar *d = (*pDC)[Cy];
  580. if (d)
  581. {
  582. s->Read(d, ScanLength);
  583. }
  584. }
  585. break;
  586. }
  587. case 32773: // Pack-bits RLE
  588. {
  589. for (int i=0; i<Limit; i++, Cy++)
  590. {
  591. uchar n;
  592. uchar c;
  593. uchar *d = (*pDC)[Cy];
  594. if (d)
  595. {
  596. // unpack data
  597. for (uchar *e=d+ScanLength; d<e; )
  598. {
  599. Read(&n, sizeof(n));
  600. if (n & 0x80)
  601. {
  602. // copy run
  603. Read(&c, sizeof(c));
  604. n = -n+1;
  605. memset(d, c, n);
  606. }
  607. else
  608. {
  609. // copy data
  610. n++;
  611. s->Read(d, n);
  612. }
  613. d += n;
  614. }
  615. }
  616. }
  617. break;
  618. }
  619. case 2: // modified huffman
  620. {
  621. if (Props)
  622. {
  623. GVariant v;
  624. Props->SetValue(LGI_FILTER_ERROR, v = "This image uses a modified huffman compression,\n"
  625. "Which is not supported yet.\n");
  626. }
  627. Error = true;
  628. break;
  629. }
  630. case 5: // LZW compression
  631. {
  632. #ifdef TIFF_USE_LZW
  633. TiffPipe Out(Meter, ScanLength, 512 << 10);
  634. if (Lib.Decompress(&Out, s))
  635. {
  636. // int Bytes = Out.GetSize();
  637. uchar *FullRez = (DownSam) ? new uchar[ScanLength] : 0;
  638. for (; Out.GetSize() >= ScanLength; Cy++)
  639. {
  640. uchar *o = (*pDC)[Cy];
  641. if (o)
  642. {
  643. if (DownSam)
  644. {
  645. if (FullRez)
  646. {
  647. Out.Read(FullRez, ScanLength);
  648. uint16 *s = (uint16*) FullRez;
  649. uint16 *e = s + (pDC->X() * 4);
  650. uchar *d = o;
  651. while (s < e)
  652. {
  653. *d++ = *s++ >> 8;
  654. }
  655. }
  656. }
  657. else
  658. {
  659. Out.Read(o, ScanLength);
  660. }
  661. }
  662. }
  663. DeleteArray(FullRez);
  664. }
  665. else
  666. {
  667. printf("%s:%i - LZW decompress failed.\n", __FILE__, __LINE__);
  668. }
  669. #else
  670. Props.Set(OptErrMsg,
  671. "This image uses LZW, which is unsupported due to\r\n"
  672. "UniSys requiring a royalty for it's patented algorithm.\r\n"
  673. "\r\n"
  674. "Use PNG instead.");
  675. Error = true;
  676. #endif
  677. break;
  678. }
  679. default:
  680. {
  681. if (Props)
  682. {
  683. char Msg[256];
  684. sprintf(Msg, "This image uses an unsupported TIFF compression method: %i", Comp);
  685. GVariant v = Msg;
  686. Props->SetValue(LGI_FILTER_ERROR, v);
  687. }
  688. Error = true;
  689. printf("%s:%i - Unknown compression '%i'\n", __FILE__, __LINE__, Comp);
  690. break;
  691. }
  692. }
  693. }
  694. if (Bits == 1)
  695. {
  696. // Unpack bits into 8 bit pixels
  697. for (int y=0; y<Cy; y++)
  698. {
  699. uchar *i = (*pDC)[y];
  700. for (int x = pDC->X()-1; x >= 0; x--)
  701. {
  702. i[x] = (
  703. i[x >> 3]
  704. &
  705. (1 << (7 - (x & 7)))
  706. )
  707. ?
  708. 0
  709. :
  710. 0xff;
  711. }
  712. }
  713. }
  714. else if (B == 32 && Bits == 24)
  715. {
  716. // Upconvert Rgb24 to Rgb32
  717. for (int y=0; y<Cy; y++)
  718. {
  719. Pixel32 *d = (Pixel32*)(*pDC)[y];
  720. Pixel24 *s = (Pixel24*)(*pDC)[y];
  721. Pixel32 *e = d;
  722. d += pDC->X() - 1;
  723. s += pDC->X() - 1;
  724. while (d >= e)
  725. {
  726. d->r = s->r;
  727. d->g = s->g;
  728. d->b = s->b;
  729. d->a = 255;
  730. s--;
  731. d--;
  732. }
  733. }
  734. }
  735. if (Interpretation == PHOTOMETRIC_RGB AND
  736. pDC->GetBits() >= 24)
  737. {
  738. if (pDC->GetBits() == 24)
  739. {
  740. class Tiff24
  741. {
  742. public:
  743. uint8 r, g, b;
  744. };
  745. // swap R and B
  746. for (int y=0; y<Cy; y++)
  747. {
  748. Pixel24 *e = (Pixel24*) (*pDC)[y];
  749. Pixel24 *d = e;
  750. Tiff24 *s = (Tiff24*) (*pDC)[y];
  751. ((uchar*&)d) += Pixel24::Size * (pDC->X()-1);
  752. s += pDC->X() - 1;
  753. while (d >= e)
  754. {
  755. Tiff24 t = *s;
  756. d->r = t.r;
  757. d->g = t.g;
  758. d->b = t.b;
  759. s--;
  760. ((uchar*&)d) -= Pixel24::Size;
  761. }
  762. }
  763. }
  764. else if (pDC->GetBits() == 32)
  765. {
  766. class Tiff32
  767. {
  768. public:
  769. uint8 r, g, b, a;
  770. };
  771. // swap R and B
  772. for (int y=0; y<Cy; y++)
  773. {
  774. Pixel32 *e = (Pixel32*) (*pDC)[y];
  775. Pixel32 *d = e;
  776. Tiff32 *s = (Tiff32*) (*pDC)[y];
  777. ((uchar*&)d) += Pixel32::Size * (pDC->X()-1);
  778. s += pDC->X() - 1;
  779. while (d >= e)
  780. {
  781. Tiff32 t = *s;
  782. d->r = t.r;
  783. d->g = t.g;
  784. d->b = t.b;
  785. s--;
  786. ((uchar*&)d) -= Pixel32::Size;
  787. }
  788. }
  789. }
  790. }
  791. if (Interpretation == PHOTOMETRIC_CMYK AND
  792. pDC->GetBits() == 32)
  793. {
  794. class TiffCmyk
  795. {
  796. public:
  797. uint8 c, m, y, k;
  798. };
  799. // 32 bit CMYK -> RGBA conversion
  800. uchar *Div = Div255Lut;
  801. for (int y=0; y<Cy; y++)
  802. {
  803. Pixel32 *d = (Pixel32*) (*pDC)[y];
  804. Pixel32 *e = d + pDC->X();
  805. TiffCmyk *s = (TiffCmyk*) (*pDC)[y];
  806. while (d < e)
  807. {
  808. int C = Div[s->c * (255 - s->k)] + s->k;
  809. int M = Div[s->m * (255 - s->k)] + s->k;
  810. int Y = Div[s->y * (255 - s->k)] + s->k;
  811. d->r = 255 - C;
  812. d->g = 255 - M;
  813. d->b = 255 - Y;
  814. d->a = 255;
  815. s++;
  816. d++;
  817. }
  818. }
  819. }
  820. IFD *Predictor = FindTag(TAG_Predictor);
  821. if (Predictor AND Predictor->Value() == 2)
  822. {
  823. switch (Bits)
  824. {
  825. case 8:
  826. {
  827. for (int y=0; y<Cy; y++)
  828. {
  829. uchar *d = (*pDC)[y];
  830. for (int x=1; x<pDC->X(); x++, d++)
  831. {
  832. d[0] += d[-1];
  833. }
  834. }
  835. break;
  836. }
  837. case 24:
  838. {
  839. for (int y=0; y<Cy; y++)
  840. {
  841. uchar *d = (*pDC)[y] + 3;
  842. for (int x=1; x<pDC->X(); x++, d+=3)
  843. {
  844. d[0] += d[-3];
  845. d[1] += d[-2];
  846. d[2] += d[-1];
  847. }
  848. }
  849. break;
  850. }
  851. }
  852. }
  853. break;
  854. }
  855. default:
  856. {
  857. if (Props)
  858. {
  859. char Msg[256];
  860. sprintf(Msg, "Image currently doesn't support %i bit TIFF files", Bits);
  861. GVariant v = Msg;
  862. Props->SetValue(LGI_FILTER_ERROR, v);
  863. }
  864. Error = true;
  865. break;
  866. }
  867. }
  868. Status = Error ? IoError : IoSuccess;
  869. }
  870. else
  871. {
  872. printf("%s:%i - Tag missing Compression=%p RowsPerStrip=%p StripOffsets=%p StripByteCounts=%p.\n",
  873. __FILE__, __LINE__,
  874. Compression,
  875. RowsPerStrip,
  876. StripOffsets,
  877. StripByteCounts);
  878. }
  879. }
  880. else
  881. {
  882. if (Props)
  883. {
  884. char Msg[256];
  885. sprintf(Msg, "Couldn't create bitmap of size %ix%i @ %i bpp.", X, Y, B);
  886. GVariant v = Msg;
  887. Props->SetValue(LGI_FILTER_ERROR, v);
  888. }
  889. Error = true;
  890. }
  891. s->SetPos(Pos);
  892. return Status;
  893. }
  894. GFilter::IoStatus GdcTiff::ReadImage(GSurface *pDC, GStream *In)
  895. {
  896. GFilter::IoStatus Status = IoError;
  897. ushort n16;
  898. if (!pDC || !In)
  899. return Status;
  900. s = In;
  901. In->Read(&n16, sizeof(n16));
  902. if (n16 == 0x4D4D)
  903. {
  904. // file is big endian so we swap
  905. // Intel is little endian (i think)
  906. // TODO_PPC: change this
  907. LgiAssert(0);
  908. }
  909. Read(&n16, sizeof(n16));
  910. if (n16 == 42) // check magic number
  911. {
  912. bool Done = false;
  913. bool Error = false;
  914. ulong Offset;
  915. Read(&Offset, sizeof(Offset));
  916. // loop through all the IFD's
  917. while ( !Done AND
  918. !Error)
  919. {
  920. if (Offset == 0)
  921. {
  922. Done = true;
  923. break;
  924. }
  925. else
  926. {
  927. In->SetPos(Offset);
  928. ushort IFDEntries;
  929. Read(&IFDEntries, sizeof(IFDEntries));
  930. for (int i=0; i<IFDEntries; i++)
  931. {
  932. IFD *Ifd = new IFD;
  933. if (Ifd)
  934. {
  935. Blocks.Insert(Ifd);
  936. Ifd->Read(*this);
  937. }
  938. else
  939. {
  940. Error = true;
  941. }
  942. }
  943. }
  944. if (!Error)
  945. {
  946. // process sub file
  947. Status = ProcessRead(pDC);
  948. Error = !Status;
  949. }
  950. else
  951. {
  952. printf("%s:%i - error reading the IFD's.\n", __FILE__, __LINE__);
  953. }
  954. Read(&Offset, sizeof(Offset));
  955. }
  956. }
  957. else
  958. {
  959. printf("%s:%i - magic number check failed.\n", __FILE__, __LINE__);
  960. }
  961. return Status;
  962. }
  963. GFilter::IoStatus GdcTiff::ProcessWrite(GSurface *pDC)
  964. {
  965. return IoUnsupportedFormat;
  966. }
  967. GFilter::IoStatus GdcTiff::WriteImage(GStream *Out, GSurface *pDC)
  968. {
  969. return ProcessWrite(pDC);
  970. }