PageRenderTime 68ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/src/tools/win32/krdevui/tpc/psd/DeePSDUnit.cpp

http://tvpcn.codeplex.com
C++ | 1109 lines | 791 code | 159 blank | 159 comment | 164 complexity | 8032652fad9d847e7971c33fd65e5157 MD5 | raw file
Possible License(s): LGPL-3.0, MIT, LGPL-2.0
  1. //---------------------------------------------------------------------------
  2. /*
  3. fgconvert (graphic converter for transparent images)
  4. Copyright (C) 2000 W.Dee <dee@kikyou.info> and contributors
  5. See details of license at "license.txt"
  6. */
  7. //---------------------------------------------------------------------------
  8. /*
  9. This is very limited loader for PSD (Photoshop native data format).
  10. This can only load PSD data of RGB, and the layer is 'normal' blend mode
  11. ('linear dodge' blend mode can also be loaded in additive alpha mode),
  12. 8bit for each color/alpha component.
  13. Otherwise the loading will fail.
  14. */
  15. //---------------------------------------------------------------------------
  16. #include <vcl.h>
  17. #pragma hdrstop
  18. #include "DeePSDUnit.h"
  19. //---------------------------------------------------------------------------
  20. // Check for pure virtual functions
  21. //---------------------------------------------------------------------------
  22. static void TestDeePSD(void)
  23. {
  24. new TDeePSD();
  25. }
  26. //---------------------------------------------------------------------------
  27. //---------------------------------------------------------------------------
  28. // integer types
  29. //---------------------------------------------------------------------------
  30. typedef unsigned long tui32;
  31. typedef long ti32;
  32. typedef unsigned short tui16;
  33. typedef short ti16;
  34. typedef unsigned char tui8;
  35. typedef char ti8;
  36. //---------------------------------------------------------------------------
  37. //---------------------------------------------------------------------------
  38. // Endian converters
  39. //---------------------------------------------------------------------------
  40. static void SwapBytes32(tui8 * data)
  41. {
  42. tui8 tmp;
  43. tmp = data[3];
  44. data[3] = data[0];
  45. data[0] = tmp;
  46. tmp = data[2];
  47. data[2] = data[1];
  48. data[1] = tmp;
  49. }
  50. //---------------------------------------------------------------------------
  51. static void inline SwapUI32(tui32 & data) { SwapBytes32((tui8*)&data); }
  52. //---------------------------------------------------------------------------
  53. static void SwapBytes16(tui8 * data)
  54. {
  55. tui8 tmp;
  56. tmp = data[1];
  57. data[1] = data[0];
  58. data[0] = tmp;
  59. }
  60. //---------------------------------------------------------------------------
  61. static void inline SwapUI16(tui16 & data) { SwapBytes16((tui8*)&data); }
  62. //---------------------------------------------------------------------------
  63. //---------------------------------------------------------------------------
  64. // Integer reader
  65. //---------------------------------------------------------------------------
  66. static tui32 Read32(TStream *in)
  67. {
  68. tui32 tmp;
  69. in->ReadBuffer(&tmp, 4);
  70. SwapUI32(tmp);
  71. return tmp;
  72. }
  73. //---------------------------------------------------------------------------
  74. static tui16 Read16(TStream *in)
  75. {
  76. tui16 tmp;
  77. in->ReadBuffer(&tmp, 2);
  78. SwapUI16(tmp);
  79. return tmp;
  80. }
  81. //---------------------------------------------------------------------------
  82. static tui8 Read8(TStream *in)
  83. {
  84. tui8 tmp;
  85. in->ReadBuffer(&tmp, 1);
  86. return tmp;
  87. }
  88. //---------------------------------------------------------------------------
  89. //---------------------------------------------------------------------------
  90. // Structure definitions
  91. //---------------------------------------------------------------------------
  92. #pragma pack(push, 1)
  93. struct TPSDFileHeader
  94. {
  95. tui8 Signature[4]; // always "8BPS"
  96. tui16 Version; // BE; always 1
  97. tui8 Reserved[6]; // always zero
  98. tui16 Channels; // BE
  99. tui32 Rows; // BE
  100. tui32 Columns; // BE
  101. tui16 Depth; // BE
  102. tui16 Mode; // BE
  103. void ToLittleEndian()
  104. {
  105. SwapBytes16((tui8*)&Version);
  106. SwapBytes16((tui8*)&Channels);
  107. SwapBytes16((tui8*)&Depth);
  108. SwapBytes16((tui8*)&Mode);
  109. SwapBytes32((tui8*)&Rows);
  110. SwapBytes32((tui8*)&Columns);
  111. }
  112. };
  113. struct TPSDChannelInfo
  114. {
  115. ti16 ID;
  116. tui32 Length;
  117. };
  118. struct TPSDLayerRecord
  119. {
  120. ti32 Top;
  121. ti32 Left;
  122. ti32 Bottom;
  123. ti32 Right;
  124. tui16 Channels;
  125. TPSDChannelInfo ChannelInfo[5];
  126. tui8 BlendSig[4];
  127. tui8 BlendMode[4];
  128. tui8 Opacity;
  129. tui8 Clipping;
  130. tui8 Flags;
  131. tui8 Reserved;
  132. };
  133. #pragma pack(pop)
  134. //---------------------------------------------------------------------------
  135. //---------------------------------------------------------------------------
  136. // 'normal' blend function
  137. //---------------------------------------------------------------------------
  138. static unsigned char OpacityOnOpacityTable[256*256];
  139. static unsigned char NegativeMulTable[256*256];
  140. static bool TableInit = false;
  141. #define ALPHA_BLEND(s, d, opa) (((d)*(255-(opa)) + (s)*(opa)) * ((1<<20) / 255) >> 20)
  142. //---------------------------------------------------------------------------
  143. static void InitTable()
  144. {
  145. if(TableInit) return;
  146. for(int a = 0; a<256; a++)
  147. {
  148. for(int b = 0; b<256; b++)
  149. {
  150. float c;
  151. int ci;
  152. int addr = b*256+ a;
  153. if(a)
  154. {
  155. float at = a/255.0, bt = b/255.0;
  156. c = bt / at;
  157. c /= (1.0 - bt + c);
  158. ci = (int)(c*255);
  159. if(ci>=256) ci = 255; /* will not overflow... */
  160. }
  161. else
  162. {
  163. ci=255;
  164. }
  165. OpacityOnOpacityTable[addr]=(unsigned char)ci;
  166. /* higher byte of the index is source opacity */
  167. /* lower byte of the index is destination opacity */
  168. NegativeMulTable[addr] = (unsigned char)
  169. ( 255 - (255-a)*(255-b)/ 255 );
  170. }
  171. }
  172. TableInit = true;
  173. }
  174. //---------------------------------------------------------------------------
  175. static void NormalBlendFunc(tui32 *dest, tui32 *src, int len)
  176. {
  177. InitTable();
  178. while(len--)
  179. {
  180. tui32 s = *src;
  181. tui32 d = *dest;
  182. tui32 r;
  183. int addr = ((s >> 16) & 0xff00) + (d >> 24); // table addr
  184. r = NegativeMulTable[addr] << 24;
  185. int sopa = OpacityOnOpacityTable[addr];
  186. int sv, dv;
  187. sv = s & 0xff;
  188. dv = d & 0xff;
  189. r |= ALPHA_BLEND(sv, dv, sopa);
  190. sv = (s & 0xff00)>>8;
  191. dv = (d & 0xff00)>>8;
  192. r |= (ALPHA_BLEND(sv, dv, sopa) << 8);
  193. sv = (s & 0xff0000)>>16;
  194. dv = (d & 0xff0000)>>16;
  195. r |= (ALPHA_BLEND(sv, dv, sopa) << 16);
  196. *dest = r;
  197. src++;
  198. dest++;
  199. }
  200. }
  201. //---------------------------------------------------------------------------
  202. //---------------------------------------------------------------------------
  203. // 'additive' blend function
  204. //---------------------------------------------------------------------------
  205. static inline int satadd(int a, int b)
  206. {
  207. int r = a + b;
  208. if(r > 255) r = 255;
  209. r |= -(r > 255);
  210. return r & 0xff;
  211. }
  212. static inline int ratio(int a, int b, int ratio)
  213. {
  214. // return (b*ratio + a*(255-ratio)) / 255
  215. return ((b*ratio + a*(255-ratio)) * ((1<<20) / 255)) >> 20;
  216. }
  217. static void AdditiveBlendFunc(tui32 * dest , tui32 * src, int len)
  218. {
  219. while(len--)
  220. {
  221. tui32 s = *src;
  222. tui32 d = *dest;
  223. int opa = s >> 24;
  224. *dest =
  225. (ratio((d )&0xff, satadd((d )&0xff, (s )&0xff), opa) )+
  226. (ratio((d>> 8)&0xff, satadd((d>> 8)&0xff, (s>> 8)&0xff), opa)<< 8)+
  227. (ratio((d>>16)&0xff, satadd((d>>16)&0xff, (s>>16)&0xff), opa)<<16)+
  228. (d & 0xff000000) ;
  229. src++;
  230. dest++;
  231. }
  232. }
  233. //---------------------------------------------------------------------------
  234. static void AdditiveCopyFunc(tui32 * dest , tui32 * src, int len)
  235. {
  236. while(len--)
  237. {
  238. tui32 s = *src;
  239. tui32 d = *dest;
  240. int opa = s >> 24;
  241. *dest = ((((s )&0xff) * opa / 255) ) +
  242. ((((s>> 8)&0xff) * opa / 255)<<8 ) +
  243. ((((s>>16)&0xff) * opa / 255)<<16) ;
  244. src++;
  245. dest++;
  246. }
  247. }
  248. //---------------------------------------------------------------------------
  249. //---------------------------------------------------------------------------
  250. // copy rectangle
  251. //---------------------------------------------------------------------------
  252. //---------------------------------------------------------------------------
  253. static void CopyBitmapRect(Graphics::TBitmap *dest, int x, int y,
  254. Graphics::TBitmap *ref, TRect refrect, int mode)
  255. {
  256. // Copy bitmap rectangle
  257. // bound check
  258. int bmpw, bmph;
  259. bmpw = ref->Width;
  260. bmph = ref->Height;
  261. if(refrect.left < 0)
  262. x -= refrect.left, refrect.left = 0;
  263. if(refrect.right > bmpw)
  264. refrect.right = bmpw;
  265. if(refrect.left >= refrect.right) return;
  266. if(refrect.top < 0)
  267. y -= refrect.top, refrect.top = 0;
  268. if(refrect.bottom > bmph)
  269. refrect.bottom = bmph;
  270. if(refrect.top >= refrect.bottom) return;
  271. bmpw = dest->Width;
  272. bmph = dest->Height;
  273. TRect rect;
  274. rect.left = x;
  275. rect.top = y;
  276. rect.right = rect.left + (refrect.right - refrect.left);
  277. rect.bottom = rect.top + (refrect.bottom - refrect.top);
  278. if(rect.left < 0)
  279. {
  280. refrect.left += -rect.left;
  281. rect.left = 0;
  282. }
  283. if(rect.right > bmpw)
  284. {
  285. refrect.right -= (rect.right - bmpw);
  286. rect.right = bmpw;
  287. }
  288. if(refrect.left >= refrect.right) return; // not drawable
  289. if(rect.top < 0)
  290. {
  291. refrect.top += -rect.top;
  292. rect.top = 0;
  293. }
  294. if(rect.bottom > bmph)
  295. {
  296. refrect.bottom -= (rect.bottom - bmph);
  297. rect.bottom = bmph;
  298. }
  299. if(refrect.top >= refrect.bottom) return; // not drawable
  300. // transfer
  301. int w = rect.right - rect.left;
  302. int h = rect.bottom - rect.top;
  303. for(int y = 0; y < h; y ++)
  304. {
  305. tui32 *d = (tui32*)dest->ScanLine[y + rect.top];
  306. tui32 *s = (tui32*)ref->ScanLine[y + refrect.top];
  307. if(mode == 0)
  308. memmove(d+ rect.left, s + refrect.left, w * sizeof(tui32));
  309. else if(mode == 1)
  310. NormalBlendFunc(d+ rect.left, s + refrect.left, w);
  311. else if(mode == 2)
  312. AdditiveCopyFunc(d + rect.left, s + refrect.left, w);
  313. else if(mode == 3)
  314. AdditiveBlendFunc(d + rect.left, s + refrect.left, w);
  315. }
  316. }
  317. //---------------------------------------------------------------------------
  318. //---------------------------------------------------------------------------
  319. // Set opacity to image
  320. //---------------------------------------------------------------------------
  321. static void SetBitmapOpacity(Graphics::TBitmap *bmp, int opa)
  322. {
  323. // bmp must be a 32bpp bitmap
  324. int w = bmp->Width;
  325. int h = bmp->Height;
  326. opa <<= 20;
  327. opa /= 255;
  328. for(int y = 0; y < h; y++)
  329. {
  330. tui32 *scl = (tui32*)bmp->ScanLine[y];
  331. for(int x = 0; x< w; x++)
  332. {
  333. tui32 d = scl[x];
  334. int o = d >> 24;
  335. o *= opa;
  336. o >>= 20;
  337. d &= 0xffffff;
  338. d |= o << 24;
  339. scl[x] = d;
  340. }
  341. }
  342. }
  343. //---------------------------------------------------------------------------
  344. /*
  345. static void SetBitmapAdditiveOpacity(Graphics::TBitmap *bmp, int opa)
  346. {
  347. // bmp must be a 32bpp bitmap
  348. int w = bmp->Width;
  349. int h = bmp->Height;
  350. opa <<= 20;
  351. opa /= 255;
  352. for(int y = 0; y < h; y++)
  353. {
  354. tui32 *scl = (tui32*)bmp->ScanLine[y];
  355. for(int x = 0; x< w; x++)
  356. {
  357. tui32 d = scl[x];
  358. scl[x] =
  359. ((((d ) & 0xff) * opa >> 20) )+
  360. ((((d>> 8) & 0xff) * opa >> 20) << 8)+
  361. ((((d>>16) & 0xff) * opa >> 20) <<16);
  362. }
  363. }
  364. }
  365. */
  366. //---------------------------------------------------------------------------
  367. //---------------------------------------------------------------------------
  368. // ConvertAlphaToAddAlpha
  369. //---------------------------------------------------------------------------
  370. void ConvertAlphaToAddAlpha(Graphics::TBitmap *in)
  371. {
  372. // convert alpha to additive alpha
  373. int w = in->Width;
  374. int h = in->Height;
  375. for(int y = 0; y < h; y++)
  376. {
  377. DWORD * p = (DWORD *)in->ScanLine[y];
  378. for(int x = 0; x < w; x++)
  379. {
  380. DWORD s = p[x];
  381. int alpha = (s >> 24) & 0xff;
  382. p[x] = (s & 0xff000000) +
  383. ((((s ) & 0xff) * alpha / 255) )+
  384. ((((s>>8 ) & 0xff) * alpha / 255)<<8 )+
  385. ((((s>>16) & 0xff) * alpha / 255)<<16) ;
  386. }
  387. }
  388. }
  389. //---------------------------------------------------------------------------
  390. //---------------------------------------------------------------------------
  391. // Read pixel data
  392. //---------------------------------------------------------------------------
  393. static Graphics::TBitmap *ReadPixelData30(TStream *Stream,
  394. int w, int h)
  395. {
  396. // read Photoshop 3.0 data
  397. // channel count must be 3
  398. Graphics::TBitmap *bmp = new Graphics::TBitmap();
  399. try
  400. {
  401. // set BMP size
  402. bmp->PixelFormat = pf24bit;
  403. bmp->Width = w;
  404. bmp->Height = h;
  405. // for each channel
  406. int mode = Read16(Stream);
  407. if(mode == 0)
  408. {
  409. // uncompressed image
  410. throw EDeePSD("TDeePSD: Uncompressed Photoshop 3.0 image is not supported." + AnsiString(mode));
  411. }
  412. else if(mode == 1)
  413. {
  414. // RLE compressed image
  415. tui16 * linelen = NULL;
  416. tui8 * linebuf = NULL;
  417. try
  418. {
  419. int h3 = h * 3;
  420. linelen = new tui16[h3];
  421. tui16 * ll = linelen;
  422. Stream->ReadBuffer(linelen, h3 * sizeof(tui16));
  423. for(int i = 0; i < h3; i++)
  424. SwapBytes16((tui8*)(linelen + i));
  425. for(int c = 0; c < 3; c++)
  426. {
  427. for(int y = 0; y < h; y++)
  428. {
  429. tui8 *scl = (tui8*)bmp->ScanLine[y] + "\x02\x01\x00"[c];
  430. linebuf = new tui8[*ll];
  431. Stream->ReadBuffer(linebuf, *ll);
  432. ll++;
  433. int x = 0;
  434. tui8 *lp = linebuf;
  435. while(x < w)
  436. {
  437. int n;
  438. n = (int)*lp;
  439. lp++;
  440. if(n >= 128) n -= 256;
  441. if(n == -128)
  442. {
  443. ;// ?? no operation
  444. }
  445. else if(n < 0) // run length
  446. {
  447. n = -n + 1;
  448. tui8 v = *lp;
  449. lp++;
  450. while(n--)
  451. *scl = v, scl += 3, x++;
  452. }
  453. else
  454. {
  455. // literal copy
  456. n++;
  457. while(n--)
  458. *scl = *(lp++), scl += 3, x++;
  459. }
  460. }
  461. delete [] linebuf;
  462. linebuf = NULL;
  463. }
  464. }
  465. }
  466. catch(...)
  467. {
  468. if(linelen) delete [] linelen;
  469. if(linebuf) delete [] linebuf;
  470. throw;
  471. }
  472. if(linelen) delete [] linelen;
  473. if(linebuf) delete [] linebuf;
  474. }
  475. else
  476. {
  477. throw EDeePSD("TDeePSD: The image has "
  478. "unsupported compression mode : " + AnsiString(mode));
  479. }
  480. }
  481. catch(...)
  482. {
  483. delete bmp;
  484. throw;
  485. }
  486. return bmp;
  487. }
  488. //---------------------------------------------------------------------------
  489. static Graphics::TBitmap *ReadPixelData(TStream *Stream, TPSDLayerRecord *lr,
  490. int laynum)
  491. {
  492. int w = lr->Right - lr->Left;
  493. int h = lr->Bottom - lr->Top;
  494. if(w < 0) w = -w; // is this needed?
  495. if(h < 0) h = -h;
  496. Graphics::TBitmap *bmp = new Graphics::TBitmap();
  497. try
  498. {
  499. // set BMP size
  500. bmp->PixelFormat = pf32bit;
  501. bmp->Width = w;
  502. bmp->Height = h;
  503. // clear BMP
  504. for(int y = 0; y < h; y++)
  505. {
  506. DWORD *scl = (DWORD*)bmp->ScanLine[y];
  507. for(int x = 0; x < w; x++)
  508. {
  509. scl[x] = 0xff000000;
  510. }
  511. }
  512. // for each channel
  513. for(int ch = 0; ch < lr->Channels; ch++)
  514. {
  515. int readstart = Stream->Position;
  516. int mode = Read16(Stream);
  517. int bitpos;
  518. bool readskip = false;
  519. tui32 bitmask;
  520. switch(lr->ChannelInfo[ch].ID)
  521. {
  522. case -2:
  523. readskip = true; break; // user supplied layer mask
  524. case -1:
  525. bitpos = 24; bitmask = 0x00ffffff; break; // alpha
  526. case 0:
  527. bitpos = 16; bitmask = 0xff00ffff; break; // R
  528. case 1:
  529. bitpos = 8; bitmask = 0xffff00ff; break; // G
  530. case 2:
  531. bitpos = 0; bitmask = 0xffffff00; break; // B
  532. default:
  533. readskip = true; break; // unknown channel ID
  534. // throw EDeePSD("TDeePSD: Layer #" + AnsiString(laynum) + " has "
  535. // "unsupported channel ID : " +
  536. // AnsiString((int)lr->ChannelInfo[ch].ID));
  537. }
  538. if(!readskip)
  539. {
  540. if(mode == 0)
  541. {
  542. // uncompressed image
  543. tui8 * data = new tui8[w * h];
  544. try
  545. {
  546. Stream->ReadBuffer(data, w * h);
  547. tui8 *p = data;
  548. for(int y = 0; y < h; y++)
  549. {
  550. tui32 * scl = (tui32*)bmp->ScanLine[y];
  551. for(int x = 0; x < w; x++)
  552. {
  553. tui32 d = scl[x];
  554. d &= bitmask;
  555. d |= (*p<<bitpos);
  556. scl[x] = d;
  557. p++;
  558. }
  559. }
  560. }
  561. catch(...)
  562. {
  563. delete [] data;
  564. throw;
  565. }
  566. delete [] data;
  567. }
  568. else if(mode == 1)
  569. {
  570. // RLE compressed image
  571. tui16 * linelen = NULL;
  572. tui8 * linebuf = NULL;
  573. try
  574. {
  575. linelen = new tui16[h];
  576. Stream->ReadBuffer(linelen, h * sizeof(tui16));
  577. for(int i = 0; i < h; i++)
  578. SwapBytes16((tui8*)(linelen + i));
  579. for(int y = 0; y < h; y++)
  580. {
  581. tui32 *scl = (tui32*)bmp->ScanLine[y];
  582. linebuf = new tui8[linelen[y]];
  583. Stream->ReadBuffer(linebuf, linelen[y]);
  584. int x = 0;
  585. tui8 *lp = linebuf;
  586. while(x < w)
  587. {
  588. int n;
  589. n = (int)*lp;
  590. lp++;
  591. if(n >= 128) n -= 256;
  592. if(n == -128)
  593. {
  594. ;// ?? no operation
  595. }
  596. else if(n < 0) // run length
  597. {
  598. n = -n + 1;
  599. tui32 v = *lp << bitpos;
  600. lp++;
  601. while(n--)
  602. {
  603. tui32 d = scl[x];
  604. d &= bitmask;
  605. d |= v;
  606. scl[x] = d;
  607. x++;
  608. }
  609. }
  610. else
  611. {
  612. // literal copy
  613. n++;
  614. while(n--)
  615. {
  616. tui32 d = scl[x];
  617. d &= bitmask;
  618. d |= (*lp << bitpos);
  619. lp++;
  620. scl[x] = d;
  621. x++;
  622. }
  623. }
  624. }
  625. delete [] linebuf;
  626. linebuf = NULL;
  627. }
  628. }
  629. catch(...)
  630. {
  631. if(linelen) delete [] linelen;
  632. if(linebuf) delete [] linebuf;
  633. throw;
  634. }
  635. if(linelen) delete [] linelen;
  636. if(linebuf) delete [] linebuf;
  637. }
  638. else
  639. {
  640. throw EDeePSD("TDeePSD: Layer #" + AnsiString(laynum) + " has "
  641. "unsupported compression mode : " + AnsiString(mode));
  642. }
  643. }
  644. Stream->Position = readstart + lr->ChannelInfo[ch].Length;
  645. }
  646. }
  647. catch(...)
  648. {
  649. delete bmp;
  650. throw;
  651. }
  652. return bmp;
  653. }
  654. //---------------------------------------------------------------------------
  655. //---------------------------------------------------------------------------
  656. // TDeePSD
  657. //---------------------------------------------------------------------------
  658. __fastcall TDeePSD::TDeePSD(void)
  659. {
  660. // constructor
  661. FLayerMode = "";
  662. }
  663. //---------------------------------------------------------------------------
  664. __fastcall TDeePSD::~TDeePSD(void)
  665. {
  666. // desturctor
  667. }
  668. //---------------------------------------------------------------------------
  669. void __fastcall TDeePSD::LoadFromStream(Classes::TStream * Stream)
  670. {
  671. // LoadFromStream
  672. // check file header
  673. TPSDFileHeader header;
  674. Stream->ReadBuffer(&header, sizeof(header));
  675. header.ToLittleEndian();
  676. if(memcmp(&header.Signature, "8BPS", 4))
  677. throw EDeePSD("TDeePSD: This is not a PSD file.");
  678. if(header.Version != 1)
  679. throw EDeePSD("TDeePSD: Invalid PSD version.");
  680. // if(header.Channels != 4)
  681. // throw EDeePSD("TDeePSD: Unsupported number of channels " +
  682. // AnsiString((int)header.Channels)+ " (must be 4)");
  683. if(header.Mode != 3)
  684. throw EDeePSD("TDeePSD: Unsupported color mode (must be RGB)");
  685. if(header.Depth != 8)
  686. throw EDeePSD("TDeePSD: Unsupported bits per channel " +
  687. AnsiString((int)header.Depth) + " (must be 8)");
  688. // skip Color mode data section
  689. {
  690. tui32 size = Read32(Stream);
  691. Stream->Position += size;
  692. }
  693. // skip Image resources section
  694. {
  695. tui32 size = Read32(Stream);
  696. Stream->Position += size;
  697. }
  698. // Set size
  699. PixelFormat = pf32bit;
  700. Width = header.Columns;
  701. Height = header.Rows;
  702. // clear image
  703. for(int y = 0; y < Height; y++)
  704. memset(ScanLine[y], 0, Width * sizeof(tui32));
  705. // read layer info section
  706. int layinfosize = Read32(Stream); // size of layer info section; discard
  707. if(layinfosize)
  708. {
  709. Read32(Stream); // discard
  710. int nlayers;
  711. nlayers = (ti16)Read16(Stream);
  712. if(nlayers < 0) nlayers = -nlayers;
  713. TPSDLayerRecord * lr = new TPSDLayerRecord[nlayers];
  714. try
  715. {
  716. for(int lay = 0; lay < nlayers; lay++)
  717. {
  718. // for each layers
  719. TPSDLayerRecord *clr = lr + lay;
  720. clr->Top = Read32(Stream);
  721. clr->Left = Read32(Stream);
  722. clr->Bottom = Read32(Stream);
  723. clr->Right = Read32(Stream);
  724. clr->Channels = Read16(Stream);
  725. if(clr->Channels > 5)
  726. throw EDeePSD("TDeePSD: Layer #" + AnsiString(lay) + " has "
  727. "unsupported layer channel count " + AnsiString((int)clr->Channels) +
  728. " (must be smaller than 6)");
  729. for(int i = 0; i < clr->Channels; i++)
  730. {
  731. clr->ChannelInfo[i].ID = Read16(Stream);
  732. clr->ChannelInfo[i].Length = Read32(Stream);
  733. }
  734. Stream->ReadBuffer(clr->BlendSig, 4);
  735. if(memcmp(clr->BlendSig, "8BIM", 4))
  736. throw EDeePSD("TDeePSD: This file is corrupted.");
  737. Stream->ReadBuffer(clr->BlendMode, 4);
  738. clr->Opacity = Read8(Stream);
  739. clr->Clipping = Read8(Stream);
  740. clr->Flags = Read8(Stream);
  741. Read8(Stream); // filler
  742. // skip extra bytes
  743. tui32 extra_bytes = Read32(Stream);
  744. Stream->Position += extra_bytes;
  745. }
  746. // check layer mode structure
  747. AnsiString org_layer_mode = FLayerMode;
  748. bool visible_found = false;
  749. if(FLayerMode == "addalpha")
  750. {
  751. // Additive Alpha output mode
  752. bool additive_found = false;
  753. for(int lay = 0; lay < nlayers; lay++)
  754. {
  755. TPSDLayerRecord *clr = lr + lay;
  756. if(clr->Opacity != 0 && !(clr->Flags & 2))
  757. {
  758. if(!memcmp(clr->BlendMode, "norm", 4))
  759. {
  760. // alpha blend mode
  761. if(additive_found)
  762. throw EDeePSD("TDeePSD: Layer #" + AnsiString(lay) + " is normal blend mode but "
  763. "cannot load normal blend mode layer over linear dodge blend mode layer");
  764. }
  765. else if(!memcmp(clr->BlendMode, "lddg", 4))
  766. {
  767. // linear dodge (additive)
  768. additive_found = true;
  769. }
  770. else
  771. throw EDeePSD("TDeePSD: Layer #" + AnsiString(lay) + " has "
  772. "unsupported blend mode '" + AnsiString((char*)clr->BlendMode, 4) +
  773. "' (must be 'norm' [normal] blend or 'lddg' [linear dodge] blend)");
  774. visible_found = true;
  775. }
  776. }
  777. }
  778. else
  779. {
  780. // normal mode
  781. // we only can pile 'normal' blend mode.
  782. // other blend modes cannot be piled yet.
  783. FLayerMode = "";
  784. for(int lay = 0; lay < nlayers; lay++)
  785. {
  786. TPSDLayerRecord *clr = lr + lay;
  787. if(clr->Opacity != 0 && !(clr->Flags & 2))
  788. {
  789. if(FLayerMode != "")
  790. {
  791. if(FLayerMode != "alpha" || memcmp(clr->BlendMode, "norm", 4))
  792. {
  793. throw EDeePSD("TDeePSD: Layer #" + AnsiString(lay) + " has "
  794. "blend mode '" + AnsiString((char*)clr->BlendMode, 4) +
  795. "' but currently this PSD loader cannot pile layers more than one in this mode.");
  796. }
  797. }
  798. if(!memcmp(clr->BlendMode, "norm", 4))
  799. FLayerMode = "alpha";
  800. else if(!memcmp(clr->BlendMode, "lddg", 4))
  801. FLayerMode = "psadd";
  802. else if(!memcmp(clr->BlendMode, "lbrn", 4))
  803. FLayerMode = "pssub";
  804. else if(!memcmp(clr->BlendMode, "mul ", 4))
  805. FLayerMode = "psmul";
  806. else if(!memcmp(clr->BlendMode, "scrn", 4))
  807. FLayerMode = "psscreen";
  808. else if(!memcmp(clr->BlendMode, "over", 4))
  809. FLayerMode = "psoverlay";
  810. else if(!memcmp(clr->BlendMode, "hLit", 4))
  811. FLayerMode = "pshlight";
  812. else if(!memcmp(clr->BlendMode, "sLit", 4))
  813. FLayerMode = "psslight";
  814. else if(!memcmp(clr->BlendMode, "div ", 4))
  815. FLayerMode = "psdodge";
  816. else if(!memcmp(clr->BlendMode, "idiv", 4))
  817. FLayerMode = "psburn";
  818. else if(!memcmp(clr->BlendMode, "lite", 4))
  819. FLayerMode = "pslighten";
  820. else if(!memcmp(clr->BlendMode, "dark", 4))
  821. FLayerMode = "psdarken";
  822. else if(!memcmp(clr->BlendMode, "diff", 4))
  823. FLayerMode = "psdiff";
  824. else if(!memcmp(clr->BlendMode, "smud", 4))
  825. FLayerMode = "psexcl";
  826. else
  827. throw EDeePSD("TDeePSD: Layer #" + AnsiString(lay) + " has "
  828. "unsupported blend mode '" + AnsiString((char*)clr->BlendMode, 4) +
  829. "'");
  830. visible_found = true;
  831. }
  832. }
  833. if(org_layer_mode != "" && FLayerMode != org_layer_mode)
  834. throw EDeePSD("TDeePSD: Unexpected layer mode '" + FLayerMode + "'");
  835. }
  836. if(!visible_found)
  837. throw EDeePSD("TDeePSD: This image does not have any visible layer");
  838. // read each layer image
  839. bool firstlayer = true;
  840. bool additive_found = false;
  841. for(int lay = 0; lay < nlayers; lay++)
  842. {
  843. // for each layers again
  844. // read pixel data
  845. TPSDLayerRecord *clr = lr + lay;
  846. Graphics::TBitmap *layerbmp = ReadPixelData(Stream, lr + lay, lay);
  847. try
  848. {
  849. if(clr->Opacity != 0 && !(clr->Flags & 2))
  850. {
  851. TRect refrect;
  852. refrect.left = refrect.top = 0;
  853. refrect.right = layerbmp->Width;
  854. refrect.bottom = layerbmp->Height;
  855. // blend
  856. if(!memcmp(clr->BlendMode, "norm", 4))
  857. {
  858. // normal alpha blend
  859. if(clr->Opacity != 255) SetBitmapOpacity(layerbmp, clr->Opacity);
  860. if(firstlayer)
  861. CopyBitmapRect(this, clr->Left, clr->Top, layerbmp, refrect, 0);
  862. else
  863. CopyBitmapRect(this, clr->Left, clr->Top, layerbmp, refrect, 1);
  864. }
  865. else if(org_layer_mode == "addalpha" && !memcmp(clr->BlendMode, "lddg", 4))
  866. {
  867. // linear dodge (additive) blend
  868. if(clr->Opacity != 255) SetBitmapOpacity(layerbmp, clr->Opacity);
  869. if(!additive_found)
  870. {
  871. additive_found = true;
  872. ConvertAlphaToAddAlpha(this);
  873. }
  874. if(firstlayer)
  875. CopyBitmapRect(this, clr->Left, clr->Top, layerbmp, refrect, 2);
  876. else
  877. CopyBitmapRect(this, clr->Left, clr->Top, layerbmp, refrect, 3);
  878. }
  879. else
  880. {
  881. if(clr->Opacity != 255) SetBitmapOpacity(layerbmp, clr->Opacity);
  882. if(firstlayer)
  883. CopyBitmapRect(this, clr->Left, clr->Top, layerbmp, refrect, 0);
  884. }
  885. firstlayer = false;
  886. }
  887. }
  888. catch(...)
  889. {
  890. delete layerbmp;
  891. throw;
  892. }
  893. delete layerbmp;
  894. }
  895. if(org_layer_mode == "addalpha" && !additive_found)
  896. ConvertAlphaToAddAlpha(this);
  897. }
  898. catch(...)
  899. {
  900. delete [] lr;
  901. throw;
  902. }
  903. delete [] lr;
  904. }
  905. else
  906. {
  907. // layer info section is zero
  908. if(header.Channels != 3)
  909. throw EDeePSD("TDeePSD: Unsupported number of channels " +
  910. AnsiString((int)header.Channels)+ " (must be 3)");
  911. Graphics::TBitmap *layerbmp =
  912. ReadPixelData30(Stream, header.Columns, header.Rows);
  913. try
  914. {
  915. Assign(layerbmp);
  916. }
  917. catch(...)
  918. {
  919. delete layerbmp;
  920. throw;
  921. }
  922. delete layerbmp;
  923. FLayerMode = "alpha"; // always assumes alpha
  924. }
  925. }
  926. //---------------------------------------------------------------------------
  927. void __fastcall TDeePSD::SaveToStream(Classes::TStream * Stream)
  928. {
  929. }
  930. //---------------------------------------------------------------------------
  931. static void InitTDeePSD()
  932. {
  933. TPicture::RegisterFileFormat(
  934. __classid(TPicture), "psd", "Photoshop image",
  935. __classid(TDeePSD));
  936. }
  937. static void UninitTDeePSD()
  938. {
  939. TPicture::UnregisterGraphicClass(__classid(TPicture),__classid(TDeePSD));
  940. }
  941. #pragma startup InitTDeePSD
  942. #pragma exit UninitTDeePSD
  943. //---------------------------------------------------------------------------
  944. //#pragma package(smart_init)