/ delphi-google-api/libs/TGifImage/GifImage.pas

http://delphi-google-api.googlecode.com/ · Pascal · 1460 lines · 726 code · 78 blank · 656 comment · 0 complexity · f6d1eb734cbb6febff5e7db70268c7a8 MD5 · raw file

  1. unit GIFImage;
  2. ////////////////////////////////////////////////////////////////////////////////
  3. // //
  4. // Project: GIF Graphics Object //
  5. // Module: gifimage //
  6. // Description: TGraphic implementation of the GIF89a graphics format //
  7. // Version: 2.2 //
  8. // Release: 5 //
  9. // Date: 23-MAY-1999 //
  10. // Target: Win32, Delphi 2, 3, 4 & 5, C++ Builder 3 & 4 //
  11. // Author(s): anme: Anders Melander, anders@melander.dk //
  12. // fila: Filip Larsen //
  13. // rps: Reinier Sterkenburg //
  14. // Copyright: (c) 1997-99 Anders Melander. //
  15. // All rights reserved. //
  16. // Formatting: 2 space indent, 8 space tabs, 80 columns. //
  17. // //
  18. ////////////////////////////////////////////////////////////////////////////////
  19. // Changed 2001.07.23 by Finn Tolderlund: //
  20. // Changed according to e-mail from "Rolf Frei" <rolf@eicom.ch> //
  21. // on 2001.07.23 so that it works in Delphi 6. //
  22. // //
  23. // Changed 2002.07.07 by Finn Tolderlund: //
  24. // Incorporated additional modifications by Alexey Barkovoy (clootie@reactor.ru)
  25. // found in his Delphi 6 GifImage.pas (from 22-Dec-2001). //
  26. // Alexey Barkovoy's Delphi 6 gifimage.pas can be downloaded from //
  27. // http://clootie.narod.ru/delphi/download_vcl.html //
  28. // These changes made showing of animated gif files more stable. The code //
  29. // from 2001.07.23 could crash sometimes with an Execption EAccessViolation. //
  30. // //
  31. // Changed 2002.10.06 by Finn Tolderlund: //
  32. // Delphi 7 compatible. //
  33. // //
  34. // Changed 2003-03-06 by Finn Tolderlund: //
  35. // Changes made as a result of postings in borland.public.delphi.graphics //
  36. // from 2003-02-28 to 2003-03-05 where white (255,255,255) in a bitmap //
  37. // was converted to (254,254,254) in the gif. //
  38. // The doCreateOptimizedPaletteFromSingleBitmap function and //
  39. // the CreateOptimizedPaletteFromManyBitmaps function is changed so that //
  40. // the correct offset 246 is used instead of 245. //
  41. // The ReduceColors function is changed according to Anders Melander's post //
  42. // so that a colour get converted to the precise colour if that colour is //
  43. // present in the palette when using ColorReduction rmQuantize. //
  44. // //
  45. // Changed 2003-03-09 by Finn Tolderlund: //
  46. // Delphi 7 version is now assumed if unknown compiler version is unknown //
  47. // for better compatibility with future Delphi versions. //
  48. // Hopefully this code is now compatible with future Delphi versions, //
  49. // unless Borland makes some changes that breaks existing code. //
  50. // //
  51. // Changed 2003-08-04 by Finn Tolderlund: //
  52. // Changed procedure AddMaskOnly so that it doesn't leak a GDI HBitmap-object //
  53. // and it doesn't release the handle of the source bitmap which //
  54. // is used to assign to the GIF object as in gif.assign(bm); //
  55. // These changes were made as a result of a news post made by Renate Schaaf //
  56. // with the subject "TGifImage HBitmap leak on assign?" //
  57. // in borland.public.delphi.graphics on Mon 28 Jul 2003 and Sun 03 Aug 2003. //
  58. // //
  59. // Changed 2004.03.09 by Finn Tolderlund: //
  60. // Added a ForceFrame property to the TGIFImage class. //
  61. // The ForceFrame property can be used to make TGIFImage display a apecific //
  62. // sub frame from an animated gif. //
  63. // How to use: Set the Animate property to False and set the ForceFrame //
  64. // property to a desired frame number (0-N) //
  65. // Normal display: Set the ForceFrame property to -1 and set Animate to True. //
  66. // If ForceFrame is negative TGIFImage behaves just as before this change. //
  67. // Note that if the sub frame in the gif only contains part of the image //
  68. // (i.e. only the changes from previous frames) the result is unpredictable. //
  69. // The result is best if each sub frame contains a whole image. //
  70. // If the sub frame is transparent the background is not automatically //
  71. // restored, you must do so yourself if you want that. //
  72. // If you are using a TImage to display the gif you can use //
  73. // Image.Parent.Invalidate or Image.Parent.Refresh to restore the background. //
  74. // This change was made as a result of a email correspondance with //
  75. // Tineke Kosmis (http://www.classe.nl/) which requested such a property. //
  76. // //
  77. // Changed 2006.07.09 by Finn Tolderlund: //
  78. // Added conditional switch as default: FIXHEADER_WIDTHHEIGHT_SILENT //
  79. // When the switch is defined: //
  80. // When loading a gif all frames are examined. If a frame has a larger //
  81. // Width/Height than the header values then the header values are updated //
  82. // with the larger values from the frame. //
  83. // I had a MANTA.GIF where the header said 120x89 but the frames said 200x148 //
  84. // and the frames got clipped. MSIE didn't clip it. //
  85. // http://www.graphcomp.com/info/specs/ani_gif.html : //
  86. // Do not assume all of your images are the same size. Read through their //
  87. // sizes and set the logical screen to the largest width & height included //
  88. // in the file. //
  89. // By removing the define FIXHEADER_WIDTHHEIGHT_SILENT //
  90. // the header is not altered. This makes the unit work as before. //
  91. // //
  92. // Changed 2006.07.10 by Finn Tolderlund: //
  93. // Added conditional switch as default: DEFAULT_GOCLEARLOOP //
  94. // When the switch is defined: //
  95. // When loading a gif default DrawOptions include goClearLoop //
  96. // Same as adding goClearLoop manually to DrawOptions. //
  97. // This will clear an animated gif before first frame on each loop. //
  98. // Someone sent me a 'conductor.gif' where some of the last frame was retaind //
  99. // when beginning a new loop and that was visually incorrect. //
  100. // Without glClearLoop the first frame may look different on the second loop //
  101. // because some part of the last frame could still be present. //
  102. // With goClearLoop the first frame will always look the same on each loop. //
  103. // I think the last is better. //
  104. // //
  105. // Changed 2006.07.29 by Finn Tolderlund: //
  106. // Added a check in procedure TGIFSubImage.Decompress to make sure that //
  107. // the InitialBitsPerCode variable never exeeds the value 15. //
  108. // Someone sent an animated iup110296.gif (corrupt I think) which caused //
  109. // this unit to crash in function NextLZW because InitialBitsPerCode was 20. //
  110. // This fix prevents the crash and should not cause problems with other gifs. //
  111. // Not sure that the fix is the correct way to handle it. It seems to work. //
  112. // //
  113. // Changed 2006.10.09 by Finn Tolderlund: //
  114. // Received a mail from Michael Thomas Greer with a fix that allows //
  115. // the TGIFSubImage.Pixels[] property to be writeable. The help file states //
  116. // that the Pixels property can be written, but it was read-only. //
  117. // Help file: "Write Pixels to change the color index of individual pixels". //
  118. // //
  119. // Changed 2006.10.16 by Finn Tolderlund: //
  120. // Received a mail from Maurizio Lotauro who was using Delphi 5 and FastMM4. //
  121. // FastMM4 complains about a memory leak when using Delphi 5. //
  122. // I don't have Delphi 5 installed so I can't test if there really is a //
  123. // memory leak or if it's just FastMM4 which can't detect it correctly. //
  124. // The problem and fix only applies to Delphi 5 or older. //
  125. // Added a fix to keep FastMM4 happy. See more at this link: //
  126. // http://sourceforge.net/forum/forum.php?thread_id=1559584&forum_id=443400 //
  127. // //
  128. // Changed 2007.01.18 by Finn Tolderlund: //
  129. // The ReduceColors function is changed so that it's now possible to use //
  130. // the TFastColorLookup class if you use ColorReduction rmQuantize. //
  131. // The TFastColorLookup class was removed 2003-03-06, but is introduced again //
  132. // because Paul Lopez needed speed when adding images to a gif. //
  133. // This changes how rmQuantize works: It's now fast but less precise. //
  134. // This means: //
  135. // Use rmQuantizeWindows to get precision, use rmQuantize if you need speed. //
  136. // //
  137. // Changed 2008.10.19 by Finn Tolderlund: //
  138. // Now compatible with Delphi 2009. //
  139. // Generally changed use of Char/PChar to AnsiChar/PAnsiChar. //
  140. // //
  141. // Changed 2009.10.10 by Finn Tolderlund: //
  142. // Now compatible with Delphi 2010. //
  143. // Changed conditional defines to assume Delphi 2010 for future compilers. //
  144. // Kind thanks to Peter Johnson (www.delphidabbler.com) //
  145. // //
  146. // Changed 2009.10.14 by Finn Tolderlund: //
  147. // Simplified the list of defines and remove a few warnings in Delphi 2006. //
  148. // //
  149. ////////////////////////////////////////////////////////////////////////////////
  150. // //
  151. // Please read the "Conditions of use" in the release notes. //
  152. // //
  153. ////////////////////////////////////////////////////////////////////////////////
  154. // Known problems:
  155. //
  156. // * The combination of buffered, tiled and transparent draw will display the
  157. // background incorrectly (scaled).
  158. // If this is a problem for you, use non-buffered (goDirectDraw) drawing
  159. // instead.
  160. //
  161. // * The combination of non-buffered, transparent and stretched draw is
  162. // sometimes distorted with a pattern effect when the image is displayed
  163. // smaller than the real size (shrinked).
  164. //
  165. // * Buffered display flickers when TGIFImage is used by a transparent TImage
  166. // component.
  167. // This is a problem with TImage caused by the fact that TImage was designed
  168. // with static images in mind. Not much I can do about it.
  169. //
  170. ////////////////////////////////////////////////////////////////////////////////
  171. // To do (in rough order of priority):
  172. // { TODO -oanme -cFeature : TImage hook for destroy notification. }
  173. // { TODO -oanme -cFeature : TBitmap pool to limit resource consumption on Win95/98. }
  174. // { TODO -oanme -cImprovement : Make BitsPerPixel property writable. }
  175. // { TODO -oanme -cFeature : Visual GIF component. }
  176. // { TODO -oanme -cImprovement : Easier method to determine DrawPainter status. }
  177. // { TODO -oanme -cFeature : Import to 256+ color GIF. }
  178. // { TODO -oanme -cFeature : Make some of TGIFImage's properties persistent (DrawOptions etc). }
  179. // { TODO -oanme -cFeature : Add TGIFImage.Persistent property. Should save published properties in application extension when this options is set. }
  180. // { TODO -oanme -cBugFix : Solution for background buffering in scrollbox. }
  181. //
  182. //////////////////////////////////////////////////////////////////////////////////
  183. {$ifdef BCB}
  184. {$ObjExportAll On}
  185. {$endif}
  186. interface
  187. ////////////////////////////////////////////////////////////////////////////////
  188. //
  189. // Conditional Compiler Symbols
  190. //
  191. ////////////////////////////////////////////////////////////////////////////////
  192. (*
  193. DEBUG Must be defined if any of the DEBUG_xxx
  194. symbols are defined.
  195. If the symbol is defined the source will not be
  196. optimized and overflow- and range checks will be
  197. enabled.
  198. DEBUG_HASHPERFORMANCE Calculates hash table performance data.
  199. DEBUG_HASHFILLFACTOR Calculates fill factor of hash table -
  200. Interferes with DEBUG_HASHPERFORMANCE.
  201. DEBUG_COMPRESSPERFORMANCE Calculates LZW compressor performance data.
  202. DEBUG_DECOMPRESSPERFORMANCE Calculates LZW decompressor performance data.
  203. DEBUG_DITHERPERFORMANCE Calculates color reduction performance data.
  204. DEBUG_DRAWPERFORMANCE Calculates low level drawing performance data.
  205. The performance data for DEBUG_DRAWPERFORMANCE
  206. will be displayed when you press the Ctrl key.
  207. DEBUG_RENDERPERFORMANCE Calculates performance data for the GIF to
  208. bitmap converter.
  209. The performance data for DEBUG_DRAWPERFORMANCE
  210. will be displayed when you press the Ctrl key.
  211. GIF_NOSAFETY Define this symbol to disable overflow- and
  212. range checks.
  213. Ignored if the DEBUG symbol is defined.
  214. STRICT_MOZILLA Define to mimic Mozilla as closely as possible.
  215. If not defined, a slightly more "optimal"
  216. implementation is used (IMHO).
  217. FAST_AS_HELL Define this symbol to use strictly GIF compliant
  218. (but too fast) animation timing.
  219. Since our paint routines are much faster and
  220. more precise timed than Mozilla's, the standard
  221. GIF and Mozilla values causes animations to loop
  222. faster than they would in Mozilla.
  223. If the symbol is _not_ defined, an alternative
  224. set of tweaked timing values will be used.
  225. The tweaked values are not optimal but are based
  226. on tests performed on my reference system:
  227. - Windows 95
  228. - 133 MHz Pentium
  229. - 64Mb RAM
  230. - Diamond Stealth64/V3000
  231. - 1600*1200 in 256 colors
  232. The alternate values can be modified if you are
  233. not satisfied with my defaults (they can be
  234. found a few pages down).
  235. REGISTER_TGIFIMAGE Define this symbol to register TGIFImage with
  236. the TPicture class and integrate with TImage.
  237. This is required to be able to display GIFs in
  238. the TImage component.
  239. The symbol is defined by default.
  240. Undefine if you use another GIF library to
  241. provide GIF support for TImage.
  242. PIXELFORMAT_TOO_SLOW When this symbol is defined, the internal
  243. PixelFormat routines are used in some places
  244. instead of TBitmap.PixelFormat.
  245. The current implementation (Delphi4, Builder 3)
  246. of TBitmap.PixelFormat can in some situation
  247. degrade performance.
  248. The symbol is defined by default.
  249. CREATEDIBSECTION_SLOW If this symbol is defined, TDIBWriter will
  250. use global memory as scanline storage, instead
  251. of a DIB section.
  252. Benchmarks have shown that a DIB section is
  253. twice as slow as global memory.
  254. The symbol is defined by default.
  255. The symbol requires that PIXELFORMAT_TOO_SLOW
  256. is defined.
  257. SERIALIZE_RENDER Define this symbol to serialize threaded
  258. GIF to bitmap rendering.
  259. When a GIF is displayed with the goAsync option
  260. (the default), the GIF to bitmap rendering is
  261. executed in the context of the draw thread.
  262. If more than one thread is drawing the same GIF
  263. or the GIF is being modified while it is
  264. animating, the GIF to bitmap rendering should be
  265. serialized to guarantee that the bitmap isn't
  266. modified by more than one thread at a time. If
  267. SERIALIZE_RENDER is defined, the draw threads
  268. uses TThread.Synchronize to serialize GIF to
  269. bitmap rendering.
  270. FIXHEADER_WIDTHHEIGHT_SILENT Define this symbol to adjust Width and Height
  271. in the header if any of the frames has a larger
  272. Width or Height.
  273. DEFAULT_GOCLEARLOOP Define this symbol to clear animation on each
  274. loop before first frame.
  275. Same as adding goClearLoop to DrawOptions.
  276. STRICT_MOZILLA does the same,
  277. but STRICT_MOZILLA does something more.
  278. *)
  279. {$DEFINE REGISTER_TGIFIMAGE}
  280. {$DEFINE PIXELFORMAT_TOO_SLOW}
  281. {$DEFINE CREATEDIBSECTION_SLOW}
  282. {$DEFINE FIXHEADER_WIDTHHEIGHT_SILENT}
  283. {$DEFINE DEFAULT_GOCLEARLOOP}
  284. ////////////////////////////////////////////////////////////////////////////////
  285. //
  286. // Determine Delphi and C++ Builder version
  287. //
  288. ////////////////////////////////////////////////////////////////////////////////
  289. // Delphi 1.x
  290. {$IFDEF VER80}
  291. 'Error: TGIFImage does not support Delphi 1.x'
  292. {$ENDIF}
  293. // Delphi 2.x
  294. {$IFDEF VER90}
  295. {$DEFINE VER9x}
  296. {$ENDIF}
  297. // C++ Builder 1.x
  298. {$IFDEF VER93}
  299. // Good luck...
  300. {$DEFINE VER9x}
  301. {$ENDIF}
  302. // Delphi 3.x
  303. {$IFDEF VER100}
  304. {$DEFINE VER10_PLUS}
  305. {$DEFINE D3_BCB3}
  306. {$ENDIF}
  307. // C++ Builder 3.x
  308. {$IFDEF VER110}
  309. {$DEFINE VER10_PLUS}
  310. {$DEFINE VER11_PLUS}
  311. {$DEFINE D3_BCB3}
  312. {$DEFINE BAD_STACK_ALIGNMENT}
  313. {$ENDIF}
  314. // Delphi 4.x
  315. {$IFDEF VER120}
  316. {$DEFINE VER10_PLUS}
  317. {$DEFINE VER11_PLUS}
  318. {$DEFINE VER12_PLUS}
  319. {$DEFINE BAD_STACK_ALIGNMENT}
  320. {$ENDIF}
  321. // C++ Builder 4.x
  322. {$IFDEF VER125}
  323. {$DEFINE VER10_PLUS}
  324. {$DEFINE VER11_PLUS}
  325. {$DEFINE VER12_PLUS}
  326. {$DEFINE VER125_PLUS}
  327. {$DEFINE BAD_STACK_ALIGNMENT}
  328. {$ENDIF}
  329. // Delphi 5.x
  330. {$IFDEF VER130}
  331. {$DEFINE VER10_PLUS}
  332. {$DEFINE VER11_PLUS}
  333. {$DEFINE VER12_PLUS}
  334. {$DEFINE VER125_PLUS}
  335. {$DEFINE VER13_PLUS}
  336. {$DEFINE BAD_STACK_ALIGNMENT}
  337. {$ENDIF}
  338. (*
  339. // Delphi 6.x
  340. {$IFDEF VER140}
  341. {$WARN SYMBOL_PLATFORM OFF}
  342. {$DEFINE VER10_PLUS}
  343. {$DEFINE VER11_PLUS}
  344. {$DEFINE VER12_PLUS}
  345. {$DEFINE VER125_PLUS}
  346. {$DEFINE VER13_PLUS}
  347. {$DEFINE VER14_PLUS}
  348. {$DEFINE BAD_STACK_ALIGNMENT}
  349. {$ENDIF}
  350. // Delphi 7.x
  351. {$IFDEF VER150}
  352. {$WARN SYMBOL_PLATFORM OFF}
  353. {$DEFINE VER10_PLUS}
  354. {$DEFINE VER11_PLUS}
  355. {$DEFINE VER12_PLUS}
  356. {$DEFINE VER125_PLUS}
  357. {$DEFINE VER13_PLUS}
  358. {$DEFINE VER14_PLUS}
  359. {$DEFINE VER15_PLUS}
  360. {$DEFINE BAD_STACK_ALIGNMENT}
  361. {$ENDIF}
  362. // 2008.10.19 ->
  363. // Delphi 2009
  364. {$IFDEF VER200}
  365. {$WARN SYMBOL_PLATFORM OFF}
  366. {$DEFINE VER10_PLUS}
  367. {$DEFINE VER11_PLUS}
  368. {$DEFINE VER12_PLUS}
  369. {$DEFINE VER125_PLUS}
  370. {$DEFINE VER13_PLUS}
  371. {$DEFINE VER14_PLUS}
  372. {$DEFINE VER15_PLUS}
  373. {$DEFINE VER20_PLUS}
  374. {$DEFINE BAD_STACK_ALIGNMENT}
  375. {$ENDIF}
  376. // 2008.10.19 <-
  377. // 2003.03.09 ->
  378. // Unknown compiler version - assume D7 compatible
  379. {$IFNDEF VER9x}
  380. {$IFNDEF VER10_PLUS}
  381. {$WARN SYMBOL_PLATFORM OFF}
  382. {$DEFINE VER10_PLUS}
  383. {$DEFINE VER11_PLUS}
  384. {$DEFINE VER12_PLUS}
  385. {$DEFINE VER125_PLUS}
  386. {$DEFINE VER13_PLUS}
  387. {$DEFINE VER14_PLUS}
  388. {$DEFINE VER15_PLUS}
  389. {$DEFINE BAD_STACK_ALIGNMENT}
  390. {$ENDIF}
  391. {$ENDIF}
  392. // 2003.03.09 <-
  393. // 2009.10.10 ->
  394. // This ensures that future compilers always have same defines as latest compiler listed here.
  395. {$IFDEF CONDITIONALEXPRESSIONS}
  396. {$IF CompilerVersion >= 21.0} // >= Delphi 2010
  397. {$WARN SYMBOL_PLATFORM OFF}
  398. {$WARN SYMBOL_DEPRECATED OFF}
  399. {$DEFINE VER10_PLUS}
  400. {$DEFINE VER11_PLUS}
  401. {$DEFINE VER12_PLUS}
  402. {$DEFINE VER125_PLUS}
  403. {$DEFINE VER13_PLUS}
  404. {$DEFINE VER14_PLUS}
  405. {$DEFINE VER15_PLUS}
  406. {$DEFINE VER20_PLUS}
  407. {$DEFINE BAD_STACK_ALIGNMENT}
  408. {$DEFINE VER21_PLUS}
  409. {$IFEND}
  410. {$ENDIF}
  411. // 2009.10.10 <-
  412. *)
  413. // 2009.10.14 ->
  414. // This ensures that future compilers always have same defines as latest compiler listed here.
  415. {$IFDEF CONDITIONALEXPRESSIONS}
  416. {$IF CompilerVersion >= 14.0} // >= Delphi 6
  417. {$WARN SYMBOL_PLATFORM OFF}
  418. {$WARN SYMBOL_DEPRECATED OFF}
  419. {$DEFINE VER10_PLUS}
  420. {$DEFINE VER11_PLUS}
  421. {$DEFINE VER12_PLUS}
  422. {$DEFINE VER125_PLUS}
  423. {$DEFINE VER13_PLUS}
  424. {$DEFINE VER14_PLUS}
  425. {$DEFINE BAD_STACK_ALIGNMENT}
  426. {$IFEND}
  427. {$IF CompilerVersion >= 15.0} // >= Delphi 7
  428. {$DEFINE VER15_PLUS}
  429. {$IFEND}
  430. {$IF CompilerVersion >= 20.0} // >= Delphi 2009
  431. {$DEFINE VER20_PLUS}
  432. {$IFEND}
  433. {$IF CompilerVersion >= 21.0} // >= Delphi 2010
  434. {$DEFINE VER21_PLUS}
  435. {$IFEND}
  436. {$ENDIF}
  437. // 2009.10.14 <-
  438. ////////////////////////////////////////////////////////////////////////////////
  439. //
  440. // Compiler Options required to compile this library
  441. //
  442. ////////////////////////////////////////////////////////////////////////////////
  443. {$A+,B-,H+,J+,K-,M-,T-,X+}
  444. // Debug control - You can safely change these settings
  445. {$IFDEF DEBUG}
  446. {$C+} // ASSERTIONS
  447. {$O-} // OPTIMIZATION
  448. {$Q+} // OVERFLOWCHECKS
  449. {$R+} // RANGECHECKS
  450. {$ELSE}
  451. {$C-} // ASSERTIONS
  452. {$IFDEF GIF_NOSAFETY}
  453. {$Q-}// OVERFLOWCHECKS
  454. {$R-}// RANGECHECKS
  455. {$ENDIF}
  456. {$ENDIF}
  457. // Special options for Time2Help parser
  458. {$ifdef TIME2HELP}
  459. {$UNDEF PIXELFORMAT_TOO_SLOW}
  460. {$endif}
  461. ////////////////////////////////////////////////////////////////////////////////
  462. //
  463. // External dependecies
  464. //
  465. ////////////////////////////////////////////////////////////////////////////////
  466. uses
  467. sysutils,
  468. Windows,
  469. Graphics,
  470. Classes;
  471. ////////////////////////////////////////////////////////////////////////////////
  472. //
  473. // TGIFImage library version
  474. //
  475. ////////////////////////////////////////////////////////////////////////////////
  476. const
  477. GIFVersion = $0202;
  478. GIFVersionMajor = 2;
  479. GIFVersionMinor = 2;
  480. GIFVersionRelease = 5;
  481. ////////////////////////////////////////////////////////////////////////////////
  482. //
  483. // Misc constants and support types
  484. //
  485. ////////////////////////////////////////////////////////////////////////////////
  486. const
  487. GIFMaxColors = 256; // Max number of colors supported by GIF
  488. // Don't bother changing this value!
  489. BitmapAllocationThreshold = 500000; // Bitmap pixel count limit at which
  490. // a newly allocated bitmap will be
  491. // converted to 1 bit format before
  492. // being resized and converted to 8 bit.
  493. var
  494. {$IFDEF FAST_AS_HELL}
  495. GIFDelayExp: integer = 10; // Delay multiplier in mS.
  496. {$ELSE}
  497. GIFDelayExp: integer = 12; // Delay multiplier in mS. Tweaked.
  498. {$ENDIF}
  499. // * GIFDelayExp:
  500. // The following delay values should all
  501. // be multiplied by this value to
  502. // calculate the effective time (in mS).
  503. // According to the GIF specs, this
  504. // value should be 10.
  505. // Since our paint routines are much
  506. // faster than Mozilla's, you might need
  507. // to increase this value if your
  508. // animations loops too fast. The
  509. // optimal value is impossible to
  510. // determine since it depends on the
  511. // speed of the CPU, the viceo card,
  512. // memory and many other factors.
  513. GIFDefaultDelay: integer = 10; // * GIFDefaultDelay:
  514. // Default animation delay.
  515. // This value is used if no GCE is
  516. // defined.
  517. // (10 = 100 mS)
  518. {$IFDEF FAST_AS_HELL}
  519. GIFMinimumDelay: integer = 1; // Minimum delay (from Mozilla source).
  520. // (1 = 10 mS)
  521. {$ELSE}
  522. GIFMinimumDelay: integer = 3; // Minimum delay - Tweaked.
  523. {$ENDIF}
  524. // * GIFMinimumDelay:
  525. // The minumum delay used in the Mozilla
  526. // source is 10mS. This corresponds to a
  527. // value of 1. However, since our paint
  528. // routines are much faster than
  529. // Mozilla's, a value of 3 or 4 gives
  530. // better results.
  531. GIFMaximumDelay: integer = 1000; // * GIFMaximumDelay:
  532. // Maximum delay when painter is running
  533. // in main thread (goAsync is not set).
  534. // This value guarantees that a very
  535. // long and slow GIF does not hang the
  536. // system.
  537. // (1000 = 10000 mS = 10 Seconds)
  538. type
  539. TGIFVersion = (gvUnknown, gv87a, gv89a);
  540. TGIFVersionRec = array[0..2] of AnsiChar;
  541. const
  542. GIFVersions : array[gv87a..gv89a] of TGIFVersionRec = ('87a', '89a');
  543. type
  544. // TGIFImage mostly throws exceptions of type GIFException
  545. GIFException = class(EInvalidGraphic);
  546. // Severity level as indicated in the Warning methods and the OnWarning event
  547. TGIFSeverity = (gsInfo, gsWarning, gsError);
  548. ////////////////////////////////////////////////////////////////////////////////
  549. //
  550. // Delphi 2.x support
  551. //
  552. ////////////////////////////////////////////////////////////////////////////////
  553. {$IFDEF VER9x}
  554. // Delphi 2 doesn't support TBitmap.PixelFormat
  555. {$DEFINE PIXELFORMAT_TOO_SLOW}
  556. type
  557. // TThreadList from Delphi 3 classes.pas
  558. TThreadList = class
  559. private
  560. FList: TList;
  561. FLock: TRTLCriticalSection;
  562. public
  563. constructor Create;
  564. destructor Destroy; override;
  565. procedure Add(Item: Pointer);
  566. procedure Clear;
  567. function LockList: TList;
  568. procedure Remove(Item: Pointer);
  569. procedure UnlockList;
  570. end;
  571. // From Delphi 3 sysutils.pas
  572. EOutOfMemory = class(Exception);
  573. // From Delphi 3 classes.pas
  574. EOutOfResources = class(EOutOfMemory);
  575. // From Delphi 3 windows.pas
  576. PMaxLogPalette = ^TMaxLogPalette;
  577. TMaxLogPalette = packed record
  578. palVersion: Word;
  579. palNumEntries: Word;
  580. palPalEntry: array [Byte] of TPaletteEntry;
  581. end; { TMaxLogPalette }
  582. // From Delphi 3 graphics.pas. Used by the D3 TGraphic class.
  583. TProgressStage = (psStarting, psRunning, psEnding);
  584. TProgressEvent = procedure (Sender: TObject; Stage: TProgressStage;
  585. PercentDone: Byte; RedrawNow: Boolean; const R: TRect; const Msg: string) of object;
  586. // From Delphi 3 windows.pas
  587. PRGBTriple = ^TRGBTriple;
  588. {$ENDIF}
  589. ////////////////////////////////////////////////////////////////////////////////
  590. //
  591. // Forward declarations
  592. //
  593. ////////////////////////////////////////////////////////////////////////////////
  594. type
  595. TGIFImage = class;
  596. TGIFSubImage = class;
  597. ////////////////////////////////////////////////////////////////////////////////
  598. //
  599. // TGIFItem
  600. //
  601. ////////////////////////////////////////////////////////////////////////////////
  602. TGIFItem = class(TPersistent)
  603. private
  604. FGIFImage: TGIFImage;
  605. protected
  606. function GetVersion: TGIFVersion; virtual;
  607. procedure Warning(Severity: TGIFSeverity; Message: string); virtual;
  608. public
  609. constructor Create(GIFImage: TGIFImage); virtual;
  610. procedure SaveToStream(Stream: TStream); virtual; abstract;
  611. procedure LoadFromStream(Stream: TStream); virtual; abstract;
  612. procedure SaveToFile(const Filename: string); virtual;
  613. procedure LoadFromFile(const Filename: string); virtual;
  614. property Version: TGIFVersion read GetVersion;
  615. property Image: TGIFImage read FGIFImage;
  616. end;
  617. ////////////////////////////////////////////////////////////////////////////////
  618. //
  619. // TGIFList
  620. //
  621. ////////////////////////////////////////////////////////////////////////////////
  622. TGIFList = class(TPersistent)
  623. private
  624. FItems: TList;
  625. FImage: TGIFImage;
  626. protected
  627. function GetItem(Index: Integer): TGIFItem;
  628. procedure SetItem(Index: Integer; Item: TGIFItem);
  629. function GetCount: Integer;
  630. procedure Warning(Severity: TGIFSeverity; Message: string); virtual;
  631. public
  632. constructor Create(Image: TGIFImage);
  633. destructor Destroy; override;
  634. function Add(Item: TGIFItem): Integer;
  635. procedure Clear;
  636. procedure Delete(Index: Integer);
  637. procedure Exchange(Index1, Index2: Integer);
  638. function First: TGIFItem;
  639. function IndexOf(Item: TGIFItem): Integer;
  640. procedure Insert(Index: Integer; Item: TGIFItem);
  641. function Last: TGIFItem;
  642. procedure Move(CurIndex, NewIndex: Integer);
  643. function Remove(Item: TGIFItem): Integer;
  644. procedure SaveToStream(Stream: TStream); virtual;
  645. procedure LoadFromStream(Stream: TStream; Parent: TObject); virtual; abstract;
  646. property Items[Index: Integer]: TGIFItem read GetItem write SetItem; default;
  647. property Count: Integer read GetCount;
  648. property List: TList read FItems;
  649. property Image: TGIFImage read FImage;
  650. end;
  651. ////////////////////////////////////////////////////////////////////////////////
  652. //
  653. // TGIFColorMap
  654. //
  655. ////////////////////////////////////////////////////////////////////////////////
  656. // One way to do it:
  657. // TBaseColor = (bcRed, bcGreen, bcBlue);
  658. // TGIFColor = array[bcRed..bcBlue] of BYTE;
  659. // Another way:
  660. TGIFColor = packed record
  661. Red: byte;
  662. Green: byte;
  663. Blue: byte;
  664. end;
  665. TColorMap = packed array[0..GIFMaxColors-1] of TGIFColor;
  666. PColorMap = ^TColorMap;
  667. TUsageCount = record
  668. Count : integer; // # of pixels using color index
  669. Index : integer; // Color index
  670. end;
  671. TColormapHistogram = array[0..255] of TUsageCount;
  672. TColormapReverse = array[0..255] of byte;
  673. TGIFColorMap = class(TPersistent)
  674. private
  675. FColorMap : PColorMap;
  676. FCount : integer;
  677. FCapacity : integer;
  678. FOptimized : boolean;
  679. protected
  680. function GetColor(Index: integer): TColor;
  681. procedure SetColor(Index: integer; Value: TColor);
  682. function GetBitsPerPixel: integer;
  683. function DoOptimize: boolean;
  684. procedure SetCapacity(Size: integer);
  685. procedure Warning(Severity: TGIFSeverity; Message: string); virtual; abstract;
  686. procedure BuildHistogram(var Histogram: TColormapHistogram); virtual; abstract;
  687. procedure MapImages(var Map: TColormapReverse); virtual; abstract;
  688. public
  689. constructor Create;
  690. destructor Destroy; override;
  691. class function Color2RGB(Color: TColor): TGIFColor;
  692. class function RGB2Color(Color: TGIFColor): TColor;
  693. procedure SaveToStream(Stream: TStream);
  694. procedure LoadFromStream(Stream: TStream; Count: integer);
  695. procedure Assign(Source: TPersistent); override;
  696. function IndexOf(Color: TColor): integer;
  697. function Add(Color: TColor): integer;
  698. function AddUnique(Color: TColor): integer;
  699. procedure Delete(Index: integer);
  700. procedure Clear;
  701. function Optimize: boolean; virtual; abstract;
  702. procedure Changed; virtual; abstract;
  703. procedure ImportPalette(Palette: HPalette);
  704. procedure ImportColorTable(Pal: pointer; Count: integer);
  705. procedure ImportDIBColors(Handle: HDC);
  706. procedure ImportColorMap(Map: TColorMap; Count: integer);
  707. function ExportPalette: HPalette;
  708. property Colors[Index: integer]: TColor read GetColor write SetColor; default;
  709. property Data: PColorMap read FColorMap;
  710. property Count: integer read FCount;
  711. property Optimized: boolean read FOptimized write FOptimized;
  712. property BitsPerPixel: integer read GetBitsPerPixel;
  713. end;
  714. ////////////////////////////////////////////////////////////////////////////////
  715. //
  716. // TGIFHeader
  717. //
  718. ////////////////////////////////////////////////////////////////////////////////
  719. TLogicalScreenDescriptor = packed record
  720. ScreenWidth: word; { logical screen width }
  721. ScreenHeight: word; { logical screen height }
  722. PackedFields: byte; { packed fields }
  723. BackgroundColorIndex: byte; { index to global color table }
  724. AspectRatio: byte; { actual ratio = (AspectRatio + 15) / 64 }
  725. end;
  726. TGIFHeader = class(TGIFItem)
  727. private
  728. FLogicalScreenDescriptor: TLogicalScreenDescriptor;
  729. FColorMap : TGIFColorMap;
  730. procedure Prepare;
  731. protected
  732. function GetVersion: TGIFVersion; override;
  733. function GetBackgroundColor: TColor;
  734. procedure SetBackgroundColor(Color: TColor);
  735. procedure SetBackgroundColorIndex(Index: BYTE);
  736. function GetBitsPerPixel: integer;
  737. function GetColorResolution: integer;
  738. public
  739. constructor Create(GIFImage: TGIFImage); override;
  740. destructor Destroy; override;
  741. procedure Assign(Source: TPersistent); override;
  742. procedure SaveToStream(Stream: TStream); override;
  743. procedure LoadFromStream(Stream: TStream); override;
  744. procedure Clear;
  745. property Version: TGIFVersion read GetVersion;
  746. property Width: WORD read FLogicalScreenDescriptor.ScreenWidth
  747. write FLogicalScreenDescriptor.ScreenWidth;
  748. property Height: WORD read FLogicalScreenDescriptor.ScreenHeight
  749. write FLogicalScreenDescriptor.Screenheight;
  750. property BackgroundColorIndex: BYTE read FLogicalScreenDescriptor.BackgroundColorIndex
  751. write SetBackgroundColorIndex;
  752. property BackgroundColor: TColor read GetBackgroundColor
  753. write SetBackgroundColor;
  754. property AspectRatio: BYTE read FLogicalScreenDescriptor.AspectRatio
  755. write FLogicalScreenDescriptor.AspectRatio;
  756. property ColorMap: TGIFColorMap read FColorMap;
  757. property BitsPerPixel: integer read GetBitsPerPixel;
  758. property ColorResolution: integer read GetColorResolution;
  759. end;
  760. ////////////////////////////////////////////////////////////////////////////////
  761. //
  762. // TGIFExtension
  763. //
  764. ////////////////////////////////////////////////////////////////////////////////
  765. TGIFExtensionType = BYTE;
  766. TGIFExtension = class;
  767. TGIFExtensionClass = class of TGIFExtension;
  768. TGIFGraphicControlExtension = class;
  769. TGIFExtension = class(TGIFItem)
  770. private
  771. FSubImage: TGIFSubImage;
  772. protected
  773. function GetExtensionType: TGIFExtensionType; virtual; abstract;
  774. function GetVersion: TGIFVersion; override;
  775. function DoReadFromStream(Stream: TStream): TGIFExtensionType;
  776. class procedure RegisterExtension(elabel: BYTE; eClass: TGIFExtensionClass);
  777. class function FindExtension(Stream: TStream): TGIFExtensionClass;
  778. class function FindSubExtension(Stream: TStream): TGIFExtensionClass; virtual;
  779. public
  780. // Ignore compiler warning about hiding base class constructor
  781. constructor Create(ASubImage: TGIFSubImage); {$IFDEF VER12_PLUS} reintroduce; {$ENDIF} virtual;
  782. destructor Destroy; override;
  783. procedure SaveToStream(Stream: TStream); override;
  784. procedure LoadFromStream(Stream: TStream); override;
  785. property ExtensionType: TGIFExtensionType read GetExtensionType;
  786. property SubImage: TGIFSubImage read FSubImage;
  787. end;
  788. ////////////////////////////////////////////////////////////////////////////////
  789. //
  790. // TGIFSubImage
  791. //
  792. ////////////////////////////////////////////////////////////////////////////////
  793. TGIFExtensionList = class(TGIFList)
  794. protected
  795. function GetExtension(Index: Integer): TGIFExtension;
  796. procedure SetExtension(Index: Integer; Extension: TGIFExtension);
  797. public
  798. procedure LoadFromStream(Stream: TStream; Parent: TObject); override;
  799. property Extensions[Index: Integer]: TGIFExtension read GetExtension write SetExtension; default;
  800. end;
  801. TImageDescriptor = packed record
  802. Separator: byte; { fixed value of ImageSeparator }
  803. Left: word; { Column in pixels in respect to left edge of logical screen }
  804. Top: word; { row in pixels in respect to top of logical screen }
  805. Width: word; { width of image in pixels }
  806. Height: word; { height of image in pixels }
  807. PackedFields: byte; { Bit fields }
  808. end;
  809. TGIFSubImage = class(TGIFItem)
  810. private
  811. FBitmap : TBitmap;
  812. FMask : HBitmap;
  813. FNeedMask : boolean;
  814. FLocalPalette : HPalette;
  815. FData : PAnsiChar;
  816. FDataSize : integer;
  817. FColorMap : TGIFColorMap;
  818. FImageDescriptor : TImageDescriptor;
  819. FExtensions : TGIFExtensionList;
  820. FTransparent : boolean;
  821. FGCE : TGIFGraphicControlExtension;
  822. procedure Prepare;
  823. procedure Compress(Stream: TStream);
  824. procedure Decompress(Stream: TStream);
  825. protected
  826. function GetVersion: TGIFVersion; override;
  827. function GetInterlaced: boolean;
  828. procedure SetInterlaced(Value: boolean);
  829. function GetColorResolution: integer;
  830. function GetBitsPerPixel: integer;
  831. procedure AssignTo(Dest: TPersistent); override;
  832. function DoGetBitmap: TBitmap;
  833. function DoGetDitherBitmap: TBitmap;
  834. function GetBitmap: TBitmap;
  835. procedure SetBitmap(Value: TBitmap);
  836. procedure FreeMask;
  837. function GetEmpty: Boolean;
  838. function GetPalette: HPALETTE;
  839. procedure SetPalette(Value: HPalette);
  840. function GetActiveColorMap: TGIFColorMap;
  841. function GetBoundsRect: TRect;
  842. procedure SetBoundsRect(const Value: TRect);
  843. procedure DoSetBounds(ALeft, ATop, AWidth, AHeight: integer);
  844. function GetClientRect: TRect;
  845. function GetPixel(x, y: integer): BYTE;
  846. // 2006.10.09 ->
  847. procedure SetPixel(x, y: integer; Value: BYTE);
  848. // 2006.10.09 <-
  849. function GetScanline(y: integer): pointer;
  850. procedure NewBitmap;
  851. procedure FreeBitmap;
  852. procedure NewImage;
  853. procedure FreeImage;
  854. procedure NeedImage;
  855. function ScaleRect(DestRect: TRect): TRect;
  856. function HasMask: boolean;
  857. function GetBounds(Index: integer): WORD;
  858. procedure SetBounds(Index: integer; Value: WORD);
  859. function GetHasBitmap: boolean;
  860. procedure SetHasBitmap(Value: boolean);
  861. public
  862. constructor Create(GIFImage: TGIFImage); override;
  863. destructor Destroy; override;
  864. procedure Clear;
  865. procedure SaveToStream(Stream: TStream); override;
  866. procedure LoadFromStream(Stream: TStream); override;
  867. procedure Assign(Source: TPersistent); override;
  868. procedure Draw(ACanvas: TCanvas; const Rect: TRect;
  869. DoTransparent, DoTile: boolean);
  870. procedure StretchDraw(ACanvas: TCanvas; const Rect: TRect;
  871. DoTransparent, DoTile: boolean);
  872. procedure Crop;
  873. procedure Merge(Previous: TGIFSubImage);
  874. property HasBitmap: boolean read GetHasBitmap write SetHasBitmap;
  875. property Left: WORD index 1 read GetBounds write SetBounds;
  876. property Top: WORD index 2 read GetBounds write SetBounds;
  877. property Width: WORD index 3 read GetBounds write SetBounds;
  878. property Height: WORD index 4 read GetBounds write SetBounds;
  879. property BoundsRect: TRect read GetBoundsRect write SetBoundsRect;
  880. property ClientRect: TRect read GetClientRect;
  881. property Interlaced: boolean read GetInterlaced write SetInterlaced;
  882. property ColorMap: TGIFColorMap read FColorMap;
  883. property ActiveColorMap: TGIFColorMap read GetActiveColorMap;
  884. property Data: PAnsiChar read FData;
  885. property DataSize: integer read FDataSize;
  886. property Extensions: TGIFExtensionList read FExtensions;
  887. property Version: TGIFVersion read GetVersion;
  888. property ColorResolution: integer read GetColorResolution;
  889. property BitsPerPixel: integer read GetBitsPerPixel;
  890. property Bitmap: TBitmap read GetBitmap write SetBitmap;
  891. property Mask: HBitmap read FMask;
  892. property Palette: HPALETTE read GetPalette write SetPalette;
  893. property Empty: boolean read GetEmpty;
  894. property Transparent: boolean read FTransparent;
  895. property GraphicControlExtension: TGIFGraphicControlExtension read FGCE;
  896. // 2006.10.09 ->
  897. // property Pixels[x, y: integer]: BYTE read GetPixel;
  898. property Pixels[x, y: integer]: BYTE read GetPixel write SetPixel;
  899. // 2006.10.09 <-
  900. property Scanline[y: integer]: pointer read GetScanline;
  901. end;
  902. ////////////////////////////////////////////////////////////////////////////////
  903. //
  904. // TGIFTrailer
  905. //
  906. ////////////////////////////////////////////////////////////////////////////////
  907. TGIFTrailer = class(TGIFItem)
  908. procedure SaveToStream(Stream: TStream); override;
  909. procedure LoadFromStream(Stream: TStream); override;
  910. end;
  911. ////////////////////////////////////////////////////////////////////////////////
  912. //
  913. // TGIFGraphicControlExtension
  914. //
  915. ////////////////////////////////////////////////////////////////////////////////
  916. // Graphic Control Extension block a.k.a GCE
  917. TGIFGCERec = packed record
  918. BlockSize: byte; { should be 4 }
  919. PackedFields: Byte;
  920. DelayTime: Word; { in centiseconds }
  921. TransparentColorIndex: Byte;
  922. Terminator: Byte;
  923. end;
  924. TDisposalMethod = (dmNone, dmNoDisposal, dmBackground, dmPrevious);
  925. TGIFGraphicControlExtension = class(TGIFExtension)
  926. private
  927. FGCExtension: TGIFGCERec;
  928. protected
  929. function GetExtensionType: TGIFExtensionType; override;
  930. function GetTransparent: boolean;
  931. procedure SetTransparent(Value: boolean);
  932. function GetTransparentColor: TColor;
  933. procedure SetTransparentColor(Color: TColor);
  934. function GetTransparentColorIndex: BYTE;
  935. procedure SetTransparentColorIndex(Value: BYTE);
  936. function GetDelay: WORD;
  937. procedure SetDelay(Value: WORD);
  938. function GetUserInput: boolean;
  939. procedure SetUserInput(Value: boolean);
  940. function GetDisposal: TDisposalMethod;
  941. procedure SetDisposal(Value: TDisposalMethod);
  942. public
  943. constructor Create(ASubImage: TGIFSubImage); override;
  944. destructor Destroy; override;
  945. procedure SaveToStream(Stream: TStream); override;
  946. procedure LoadFromStream(Stream: TStream); override;
  947. property Delay: WORD read GetDelay write SetDelay;
  948. property Transparent: boolean read GetTransparent write SetTransparent;
  949. property TransparentColorIndex: BYTE read GetTransparentColorIndex
  950. write SetTransparentColorIndex;
  951. property TransparentColor: TColor read GetTransparentColor write SetTransparentColor;
  952. property UserInput: boolean read GetUserInput write SetUserInput;
  953. property Disposal: TDisposalMethod read GetDisposal write SetDisposal;
  954. end;
  955. ////////////////////////////////////////////////////////////////////////////////
  956. //
  957. // TGIFTextExtension
  958. //
  959. ////////////////////////////////////////////////////////////////////////////////
  960. TGIFPlainTextExtensionRec = packed record
  961. BlockSize: byte; { should be 12 }
  962. Left, Top, Width, Height: Word;
  963. CellWidth, CellHeight: Byte;
  964. TextFGColorIndex,
  965. TextBGColorIndex: Byte;
  966. end;
  967. TGIFTextExtension = class(TGIFExtension)
  968. private
  969. FText : TStrings;
  970. FPlainTextExtension : TGIFPlainTextExtensionRec;
  971. protected
  972. function GetExtensionType: TGIFExtensionType; override;
  973. function GetForegroundColor: TColor;
  974. procedure SetForegroundColor(Color: TColor);
  975. function GetBackgroundColor: TColor;
  976. procedure SetBackgroundColor(Color: TColor);
  977. function GetBounds(Index: integer): WORD;
  978. procedure SetBounds(Index: integer; Value: WORD);
  979. function GetCharWidthHeight(Index: integer): BYTE;
  980. procedure SetCharWidthHeight(Index: integer; Value: BYTE);
  981. function GetColorIndex(Index: integer): BYTE;
  982. procedure SetColorIndex(Index: integer; Value: BYTE);
  983. public
  984. constructor Create(ASubImage: TGIFSubImage); override;
  985. destructor Destroy; override;
  986. procedure SaveToStream(Stream: TStream); override;
  987. procedure LoadFromStream(Stream: TStream); override;
  988. property Left: WORD index 1 read GetBounds write SetBounds;
  989. property Top: WORD index 2 read GetBounds write SetBounds;
  990. property GridWidth: WORD index 3 read GetBounds write SetBounds;
  991. property GridHeight: WORD index 4 read GetBounds write SetBounds;
  992. property CharWidth: BYTE index 1 read GetCharWidthHeight write SetCharWidthHeight;
  993. property CharHeight: BYTE index 2 read GetCharWidthHeight write SetCharWidthHeight;
  994. property ForegroundColorIndex: BYTE index 1 read GetColorIndex write SetColorIndex;
  995. property ForegroundColor: TColor read GetForegroundColor;
  996. property BackgroundColorIndex: BYTE index 2 read GetColorIndex write SetColorIndex;
  997. property BackgroundColor: TColor read GetBackgroundColor;
  998. property Text: TStrings read FText write FText;
  999. end;
  1000. ////////////////////////////////////////////////////////////////////////////////
  1001. //
  1002. // TGIFCommentExtension
  1003. //
  1004. ////////////////////////////////////////////////////////////////////////////////
  1005. TGIFCommentExtension = class(TGIFExtension)
  1006. private
  1007. FText : TStrings;
  1008. protected
  1009. function GetExtensionType: TGIFExtensionType; override;
  1010. public
  1011. constructor Create(ASubImage: TGIFSubImage); override;
  1012. destructor Destroy; override;
  1013. procedure SaveToStream(Stream: TStream); override;
  1014. procedure LoadFromStream(Stream: TStream); override;
  1015. property Text: TStrings read FText;
  1016. end;
  1017. ////////////////////////////////////////////////////////////////////////////////
  1018. //
  1019. // TGIFApplicationExtension
  1020. //
  1021. ////////////////////////////////////////////////////////////////////////////////
  1022. TGIFIdentifierCode = array[0..7] of AnsiChar;
  1023. TGIFAuthenticationCode = array[0..2] of AnsiChar;
  1024. TGIFApplicationRec = packed record
  1025. Identifier : TGIFIdentifierCode;
  1026. Authentication : TGIFAuthenticationCode;
  1027. end;
  1028. TGIFApplicationExtension = class;
  1029. TGIFAppExtensionClass = class of TGIFApplicationExtension;
  1030. TGIFApplicationExtension = class(TGIFExtension)
  1031. private
  1032. FIdent : TGIFApplicationRec;
  1033. function GetAuthentication: AnsiString;
  1034. function GetIdentifier: AnsiString;
  1035. protected
  1036. function GetExtensionType: TGIFExtensionType; override;
  1037. procedure SetAuthentication(const Value: AnsiString);
  1038. procedure SetIdentifier(const Value: AnsiString);
  1039. procedure SaveData(Stream: TStream); virtual; abstract;
  1040. procedure LoadData(Stream: TStream); virtual; abstract;
  1041. public
  1042. constructor Create(ASubImage: TGIFSubImage); override;
  1043. destructor Destroy; override;
  1044. procedure SaveToStream(Stream: TStream); override;
  1045. procedure LoadFromStream(Stream: TStream); override;
  1046. class procedure RegisterExtension(eIdent: TGIFApplicationRec; eClass: TGIFAppExtensionClass);
  1047. class function FindSubExtension(Stream: TStream): TGIFExtensionClass; override;
  1048. property Identifier: AnsiString read GetIdentifier write SetIdentifier;
  1049. property Authentication: AnsiString read GetAuthentication write SetAuthentication;
  1050. end;
  1051. ////////////////////////////////////////////////////////////////////////////////
  1052. //
  1053. // TGIFUnknownAppExtension
  1054. //
  1055. ////////////////////////////////////////////////////////////////////////////////
  1056. TGIFBlock = class(TObject)
  1057. private
  1058. FSize : BYTE;
  1059. FData : pointer;
  1060. public
  1061. constructor Create(ASize: integer);
  1062. destructor Destroy; override;
  1063. procedure SaveToStream(Stream: TStream);
  1064. procedure LoadFromStream(Stream: TStream);
  1065. property Size: BYTE read FSize;
  1066. property Data: pointer read FData;
  1067. end;
  1068. TGIFUnknownAppExtension = class(TGIFApplicationExtension)
  1069. private
  1070. FBlocks : TList;
  1071. protected
  1072. procedure SaveData(Stream: TStream); override;
  1073. procedure LoadData(Stream: TStream); override;
  1074. public
  1075. constructor Create(ASubImage: TGIFSubImage); override;
  1076. destructor Destroy; override;
  1077. property Blocks: TList read FBlocks;
  1078. end;
  1079. ////////////////////////////////////////////////////////////////////////////////
  1080. //
  1081. // TGIFAppExtNSLoop
  1082. //
  1083. ////////////////////////////////////////////////////////////////////////////////
  1084. TGIFAppExtNSLoop = class(TGIFApplicationExtension)
  1085. private
  1086. FLoops : WORD;
  1087. FBufferSize : DWORD;
  1088. protected
  1089. procedure SaveData(Stream: TStream); override;
  1090. procedure LoadData(Stream: TStream); override;
  1091. public
  1092. constructor Create(ASubImage: TGIFSubImage); override;
  1093. property Loops: WORD read FLoops write FLoops;
  1094. property BufferSize: DWORD read FBufferSize write FBufferSize;
  1095. end;
  1096. ////////////////////////////////////////////////////////////////////////////////
  1097. //
  1098. // TGIFImage
  1099. //
  1100. ////////////////////////////////////////////////////////////////////////////////
  1101. TGIFImageList = class(TGIFList)
  1102. protected
  1103. function GetImage(Index: Integer): TGIFSubImage;
  1104. procedure SetImage(Index: Integer; SubImage: TGIFSubImage);
  1105. public
  1106. procedure LoadFromStream(Stream: TStream; Parent: TObject); override;
  1107. procedure SaveToStream(Stream: TStream); override;
  1108. property SubImages[Index: Integer]: TGIFSubImage read GetImage write SetImage; default;
  1109. end;
  1110. // Compression algorithms
  1111. TGIFCompression =
  1112. (gcLZW, // Normal LZW compression
  1113. gcRLE // GIF compatible RLE compression
  1114. );
  1115. // Color reduction methods
  1116. TColorReduction =
  1117. (rmNone, // Do not perform color reduction
  1118. rmWindows20, // Reduce to the Windows 20 color system palette
  1119. rmWindows256, // Reduce to the Windows 256 color halftone palette (Only works in 256 color display mode)
  1120. rmWindowsGray, // Reduce to the Windows 4 grayscale colors
  1121. rmMonochrome, // Reduce to a black/white monochrome palette
  1122. rmGrayScale, // Reduce to a uniform 256 shade grayscale palette
  1123. rmNetscape, // Reduce to the Netscape 216 color palette
  1124. rmQuantize, // Reduce to optimal 2^n color palette
  1125. rmQuantizeWindows, // Reduce to optimal 256 color windows palette
  1126. rmPalette // Reduce to custom palette
  1127. );
  1128. TDitherMode =
  1129. (dmNearest, // Nearest color matching w/o error correction
  1130. dmFloydSteinberg, // Floyd Steinberg Error Diffusion dithering
  1131. dmStucki, // Stucki Error Diffusion dithering
  1132. dmSierra, // Sierra Error Diffusion dithering
  1133. dmJaJuNI, // Jarvis, Judice & Ninke Error Diffusion dithering
  1134. dmSteveArche, // Stevenson & Arche Error Diffusion dithering
  1135. dmBurkes // Burkes Error Diffusion dithering
  1136. // dmOrdered, // Ordered dither
  1137. );
  1138. // Optimization options
  1139. TGIFOptimizeOption =
  1140. (ooCrop, // Crop animated GIF frames
  1141. ooMerge, // Merge pixels of same color
  1142. ooCleanup, // Remove comments and application extensions
  1143. ooColorMap, // Sort color map by usage and remove unused entries
  1144. ooReduceColors // Reduce color depth ***NOT IMPLEMENTED***
  1145. );
  1146. TGIFOptimizeOptions = set of TGIFOptimizeOption;
  1147. TGIFDrawOption =
  1148. (goAsync, // Asyncronous draws (paint in thread)
  1149. goTransparent, // Transparent draws
  1150. goAnimate, // Animate draws
  1151. goLoop, // Loop animations
  1152. goLoopContinously, // Ignore loop count and loop forever
  1153. goValidateCanvas, // Validate canvas in threaded paint ***NOT IMPLEMENTED***
  1154. goDirectDraw, // Draw() directly on canvas
  1155. goClearOnLoop, // Clear animation on loop
  1156. goTile, // Tiled display
  1157. goDither, // Dither to Netscape palette
  1158. goAutoDither // Only dither on 256 color systems
  1159. );
  1160. TGIFDrawOptions = set of TGIFDrawOption;
  1161. // Note: if goAsync is not set then goDirectDraw should be set. Otherwise
  1162. // the image will not be displayed.
  1163. PGIFPainter = ^TGIFPainter;
  1164. TGIFPainter = class(TThread)
  1165. private
  1166. FImage : TGIFImage; // The TGIFImage that owns this painter
  1167. FCanvas : TCanvas; // Destination canvas
  1168. FRect : TRect; // Destination rect
  1169. FDrawOptions : TGIFDrawOptions;// Paint options
  1170. FAnimationSpeed : integer; // Animation speed %
  1171. FActiveImage : integer; // Current frame
  1172. Disposal , // Used by synchronized paint
  1173. OldDisposal : TDisposalMethod;// Used by synchronized paint
  1174. BackupBuffer : TBitmap; // Used by synchronized paint
  1175. FrameBuffer : TBitmap; // Used by synchronized paint
  1176. Background : TBitmap; // Used by synchronized paint
  1177. ValidateDC : HDC;
  1178. DoRestart : boolean; // Flag used to restart animation
  1179. FStarted : boolean; // Flag used to signal start of paint
  1180. PainterRef : PGIFPainter; // Pointer to var referencing painter
  1181. FEventHandle : THandle; // Animation delay event
  1182. ExceptObject : Exception; // Eaten exception
  1183. ExceptAddress : pointer; // Eaten exceptions address
  1184. FEvent : TNotifyEvent; // Used by synchronized events
  1185. FOnStartPaint : TNotifyEvent;
  1186. FOnPaint : TNotifyEvent;
  1187. FOnAfterPaint : TNotifyEvent;
  1188. FOnLoop : TNotifyEvent;
  1189. FOnEndPaint : TNotifyEvent;
  1190. procedure DoOnTerminate(Sender: TObject);// Sync. shutdown procedure
  1191. procedure DoSynchronize(Method: TThreadMethod);// Conditional sync stub
  1192. {$ifdef SERIALIZE_RENDER}
  1193. procedure PrefetchBitmap; // Sync. bitmap prefetch
  1194. {$endif}
  1195. procedure DoPaintFrame; // Sync. buffered paint procedure
  1196. procedure DoPaint; // Sync. paint procedure
  1197. procedure DoEvent;
  1198. procedure SetActiveImage(const Value: integer);// Sync. event procedure
  1199. protected
  1200. procedure Execute; override;
  1201. procedure SetAnimationSpeed(Value: integer);
  1202. public
  1203. constructor Create(AImage: TGIFImage; ACanvas: TCanvas; ARect: TRect;
  1204. Options: TGIFDrawOptions);
  1205. constructor CreateRef(Painter: PGIFPainter; AImage: TGIFImage; ACanvas: TCanvas; ARect: TRect;
  1206. Options: TGIFDrawOptions);
  1207. destructor Destroy; override;
  1208. procedure Start;
  1209. procedure Stop;
  1210. procedure Restart;
  1211. property Image: TGIFImage read FImage;
  1212. property Canvas: TCanvas read FCanvas;
  1213. property Rect: TRect read FRect write FRect;
  1214. property DrawOptions: TGIFDrawOptions read FDrawOptions write FDrawOptions;
  1215. property AnimationSpeed: integer read FAnimationSpeed write SetAnimationSpeed;
  1216. property Started: boolean read FStarted;
  1217. property ActiveImage: integer read FActiveImage write SetActiveImage;
  1218. property OnStartPaint: TNotifyEvent read FOnStartPaint write FOnStartPaint;
  1219. property OnPaint: TNotifyEvent read FOnPaint write FOnPaint;
  1220. property OnAfterPaint: TNotifyEvent read FOnAfterPaint write FOnAfterPaint;
  1221. property OnLoop: TNotifyEvent read FOnLoop write FOnLoop;
  1222. property OnEndPaint : TNotifyEvent read FOnEndPaint write FOnEndPaint ;
  1223. property EventHandle: THandle read FEventHandle;
  1224. end;
  1225. TGIFWarning = procedure(Sender: TObject; Severity: TGIFSeverity; Message: string) of object;
  1226. TGIFImage = class(TGraphic)
  1227. private
  1228. IsDrawing : Boolean;
  1229. IsInsideGetPalette : boolean;
  1230. FImages : TGIFImageList;
  1231. FHeader : TGIFHeader;
  1232. FGlobalPalette : HPalette;
  1233. FPainters : TThreadList;
  1234. FDrawOptions : TGIFDrawOptions;
  1235. FColorReduction : TColorReduction;
  1236. FReductionBits : integer;
  1237. FDitherMode : TDitherMode;
  1238. FCompression : TGIFCompression;
  1239. FOnWarning : TGIFWarning;
  1240. FBitmap : TBitmap;
  1241. FDrawPainter : TGIFPainter;
  1242. FThreadPriority : TThreadPriority;
  1243. FAnimationSpeed : integer;
  1244. FForceFrame: Integer; // 2004.03.09
  1245. FDrawBackgroundColor: TColor;
  1246. FOnStartPaint : TNotifyEvent;
  1247. FOnPaint : TNotifyEvent;
  1248. FOnAfterPaint : TNotifyEvent;
  1249. FOnLoop : TNotifyEvent;
  1250. FOnEndPaint : TNotifyEvent;
  1251. {$IFDEF VER9x}
  1252. FPaletteModified : Boolean;
  1253. FOnProgress : TProgressEvent;
  1254. {$ENDIF}
  1255. function GetAnimate: Boolean; // 2002.07.07
  1256. procedure SetAnimate(const Value: Boolean); // 2002.07.07
  1257. procedure SetForceFrame(const Value: Integer); // 2004.03.09
  1258. protected
  1259. // Obsolete: procedure Changed(Sender: TObject); {$IFDEF VER9x} virtual; {$ELSE} override; {$ENDIF}
  1260. function GetHeight: Integer; override;
  1261. procedure SetHeight(Value: Integer); override;
  1262. function GetWidth: Integer; override;
  1263. procedure SetWidth(Value: Integer); override;
  1264. procedure AssignTo(Dest: TPersistent); override;
  1265. function InternalPaint(Painter: PGIFPainter; ACanvas: TCanvas; const Rect: TRect; Options: TGIFDrawOptions): TGIFPainter;
  1266. procedure Draw(ACanvas: TCanvas; const Rect: TRect); override;
  1267. function Equals(Graphic: TGraphic): Boolean; override;
  1268. function GetPalette: HPALETTE; {$IFDEF VER9x} virtual; {$ELSE} override; {$ENDIF}
  1269. procedure SetPalette(Value: HPalette); {$IFDEF VER9x} virtual; {$ELSE} override; {$ENDIF}
  1270. function GetEmpty: Boolean; override;
  1271. procedure WriteData(Stream: TStream); override;
  1272. function GetIsTransparent: Boolean;
  1273. function GetVersion: TGIFVersion;
  1274. function GetColorResolution: integer;
  1275. function GetBitsPerPixel: integer;
  1276. function GetBackgroundColorIndex: BYTE;
  1277. procedure SetBackgroundColorIndex(const Value: BYTE);
  1278. function GetBackgroundColor: TColor;
  1279. procedure SetBackgroundColor(const Value: TColor);
  1280. function GetAspectRatio: BYTE;
  1281. procedure SetAspectRatio(const Value: BYTE);
  1282. procedure SetDrawOptions(Value: TGIFDrawOptions);
  1283. procedure SetAnimationSpeed(Value: integer);
  1284. procedure SetReductionBits(Value: integer);
  1285. procedure NewImage;
  1286. function GetBitmap: TBitmap;
  1287. function NewBitmap: TBitmap;
  1288. procedure FreeBitmap;
  1289. function GetColorMap: TGIFColorMap;
  1290. function GetDoDither: boolean;
  1291. property DrawPainter: TGIFPainter read FDrawPainter; // Extremely volatile
  1292. property DoDither: boolean read GetDoDither;
  1293. {$IFDEF VER9x}
  1294. procedure Progress(Sender: TObject; Stage: TProgressStage;
  1295. PercentDone: Byte; RedrawNow: Boolean; const R: TRect; const Msg: string); dynamic;
  1296. {$ENDIF}
  1297. {$IFDEF FIXHEADER_WIDTHHEIGHT_SILENT}
  1298. procedure FixHeaderWidthHeight; // 2006.07.09
  1299. {$ENDIF}
  1300. public
  1301. constructor Create; override;
  1302. destructor Destroy; override;
  1303. procedure SaveToStream(Stream: TStream); override;
  1304. procedure LoadFromStream(Stream: TStream); override;
  1305. procedure LoadFromResourceName(Instance: THandle; const ResName: String); // 2002.07.07
  1306. function Add(Source: TPersistent): integer;
  1307. procedure Pack;
  1308. procedure OptimizeColorMap;
  1309. procedure Optimize(Options: TGIFOptimizeOptions;
  1310. ColorReduction: TColorReduction; DitherMode: TDitherMode;
  1311. ReductionBits: integer);
  1312. procedure Clear;
  1313. procedure StopDraw;
  1314. function Paint(ACanvas: TCanvas; const Rect: TRect; Options: TGIFDrawOptions): TGIFPainter;
  1315. procedure PaintStart;
  1316. procedure PaintPause;
  1317. procedure PaintStop;
  1318. procedure PaintResume;
  1319. procedure PaintRestart;
  1320. procedure Warning(Sender: TObject; Severity: TGIFSeverity; Message: string); virtual;
  1321. procedure Assign(Source: TPersistent); override;
  1322. procedure LoadFromClipboardFormat(AFormat: Word; AData: THandle;
  1323. APalette: HPALETTE); override;
  1324. procedure SaveToClipboardFormat(var AFormat: Word; var AData: THandle;
  1325. var APalette: HPALETTE); override;
  1326. property GlobalColorMap: TGIFColorMap read GetColorMap;
  1327. property Version: TGIFVersion read GetVersion;
  1328. property Images: TGIFImageList read FImages;
  1329. property ColorResolution: integer read GetColorResolution;
  1330. property BitsPerPixel: integer read GetBitsPerPixel;
  1331. property BackgroundColorIndex: BYTE read GetBackgroundColorIndex write SetBackgroundColorIndex;
  1332. property BackgroundColor: TColor read GetBackgroundColor write SetBackgroundColor;
  1333. property AspectRatio: BYTE read GetAspectRatio write SetAspectRatio;
  1334. property Header: TGIFHeader read FHeader; // ***OBSOLETE***
  1335. property IsTransparent: boolean read GetIsTransparent;
  1336. property DrawOptions: TGIFDrawOptions read FDrawOptions write SetDrawOptions;
  1337. property DrawBackgroundColor: TColor read FDrawBackgroundColor write FDrawBackgroundColor;
  1338. property ColorReduction: TColorReduction read FColorReduction write FColorReduction;
  1339. property ReductionBits: integer read FReductionBits write SetReductionBits;
  1340. property DitherMode: TDitherMode read FDitherMode write FDitherMode;
  1341. property Compression: TGIFCompression read FCompression write FCompression;
  1342. property AnimationSpeed: integer read FAnimationSpeed write SetAnimationSpeed;
  1343. property Animate: Boolean read GetAnimate write SetAnimate; // 2002.07.07
  1344. property ForceFrame: Integer read FForceFrame write SetForceFrame; // 2004.03.09
  1345. property Painters: TThreadList read FPainters;
  1346. property ThreadPriority: TThreadPriority read FThreadPriority write FThreadPriority;
  1347. property Bitmap: TBitmap read GetBitmap; // Volatile - beware!
  1348. property OnWarning: TGIFWarning read FOnWarning write FOnWarning;
  1349. property OnStartPaint: TNotifyEvent read FOnStartPaint write FOnStartPaint;
  1350. property OnPaint: TNotifyEvent read FOnPaint write FOnPaint;
  1351. property OnAfterPaint: TNotifyEvent read FOnAfterPaint write FOnAfterPaint;
  1352. property OnLoop: TNotifyEvent read FOnLoop write FOnLoop;
  1353. property OnEndPaint : TNotifyEvent read FOnEndPaint write FOnEndPaint ;
  1354. {$IFDEF VER9x}
  1355. property Palette: HPALETTE read GetPalette write SetPalette;
  1356. property PaletteModified: Boolean read FPaletteModified write FPaletteModified;
  1357. property OnProgress: TProgressEvent read FOnProgress write FOnProgress;
  1358. {$ENDIF}
  1359. end;
  1360. ////////////////////////////////////////////////////////////////////////////////
  1361. //
  1362. // Utility routines
  1363. //
  1364. ////////////////////////////////////////////////////////////////////////////////
  1365. // WebPalette creates a 216 color uniform palette a.k.a. the Netscape Palette
  1366. function WebPalette: HPalette;
  1367. // ReduceColors