PngExplorerMain.pas 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732
  1. unit PNGExplorerMain;
  2. interface
  3. uses
  4. Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  5. Menus, ComCtrls, StdCtrls, ExtCtrls, ToolWin, ActnList, StdActns,
  6. ImgList, System.ImageList, System.Actions,
  7. GR32,
  8. GR32_PortableNetworkGraphic,
  9. GR32_PNG,
  10. GR32_Image;
  11. type
  12. TMyPortableNetworkGraphic = class(TPortableNetworkGraphic32);
  13. TFmPngExplorer = class(TForm)
  14. AcEditCopy: TEditCopy;
  15. AcEditCut: TEditCut;
  16. AcEditPaste: TEditPaste;
  17. AcEditUndo: TEditUndo;
  18. AcFileExit: TFileExit;
  19. AcFileOpen: TFileOpen;
  20. AcFileSaveAs: TFileSaveAs;
  21. ActionList: TActionList;
  22. CoolBar: TCoolBar;
  23. ImgView32: TImgView32;
  24. ListView: TListView;
  25. MainMenu: TMainMenu;
  26. MIAbout: TMenuItem;
  27. MiCopy: TMenuItem;
  28. MICut: TMenuItem;
  29. MIEdit: TMenuItem;
  30. MIExit: TMenuItem;
  31. MIFile: TMenuItem;
  32. MIHelp: TMenuItem;
  33. MIOpen: TMenuItem;
  34. MIPaste: TMenuItem;
  35. MISave: TMenuItem;
  36. MISaveAs: TMenuItem;
  37. MIStatusBar: TMenuItem;
  38. MIToolbar: TMenuItem;
  39. MIUndo: TMenuItem;
  40. MIView: TMenuItem;
  41. N1: TMenuItem;
  42. N2: TMenuItem;
  43. N3: TMenuItem;
  44. PnMain: TPanel;
  45. PnPaintBox: TPanel;
  46. SpHorizontal: TSplitter;
  47. SpVertical: TSplitter;
  48. StatusBar: TStatusBar;
  49. TbCopy: TToolButton;
  50. TbCut: TToolButton;
  51. TbOpen: TToolButton;
  52. TbPaste: TToolButton;
  53. TbSplit1: TToolButton;
  54. TbSplit2: TToolButton;
  55. ToolBar: TToolBar;
  56. ToolbarImages: TImageList;
  57. TreeView: TTreeView;
  58. procedure FormCreate(Sender: TObject);
  59. procedure FormDestroy(Sender: TObject);
  60. procedure FormShow(Sender: TObject);
  61. procedure AcFileOpenAccept(Sender: TObject);
  62. procedure MIStatusBarClick(Sender: TObject);
  63. procedure MIToolbarClick(Sender: TObject);
  64. procedure ShowHint(Sender: TObject);
  65. procedure TreeViewChange(Sender: TObject; Node: TTreeNode);
  66. procedure TreeViewMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
  67. private
  68. FPngFile : TMyPortableNetworkGraphic;
  69. procedure InitializeDefaultListView;
  70. procedure PNGChanged;
  71. protected
  72. procedure ListViewColumns(Columns: Array of string);
  73. procedure ListViewData(Strings: Array of string);
  74. procedure DisplayHeaderChunk(HeaderChunk: TChunkPngImageHeader);
  75. procedure DisplayPaletteChunk(PaletteChunk: TChunkPngPalette);
  76. procedure DisplayChromaticitiesChunk(ChromaChunk: TChunkPngPrimaryChromaticities);
  77. procedure DisplayGammaChunk(GammaChunk: TChunkPngGamma);
  78. procedure DisplayPhysicalDimensionsChunk(PhysicalDimensionsChunk: TChunkPngPhysicalPixelDimensions);
  79. procedure DisplayTextChunk(TextChunk: TCustomChunkPngText);
  80. {$if defined(TChunkPngSuggestedPalette)} // TChunkPngSuggestedPalette is incomplete and has been disabled
  81. procedure DisplaySuggestedPaletteChunk(SuggestedPaletteChunk: TChunkPngSuggestedPalette);
  82. {$ifend}
  83. procedure DisplaySignificantBitsChunk(SignificantBitsChunk: TChunkPngSignificantBits);
  84. procedure DisplayStandardColorSpaceRGBChunk(StandardColorSpaceRGB: TChunkPngStandardColorSpaceRGB);
  85. procedure DisplayBackgroundColorChunk(BackgroundColor: TChunkPngBackgroundColor);
  86. procedure DisplayTransparencyChunk(TransparencyChunk: TChunkPngTransparency);
  87. procedure DisplayHistogramChunk(HistogramChunk: TChunkPngImageHistogram);
  88. procedure DisplayTimeChunk(TimeChunk: TChunkPngTime);
  89. public
  90. procedure LoadFromFile(Filename: TFileName);
  91. procedure LoadFromStream(Stream: TStream);
  92. end;
  93. var
  94. FmPngExplorer: TFmPngExplorer;
  95. implementation
  96. {$R *.dfm}
  97. uses
  98. Inifiles, Math, Types;
  99. { TFmPngExplorer }
  100. procedure TFmPngExplorer.FormCreate(Sender: TObject);
  101. begin
  102. Application.OnHint := ShowHint;
  103. FPngFile := TMyPortableNetworkGraphic.Create;
  104. end;
  105. procedure TFmPngExplorer.FormDestroy(Sender: TObject);
  106. begin
  107. // free png file
  108. FreeAndNil(FPngFile);
  109. end;
  110. procedure TFmPngExplorer.FormShow(Sender: TObject);
  111. begin
  112. if FileExists(ParamStr(1)) then
  113. LoadFromFile(ParamStr(1));
  114. end;
  115. procedure TFmPngExplorer.InitializeDefaultListView;
  116. begin
  117. // add columns
  118. ListViewColumns(['Name', 'Value']);
  119. end;
  120. procedure TFmPngExplorer.ListViewColumns(Columns: array of string);
  121. var
  122. ColumnIndex : Integer;
  123. begin
  124. // clear list view
  125. ListView.Clear;
  126. // clear columns
  127. ListView.Columns.Clear;
  128. // add column
  129. for ColumnIndex := 0 to Length(Columns) - 1 do
  130. with ListView.Columns.Add do
  131. begin
  132. Caption := Columns[ColumnIndex];
  133. Width := Min(256, (ListView.Width - 16) div (Length(Columns)));
  134. MinWidth := 64;
  135. AutoSize := True;
  136. end;
  137. end;
  138. procedure TFmPngExplorer.ListViewData(Strings: array of string);
  139. var
  140. ValueIndex : Integer;
  141. begin
  142. // add data
  143. with ListView.Items.Add do
  144. begin
  145. Caption := Strings[0];
  146. for ValueIndex := 1 to Length(Strings) - 1 do
  147. SubItems.Add(Strings[ValueIndex]);
  148. end;
  149. end;
  150. procedure TFmPngExplorer.ShowHint(Sender: TObject);
  151. begin
  152. if Length(Application.Hint) > 0 then
  153. begin
  154. StatusBar.SimplePanel := True;
  155. StatusBar.SimpleText := Application.Hint;
  156. end
  157. else
  158. StatusBar.SimplePanel := False;
  159. end;
  160. procedure TFmPngExplorer.AcFileOpenAccept(Sender: TObject);
  161. begin
  162. LoadFromFile(AcFileOpen.Dialog.Filename);
  163. end;
  164. procedure TFmPngExplorer.MIStatusBarClick(Sender: TObject);
  165. begin
  166. MIStatusBar.Checked := not MIStatusBar.Checked;
  167. StatusBar.Visible := MIStatusBar.Checked;
  168. end;
  169. procedure TFmPngExplorer.MIToolbarClick(Sender: TObject);
  170. begin
  171. MIToolbar.Checked := not MIToolbar.Checked;
  172. CoolBar.Visible := MIToolbar.Checked;
  173. end;
  174. procedure TFmPngExplorer.DisplayHeaderChunk(HeaderChunk: TChunkPngImageHeader);
  175. begin
  176. with HeaderChunk do
  177. begin
  178. InitializeDefaultListView;
  179. ListViewData(['Width', IntToStr(Width)]);
  180. ListViewData(['Height', IntToStr(Height)]);
  181. ListViewData(['Bit Depth', IntToStr(BitDepth)]);
  182. ListViewData(['Color Type', ColorTypeToString(ColorType)]);
  183. ListViewData(['Compression Method', IntToStr(CompressionMethod)]);
  184. ListViewData(['Filter Method', 'Adaptive']);
  185. ListViewData(['Interlace Method', InterlaceMethodToString(InterlaceMethod)]);
  186. ListViewData(['HasPallette', BoolToStr(HasPalette)]);
  187. ListView.BringToFront;
  188. end;
  189. end;
  190. procedure TFmPngExplorer.DisplayPaletteChunk(PaletteChunk: TChunkPngPalette);
  191. var
  192. Index : Integer;
  193. begin
  194. with PaletteChunk do
  195. begin
  196. InitializeDefaultListView;
  197. ListViewColumns(['Index', 'Color']);
  198. for Index := 0 to Count - 1 do
  199. with PaletteEntry[Index] do
  200. ListViewData([IntToStr(Index), '#' + IntToHex(
  201. Integer(R shl 16 + G shl 8 + B), 6)]);
  202. ListView.BringToFront;
  203. end;
  204. end;
  205. procedure TFmPngExplorer.DisplayGammaChunk(GammaChunk: TChunkPngGamma);
  206. begin
  207. with GammaChunk do
  208. begin
  209. InitializeDefaultListView;
  210. ListViewData(['Gamma', FloatToStr(GammaAsSingle)]);
  211. ListView.BringToFront;
  212. end;
  213. end;
  214. procedure TFmPngExplorer.DisplayHistogramChunk(HistogramChunk: TChunkPngImageHistogram);
  215. var
  216. Index : Integer;
  217. begin
  218. with HistogramChunk do
  219. begin
  220. ListViewColumns(['Index', 'Frequency']);
  221. for Index := 0 to Count - 1 do
  222. ListViewData([IntToStr(Index), IntToStr(Frequency[Index])]);
  223. ListView.BringToFront;
  224. end;
  225. end;
  226. {$if defined(TChunkPngSuggestedPalette)}
  227. procedure TFmPngExplorer.DisplaySuggestedPaletteChunk(SuggestedPaletteChunk: TChunkPngSuggestedPalette);
  228. begin
  229. with SuggestedPaletteChunk do
  230. begin
  231. InitializeDefaultListView;
  232. // ListViewData(['Palette Entries', IntToStr(Count)]);
  233. ListView.BringToFront;
  234. end;
  235. end;
  236. {$ifend}
  237. procedure TFmPngExplorer.DisplaySignificantBitsChunk(
  238. SignificantBitsChunk: TChunkPngSignificantBits);
  239. begin
  240. with SignificantBitsChunk do
  241. begin
  242. InitializeDefaultListView;
  243. if SignificantBits is TPngSignificantBitsFormat0 then
  244. ListViewData(['Greyscale Bits',
  245. IntToStr(TPngSignificantBitsFormat0(SignificantBits).GrayBits)])
  246. else if SignificantBits is TPngSignificantBitsFormat23 then
  247. begin
  248. ListViewData(['Red Bits',
  249. IntToStr(TPngSignificantBitsFormat23(SignificantBits).RedBits)]);
  250. ListViewData(['Green Bits',
  251. IntToStr(TPngSignificantBitsFormat23(SignificantBits).GreenBits)]);
  252. ListViewData(['Blue Bits',
  253. IntToStr(TPngSignificantBitsFormat23(SignificantBits).BlueBits)]);
  254. end
  255. else if SignificantBits is TPngSignificantBitsFormat4 then
  256. begin
  257. ListViewData(['Greyscale Bits',
  258. IntToStr(TPngSignificantBitsFormat4(SignificantBits).GrayBits)]);
  259. ListViewData(['Alpha Bits',
  260. IntToStr(TPngSignificantBitsFormat4(SignificantBits).AlphaBits)]);
  261. end
  262. else if SignificantBits is TPngSignificantBitsFormat6 then
  263. begin
  264. ListViewData(['Red Bits',
  265. IntToStr(TPngSignificantBitsFormat6(SignificantBits).RedBits)]);
  266. ListViewData(['Green Bits',
  267. IntToStr(TPngSignificantBitsFormat6(SignificantBits).GreenBits)]);
  268. ListViewData(['Blue Bits',
  269. IntToStr(TPngSignificantBitsFormat6(SignificantBits).BlueBits)]);
  270. ListViewData(['Alpha Bits',
  271. IntToStr(TPngSignificantBitsFormat6(SignificantBits).AlphaBits)]);
  272. end;
  273. ListView.BringToFront;
  274. end;
  275. end;
  276. procedure TFmPngExplorer.DisplayStandardColorSpaceRGBChunk(
  277. StandardColorSpaceRGB: TChunkPngStandardColorSpaceRGB);
  278. begin
  279. with StandardColorSpaceRGB do
  280. begin
  281. InitializeDefaultListView;
  282. case RenderingIntent of
  283. 0 : ListViewData(['Rendering Indent', 'Perceptual']);
  284. 1 : ListViewData(['Rendering Indent', 'Relative Colorimetric']);
  285. 2 : ListViewData(['Rendering Indent', 'Saturation']);
  286. 3 : ListViewData(['Rendering Indent', 'Absolute Colorimetric']);
  287. else
  288. ListViewData(['Rendering Indent', IntToStr(RenderingIntent)]);
  289. end;
  290. ListView.BringToFront;
  291. end;
  292. end;
  293. procedure TFmPngExplorer.DisplayTextChunk(TextChunk: TCustomChunkPngText);
  294. begin
  295. with TextChunk do
  296. begin
  297. InitializeDefaultListView;
  298. ListViewData([string(Keyword), string(Text)]);
  299. ListView.BringToFront;
  300. end;
  301. end;
  302. procedure TFmPngExplorer.DisplayTimeChunk(TimeChunk: TChunkPngTime);
  303. begin
  304. with TimeChunk do
  305. begin
  306. InitializeDefaultListView;
  307. ListViewData(['Time', DateTimeToStr(ModifiedDateTime)]);
  308. ListView.BringToFront;
  309. end;
  310. end;
  311. procedure TFmPngExplorer.DisplayTransparencyChunk(
  312. TransparencyChunk: TChunkPngTransparency);
  313. var
  314. Index : Integer;
  315. begin
  316. with TransparencyChunk do
  317. begin
  318. InitializeDefaultListView;
  319. if Transparency is TPngTransparencyFormat0 then
  320. ListViewData(['Grey Sample Value',
  321. IntToStr(TPngTransparencyFormat0(Transparency).GraySampleValue)])
  322. else if Transparency is TPngTransparencyFormat2 then
  323. begin
  324. ListViewData(['Red Sample Value',
  325. IntToStr(TPngTransparencyFormat2(Transparency).RedSampleValue)]);
  326. ListViewData(['Blue Sample Value',
  327. IntToStr(TPngTransparencyFormat2(Transparency).BlueSampleValue)]);
  328. ListViewData(['Green Sample Value',
  329. IntToStr(TPngTransparencyFormat2(Transparency).GreenSampleValue)]);
  330. end
  331. else if Transparency is TPngTransparencyFormat3 then
  332. for Index := 0 to TPngTransparencyFormat3(Transparency).Count - 1 do
  333. ListViewData(['Index ' + IntToStr(Index),
  334. IntToStr(TPngTransparencyFormat3(Transparency).Transparency[Index])]);
  335. ListView.BringToFront;
  336. end;
  337. end;
  338. procedure TFmPngExplorer.DisplayPhysicalDimensionsChunk(PhysicalDimensionsChunk: TChunkPngPhysicalPixelDimensions);
  339. begin
  340. with PhysicalDimensionsChunk do
  341. begin
  342. InitializeDefaultListView;
  343. ListViewData(['Pixels per unit X', IntToStr(PixelsPerUnitX)]);
  344. ListViewData(['Pixels per unit Y', IntToStr(PixelsPerUnitY)]);
  345. ListView.BringToFront;
  346. end;
  347. end;
  348. procedure TFmPngExplorer.DisplayBackgroundColorChunk(
  349. BackgroundColor: TChunkPngBackgroundColor);
  350. begin
  351. with BackgroundColor do
  352. begin
  353. InitializeDefaultListView;
  354. if Background is TPngBackgroundColorFormat04 then
  355. ListViewData(['Grey',
  356. IntToStr(TPngBackgroundColorFormat04(Background).GraySampleValue)])
  357. else if Background is TPngBackgroundColorFormat26 then
  358. begin
  359. ListViewData(['Red',
  360. IntToStr(TPngBackgroundColorFormat26(Background).RedSampleValue)]);
  361. ListViewData(['Blue',
  362. IntToStr(TPngBackgroundColorFormat26(Background).BlueSampleValue)]);
  363. ListViewData(['Green',
  364. IntToStr(TPngBackgroundColorFormat26(Background).GreenSampleValue)]);
  365. end
  366. else if Background is TPngBackgroundColorFormat3 then
  367. ListViewData(['Palette Index',
  368. IntToStr(TPngBackgroundColorFormat3(Background).PaletteIndex)]);
  369. ListView.BringToFront;
  370. end;
  371. end;
  372. procedure TFmPngExplorer.DisplayChromaticitiesChunk(ChromaChunk: TChunkPngPrimaryChromaticities);
  373. begin
  374. with ChromaChunk do
  375. begin
  376. InitializeDefaultListView;
  377. ListViewData(['White X', FloatToStr(WhiteXAsSingle)]);
  378. ListViewData(['White Y', FloatToStr(WhiteYAsSingle)]);
  379. ListViewData(['Red X', FloatToStr(RedXAsSingle)]);
  380. ListViewData(['Red Y', FloatToStr(RedYAsSingle)]);
  381. ListViewData(['Green X', FloatToStr(GreenXAsSingle)]);
  382. ListViewData(['Green Y', FloatToStr(GreenYAsSingle)]);
  383. ListViewData(['Blue X', FloatToStr(BlueXAsSingle)]);
  384. ListViewData(['Blue Y', FloatToStr(BlueYAsSingle)]);
  385. ListView.BringToFront;
  386. end;
  387. end;
  388. procedure TFmPngExplorer.TreeViewMouseMove(Sender: TObject; Shift: TShiftState; X,
  389. Y: Integer);
  390. var
  391. MouseOverNode : TTreeNode;
  392. ParentNode : TTreeNode;
  393. begin
  394. MouseOverNode := TreeView.GetNodeAt(X, Y);
  395. // status bar
  396. if Assigned(MouseOverNode) and Assigned(MouseOverNode.Data) then
  397. begin
  398. ParentNode := MouseOverNode;
  399. while not (TObject(ParentNode.Data) is TCustomDefinedChunk) do
  400. begin
  401. ParentNode := ParentNode.Parent;
  402. if not Assigned(ParentNode.Data)
  403. then Exit;
  404. end;
  405. if TObject(ParentNode.Data) is TCustomDefinedChunkWithHeader then
  406. with TCustomDefinedChunkWithHeader(ParentNode.Data) do
  407. begin
  408. // StatusBar.SimpleText := 'Table ID: ' + TableType;
  409. end;
  410. end;
  411. end;
  412. procedure TFmPngExplorer.TreeViewChange(Sender: TObject; Node: TTreeNode);
  413. begin
  414. Node.Expanded := True;
  415. if Assigned(Node.Data) then
  416. begin
  417. // display chunk size
  418. if TObject(Node.Data) is TCustomDefinedChunk then
  419. StatusBar.SimpleText := 'Chunk Size: ' + IntToStr(
  420. TCustomDefinedChunk(Node.Data).ChunkSize);
  421. // PNG HeaderChunk chunk
  422. if TObject(Node.Data) is TChunkPngImageHeader then
  423. DisplayHeaderChunk(TChunkPngImageHeader(Node.Data))
  424. else if TObject(Node.Data) is TChunkPngPalette then
  425. DisplayPaletteChunk(TChunkPngPalette(Node.Data))
  426. else if TObject(Node.Data) is TChunkPngGamma then
  427. DisplayGammaChunk(TChunkPngGamma(Node.Data))
  428. else if TObject(Node.Data) is TChunkPngTime then
  429. DisplayTimeChunk(TChunkPngTime(Node.Data))
  430. (*
  431. else if TObject(Node.Data) is TChunkPngPhysicalScale then
  432. DisplayPhysicalScaleChunk(TChunkPngPhysicalScale(Node.Data))
  433. *)
  434. else if TObject(Node.Data) is TCustomChunkPngText then
  435. DisplayTextChunk(TCustomChunkPngText(Node.Data))
  436. else if TObject(Node.Data) is TChunkPngStandardColorSpaceRGB then
  437. DisplayStandardColorSpaceRGBChunk(TChunkPngStandardColorSpaceRGB(Node.Data))
  438. else if TObject(Node.Data) is TChunkPngImageHistogram then
  439. DisplayHistogramChunk(TChunkPngImageHistogram(Node.Data))
  440. else if TObject(Node.Data) is TChunkPngBackgroundColor then
  441. DisplayBackgroundColorChunk(TChunkPngBackgroundColor(Node.Data))
  442. {$if defined(TChunkPngSuggestedPalette)}
  443. else if TObject(Node.Data) is TChunkPngSuggestedPalette then
  444. DisplaySuggestedPaletteChunk(TChunkPngSuggestedPalette(Node.Data))
  445. {$ifend}
  446. else if TObject(Node.Data) is TChunkPngPrimaryChromaticities then
  447. DisplayChromaticitiesChunk(TChunkPngPrimaryChromaticities(Node.Data))
  448. else if TObject(Node.Data) is TChunkPngPhysicalPixelDimensions then
  449. DisplayPhysicalDimensionsChunk(TChunkPngPhysicalPixelDimensions(Node.Data))
  450. else if TObject(Node.Data) is TChunkPngSignificantBits then
  451. DisplaySignificantBitsChunk(TChunkPngSignificantBits(Node.Data))
  452. else if TObject(Node.Data) is TChunkPngTransparency then
  453. DisplayTransparencyChunk(TChunkPngTransparency(Node.Data))
  454. else
  455. // other unregistered chunks
  456. if TObject(Node.Data) is TCustomChunk then
  457. with TCustomChunk(Node.Data) do
  458. begin
  459. InitializeDefaultListView;
  460. ListViewData(['Chunk Name', string(ChunkNameAsString)]);
  461. ListViewData(['Chunk Size', IntToStr(ChunkSize)]);
  462. ListView.BringToFront;
  463. end;
  464. PnPaintBox.Visible := False;
  465. SpVertical.Visible := False;
  466. end
  467. else
  468. begin
  469. PnPaintBox.Visible := True;
  470. SpVertical.Visible := True;
  471. end;
  472. end;
  473. procedure TFmPngExplorer.PNGChanged;
  474. var
  475. Index : Integer;
  476. begin
  477. with FPngFile, TreeView do
  478. begin
  479. // begin update
  480. Items.BeginUpdate;
  481. // add PNG Header chunk
  482. Items.AddChildObject(Items[0], 'IHDR', FImageHeader);
  483. // eventually add Palette chunk
  484. if Assigned(FPaletteChunk) then
  485. Items.AddChildObject(Items[0], 'PLTE', FPaletteChunk);
  486. // eventually add PNG Gamma chunk
  487. if Assigned(FGammaChunk) then
  488. Items.AddChildObject(Items[0], 'gAMA', FGammaChunk);
  489. // eventually add PNG Time chunk
  490. if Assigned(FTimeChunk) then
  491. Items.AddChildObject(Items[0], 'tIME', FTimeChunk);
  492. // eventually add PNG Background chunk
  493. if Assigned(FBackgroundChunk) then
  494. Items.AddChildObject(Items[0], 'bKGD', FBackgroundChunk);
  495. // eventually add PNG Significant Bits chunk
  496. if Assigned(FSignificantBits) then
  497. Items.AddChildObject(Items[0], 'sBIT', FSignificantBits);
  498. // eventually add PNG Transparency chunk
  499. if Assigned(FTransparencyChunk) then
  500. Items.AddChildObject(Items[0], 'tRNS', FTransparencyChunk);
  501. // eventually add PNG Chroma chunk
  502. if Assigned(FChromaChunk) then
  503. Items.AddChildObject(Items[0], 'cHRM', FChromaChunk);
  504. // eventually add PNG Physical Pixel Dimensions chunk
  505. if Assigned(FPhysicalDimensions) then
  506. Items.AddChildObject(Items[0], 'pHYs', FPhysicalDimensions);
  507. // eventually add additional chunks
  508. for Index := 0 to FAdditionalChunkList.Count - 1 do
  509. begin
  510. if FAdditionalChunkList[Index] is TCustomChunk then
  511. Items.AddChildObject(Items[0],
  512. string(TCustomChunk(FAdditionalChunkList[Index]).ChunkNameAsString),
  513. FAdditionalChunkList[Index])
  514. end;
  515. // end update
  516. Items.EndUpdate;
  517. // assign png file
  518. ImgView32.Bitmap.Assign(FPngFile);
  519. // expand tree
  520. Items[0].Expanded := True;
  521. end;
  522. end;
  523. procedure TFmPngExplorer.LoadFromFile(Filename: TFileName);
  524. var
  525. Start, Stop, Freq : Int64;
  526. MemoryFileStream : TMemoryStream;
  527. begin
  528. if FileExists(FileName) then
  529. begin
  530. // initialize listview
  531. InitializeDefaultListView;
  532. // create temporary memory strem
  533. MemoryFileStream := TMemoryStream.Create;
  534. try
  535. // query start
  536. QueryPerformanceCounter(Start);
  537. // load data from file
  538. MemoryFileStream.LoadFromFile(Filename);
  539. // query stop
  540. QueryPerformanceCounter(Stop);
  541. // query performance frequency
  542. QueryPerformanceFrequency(Freq);
  543. // add loading TimeChunk
  544. ListViewData(['loading time', FloatToStrF((Stop - Start) * 1000 / Freq, ffGeneral, 4, 4) + ' ms']);
  545. // query start
  546. QueryPerformanceCounter(Start);
  547. // load PNG file
  548. FPngFile.LoadFromStream(MemoryFileStream);
  549. // query stop
  550. QueryPerformanceCounter(Stop);
  551. // query performance frequency
  552. QueryPerformanceFrequency(Freq);
  553. // add loading TimeChunk
  554. ListViewData(['interpreting time', FloatToStrF((Stop - Start) * 1000 / Freq, ffGeneral, 4, 4) + ' ms']);
  555. finally
  556. FreeAndNil(MemoryFileStream);
  557. end;
  558. // clear existing items on treeview
  559. TreeView.Items.Clear;
  560. // add root item on treeview
  561. TreeView.Items.AddChild(nil, ExtractFileName(FileName));
  562. // query start
  563. QueryPerformanceCounter(Start);
  564. PNGChanged;
  565. // query stop
  566. QueryPerformanceCounter(Stop);
  567. // add building tree TimeChunk
  568. ListViewData(['building tree time', FloatToStrF((Stop - Start) * 1000 / Freq, ffGeneral, 4, 4) + ' ms']);
  569. ListView.BringToFront;
  570. Caption := 'PNG Explorer [' + ExtractFileName(Filename) + ']';
  571. end
  572. else
  573. raise Exception.Create('File does not exists');
  574. end;
  575. procedure TFmPngExplorer.LoadFromStream(Stream: TStream);
  576. var
  577. Start, Stop, Freq : Int64;
  578. begin
  579. // reset stream position
  580. Stream.Position := 0;
  581. // query start
  582. QueryPerformanceCounter(Start);
  583. // load PNG file
  584. FPNGFile.LoadFromStream(Stream);
  585. // query stop
  586. QueryPerformanceCounter(Stop);
  587. // query performance frequency
  588. QueryPerformanceFrequency(Freq);
  589. // initialize listview
  590. InitializeDefaultListView;
  591. // add loading TimeChunk
  592. ListViewData(['loading time', FloatToStrF((Stop - Start) * 1000 / Freq, ffGeneral, 4, 4) + ' ms']);
  593. // clear existing items on treeview
  594. TreeView.Items.Clear;
  595. // add root item on treeview
  596. TreeView.Items.AddChild(nil, '(internal PNG)');
  597. // query start
  598. QueryPerformanceCounter(Start);
  599. PNGChanged;
  600. // query stop
  601. QueryPerformanceCounter(Stop);
  602. // add building tree TimeChunk
  603. ListViewData(['building tree time', FloatToStrF((Stop - Start) * 1000 / Freq, ffGeneral, 4, 4) + ' ms']);
  604. ListView.BringToFront;
  605. // change caption
  606. Caption := 'PNG Explorer';
  607. end;
  608. end.