fpimage.inc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 2003 by the Free Pascal development team
  5. TFPCustomImage implementation.
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. { TFPCustomImage }
  13. constructor TFPCustomImage.create (AWidth,AHeight:integer);
  14. begin
  15. inherited create;
  16. FExtra := TStringList.Create;
  17. FWidth := 0;
  18. FHeight := 0;
  19. FPalette := nil;
  20. SetSize (AWidth,AHeight);
  21. end;
  22. destructor TFPCustomImage.destroy;
  23. begin
  24. FExtra.Free;
  25. if assigned (FPalette) then
  26. FPalette.Free;
  27. inherited;
  28. end;
  29. procedure TFPCustomImage.LoadFromStream (Str:TStream; Handler:TFPCustomImagereader);
  30. begin
  31. Handler.ImageRead (Str, self);
  32. end;
  33. procedure TFPCustomImage.LoadFromFile (const filename:String; Handler:TFPCustomImageReader);
  34. var
  35. fs : TStream;
  36. begin
  37. if FileExists (filename) then
  38. begin
  39. fs := TFileStream.Create (filename, fmOpenRead);
  40. try
  41. LoadFromStream (fs, handler);
  42. finally
  43. fs.Free;
  44. end;
  45. end
  46. else
  47. FPImgError (StrNoFile, [filename]);
  48. end;
  49. procedure TFPCustomImage.SaveToStream (Str:TStream; Handler:TFPCustomImageWriter);
  50. begin
  51. Handler.ImageWrite (Str, Self);
  52. end;
  53. procedure TFPCustomImage.SaveToFile (const filename:String; Handler:TFPCustomImageWriter);
  54. var
  55. fs : TStream;
  56. begin
  57. fs := TFileStream.Create (filename, fmCreate);
  58. try
  59. SaveToStream (fs, handler);
  60. finally
  61. fs.Free;
  62. end
  63. end;
  64. procedure TFPCustomImage.SaveToFile (const filename:String);
  65. var e,s : string;
  66. r : integer;
  67. f : TFileStream;
  68. h : TFPCustomImageWriterClass;
  69. Writer : TFPCustomImageWriter;
  70. d : TIHData;
  71. Msg : string;
  72. begin
  73. e := lowercase (ExtractFileExt(filename));
  74. if (e <> '') and (e[1] = '.') then
  75. delete (e,1,1);
  76. with ImageHandlers do
  77. begin
  78. r := count-1;
  79. s := e + ';';
  80. while (r >= 0) do
  81. begin
  82. d := GetData(r);
  83. if (pos(s,d.Fextention+';') <> 0) then
  84. try
  85. h := d.FWriter;
  86. if assigned (h) then
  87. begin
  88. Writer := h.Create;
  89. SaveTofile (filename, Writer);
  90. break;
  91. end;
  92. except
  93. on e : exception do
  94. Msg := e.message;
  95. end;
  96. dec (r);
  97. end
  98. end;
  99. if (Msg<>'') then
  100. FPImgError (StrWriteWithError, [Msg]);
  101. end;
  102. procedure TFPCustomImage.LoadFromStream (Str:TStream);
  103. var r : integer;
  104. h : TFPCustomImageReaderClass;
  105. reader : TFPCustomImageReader;
  106. msg : string;
  107. d : TIHData;
  108. begin
  109. with ImageHandlers do
  110. try
  111. r := count-1;
  112. while (r >= 0) do
  113. begin
  114. d := GetData(r);
  115. if assigned (d) then
  116. h := d.FReader;
  117. if assigned (h) then
  118. begin
  119. reader := h.Create;
  120. with reader do
  121. try
  122. if CheckContents (str) then
  123. try
  124. FStream := str;
  125. FImage := self;
  126. InternalRead (str, self);
  127. break;
  128. except
  129. on e : exception do
  130. msg := e.message;
  131. end;
  132. finally
  133. Free;
  134. str.seek (soFromBeginning, 0);
  135. end;
  136. end;
  137. dec (r);
  138. end;
  139. except
  140. on e : exception do
  141. FPImgError (StrCantDetermineType, [e.message]);
  142. end;
  143. if r < 0 then
  144. if msg = '' then
  145. FPImgError (StrNoCorrectReaderFound)
  146. else
  147. FPImgError (StrReadWithError, [Msg]);
  148. end;
  149. procedure TFPCustomImage.LoadFromFile (const filename:String);
  150. var e,s : string;
  151. r : integer;
  152. f : TFileStream;
  153. h : TFPCustomImageReaderClass;
  154. reader : TFPCustomImageReader;
  155. d : TIHData;
  156. Msg : string;
  157. begin
  158. e := lowercase (ExtractFileExt(filename));
  159. if (e <> '') and (e[1] = '.') then
  160. delete (e,1,1);
  161. with ImageHandlers do
  162. begin
  163. r := count-1;
  164. s := e + ';';
  165. while (r >= 0) do
  166. begin
  167. d := GetData(r);
  168. if (pos(s,d.Fextention+';') <> 0) then
  169. try
  170. h := d.FReader;
  171. if assigned (h) then
  172. begin
  173. reader := h.Create;
  174. loadfromfile (filename, reader);
  175. break;
  176. end;
  177. except
  178. on e : exception do
  179. Msg := e.message;
  180. end;
  181. dec (r);
  182. end
  183. end;
  184. if Msg = '' then
  185. begin
  186. if r < 0 then
  187. begin
  188. f := TFileStream.Create (filename, fmOpenRead);
  189. try
  190. LoadFromStream (f);
  191. finally
  192. f.Free;
  193. end;
  194. end;
  195. end
  196. else
  197. FPImgError (StrReadWithError, [Msg]);
  198. end;
  199. procedure TFPCustomImage.SetHeight (Value : integer);
  200. begin
  201. if Value <> FHeight then
  202. SetSize (FWidth, Value);
  203. end;
  204. procedure TFPCustomImage.SetWidth (Value : integer);
  205. begin
  206. if Value <> FWidth then
  207. SetSize (Value, FHeight);
  208. end;
  209. procedure TFPCustomImage.SetSize (AWidth, AHeight : integer);
  210. begin
  211. FWidth := AWidth;
  212. FHeight := AHeight;
  213. end;
  214. procedure TFPCustomImage.SetExtraValue (index:integer; const AValue:string);
  215. var s : string;
  216. p : integer;
  217. begin
  218. s := FExtra[index];
  219. p := pos ('=', s);
  220. if p > 0 then
  221. FExtra[index] := copy(s, 1, p) + AValue
  222. else
  223. FPImgError (StrInvalidIndex,[ErrorText[StrImageExtra],index]);
  224. end;
  225. function TFPCustomImage.GetExtraValue (index:integer) : string;
  226. var s : string;
  227. p : integer;
  228. begin
  229. s := FExtra[index];
  230. p := pos ('=', s);
  231. if p > 0 then
  232. result := copy(s, p+1, maxint)
  233. else
  234. result := '';
  235. end;
  236. procedure TFPCustomImage.SetExtraKey (index:integer; const AValue:string);
  237. var s : string;
  238. p : integer;
  239. begin
  240. s := FExtra[index];
  241. p := pos('=',s);
  242. if p > 0 then
  243. s := AValue + copy(s,p,maxint)
  244. else
  245. s := AValue;
  246. FExtra[index] := s;
  247. end;
  248. function TFPCustomImage.GetExtraKey (index:integer) : string;
  249. begin
  250. result := FExtra.Names[index];
  251. end;
  252. procedure TFPCustomImage.SetExtra (const key:String; const AValue:string);
  253. begin
  254. FExtra.values[key] := AValue;
  255. end;
  256. function TFPCustomImage.GetExtra (const key:String) : string;
  257. begin
  258. result := FExtra.values[key];
  259. end;
  260. function TFPCustomImage.ExtraCount : integer;
  261. begin
  262. result := FExtra.count;
  263. end;
  264. procedure TFPCustomImage.RemoveExtra (const key:string);
  265. var p : integer;
  266. begin
  267. p := FExtra.IndexOfName(key);
  268. if p >= 0 then
  269. FExtra.Delete (p);
  270. end;
  271. procedure TFPCustomImage.SetPixel (x,y:integer; Value:integer);
  272. begin
  273. CheckPaletteIndex (Value);
  274. CheckIndex (x,y);
  275. SetInternalPixel (x,y,Value);
  276. end;
  277. function TFPCustomImage.GetPixel (x,y:integer) : integer;
  278. begin
  279. CheckIndex (x,y);
  280. result := GetInternalPixel(x,y);
  281. end;
  282. procedure TFPCustomImage.SetColor (x,y:integer; const Value:TFPColor);
  283. begin
  284. CheckIndex (x,y);
  285. SetInternalColor (x,y,Value);
  286. end;
  287. function TFPCustomImage.GetColor (x,y:integer) : TFPColor;
  288. begin
  289. CheckIndex (x,y);
  290. result := GetInternalColor(x,y);
  291. end;
  292. procedure TFPCustomImage.SetInternalColor (x,y:integer; const Value:TFPColor);
  293. var i : integer;
  294. begin
  295. i := FPalette.IndexOf (Value);
  296. SetInternalPixel (x,y,i);
  297. end;
  298. function TFPCustomImage.GetInternalColor (x,y:integer) : TFPColor;
  299. begin
  300. result := FPalette.Color[GetInternalPixel(x,y)];
  301. end;
  302. function TFPCustomImage.GetUsePalette : boolean;
  303. begin
  304. result := assigned(FPalette);
  305. end;
  306. procedure TFPCustomImage.SetUsePalette(Value:boolean);
  307. begin
  308. if Value <> assigned(FPalette)
  309. then
  310. if Value
  311. then
  312. begin
  313. FPalette := TFPPalette.Create (0);
  314. // FPalette.Add (colTransparent);
  315. end
  316. else
  317. begin
  318. FPalette.Free;
  319. FPalette := nil;
  320. end;
  321. end;
  322. procedure TFPCustomImage.CheckPaletteIndex (PalIndex:integer);
  323. begin
  324. if UsePalette then
  325. begin
  326. if (PalIndex < -1) or (PalIndex >= FPalette.Count) then
  327. FPImgError (StrInvalidIndex,[ErrorText[StrPalette],PalIndex]);
  328. end
  329. else
  330. FPImgError (StrNoPaletteAvailable);
  331. end;
  332. procedure TFPCustomImage.CheckIndex (x,y:integer);
  333. begin
  334. if (x < 0) or (x >= FWidth) then
  335. FPImgError (StrInvalidIndex,[ErrorText[StrImageX],x]);
  336. if (y < 0) or (y >= FHeight) then
  337. FPImgError (StrInvalidIndex,[ErrorText[StrImageY],y]);
  338. end;
  339. Procedure TFPCustomImage.Progress(Sender: TObject; Stage: TProgressStage;
  340. PercentDone: Byte; RedrawNow: Boolean; const R: TRect;
  341. const Msg: AnsiString; var Continue: Boolean);
  342. begin
  343. If Assigned(FOnProgress) then
  344. FonProgress(Sender,Stage,PercentDone,RedrawNow,R,Msg,Continue);
  345. end;
  346. Procedure TFPCustomImage.Assign(Source: TPersistent);
  347. Var
  348. Src : TFPCustomImage;
  349. X,Y : Integer;
  350. begin
  351. If Source is TFPCustomImage then
  352. begin
  353. Src:=TFPCustomImage(Source);
  354. // Copy extra info
  355. FExtra.Assign(Src.Fextra);
  356. // Copy palette if needed.
  357. UsePalette:=Src.UsePalette;
  358. If UsePalette then
  359. begin
  360. Palette.Count:=0;
  361. Palette.Build(Src);
  362. end;
  363. // Copy image.
  364. SetSize(Src.Width,Src.height);
  365. If UsePalette then
  366. For x:=0 to Src.Width-1 do
  367. For y:=0 to src.Height-1 do
  368. pixels[X,Y]:=src.pixels[X,Y]
  369. else
  370. For x:=0 to Src.Width-1 do
  371. For y:=0 to src.Height-1 do
  372. self[X,Y]:=src[X,Y];
  373. end
  374. else
  375. Inherited Assign(Source);
  376. end;
  377. { TFPMemoryImage }
  378. constructor TFPMemoryImage.Create (AWidth,AHeight:integer);
  379. begin
  380. Fdata := nil;
  381. inherited create (AWidth,AHeight);
  382. {Default behavior is to use palette as suggested by Michael}
  383. SetUsePalette(True);
  384. end;
  385. destructor TFPMemoryImage.Destroy;
  386. begin
  387. // MG: missing if
  388. if FData<>nil then
  389. FreeMem (FData);
  390. inherited Destroy;
  391. end;
  392. function TFPMemoryImage.GetInternalColor(x,y:integer):TFPColor;
  393. begin
  394. if Assigned(FPalette)
  395. then
  396. Result:=inherited GetInternalColor(x,y)
  397. else
  398. Result:=PFPColorArray(FData)^[y*FWidth+x];
  399. end;
  400. function TFPMemoryImage.GetInternalPixel (x,y:integer) : integer;
  401. begin
  402. result := FData^[y*FWidth+x];
  403. end;
  404. procedure TFPMemoryImage.SetInternalColor (x,y:integer; const Value:TFPColor);
  405. begin
  406. if Assigned(FPalette)
  407. then
  408. inherited SetInternalColor(x,y,Value)
  409. else
  410. PFPColorArray(FData)^[y*FWidth+x]:=Value;
  411. end;
  412. procedure TFPMemoryImage.SetInternalPixel (x,y:integer; Value:integer);
  413. begin
  414. FData^[y*FWidth+x] := Value;
  415. end;
  416. function Lowest (a,b : integer) : integer;
  417. begin
  418. if a <= b then
  419. result := a
  420. else
  421. result := b;
  422. end;
  423. procedure TFPMemoryImage.SetSize (AWidth, AHeight : integer);
  424. var w, h, r, old : integer;
  425. NewData : PFPIntegerArray;
  426. begin
  427. if (AWidth <> Width) or (AHeight <> Height) then
  428. begin
  429. old := Height * Width;
  430. r:=AWidth*AHeight;
  431. if Assigned(FPalette)
  432. then
  433. r:=SizeOf(integer)*r
  434. else
  435. r:=SizeOf(TFPColor)*r;
  436. if r = 0 then
  437. NewData := nil
  438. else
  439. begin
  440. GetMem (NewData, r);
  441. FillWord (Newdata^[0], r div sizeof(word), 0);
  442. end;
  443. // MG: missing "and (NewData<>nil)"
  444. if (old <> 0) and assigned(FData) and (NewData<>nil) then
  445. begin
  446. if r <> 0 then
  447. begin
  448. w := Lowest(Width, AWidth);
  449. h := Lowest(Height, AHeight);
  450. for r := 0 to h-1 do
  451. move (FData^[r*Width], NewData^[r*AWidth], w);
  452. end;
  453. FreeMem (FData);
  454. end;
  455. FData := NewData;
  456. inherited;
  457. end;
  458. end;
  459. procedure TFPMemoryImage.SetUsePalette(Value:boolean);
  460. var
  461. OldColors:PFPColorArray;
  462. OldPixels:PFPIntegerArray;
  463. r,c:Integer;
  464. begin
  465. if Value<>assigned(FPalette)
  466. then
  467. if Value
  468. then
  469. begin
  470. FPalette:=TFPPalette.Create(0);
  471. //FPalette.Add(colTransparent);
  472. if assigned(FData) then
  473. begin
  474. OldColors:=PFPColorArray(FData);
  475. GetMem(FData,FWidth*FHeight*SizeOf(Integer));
  476. for r:=0 to FHeight-1 do
  477. for c:=0 to FWidth-1 do
  478. Colors[c,r]:=OldColors^[r*FWidth+c];
  479. FreeMem(OldColors);
  480. end;
  481. end
  482. else
  483. begin
  484. OldPixels:=PFPIntegerArray(FData);
  485. GetMem(FData,FWidth*FHeight*SizeOf(TFPColor));
  486. for r:=0 to FHeight-1 do
  487. for c:=0 to FWidth-1 do
  488. Colors[c,r]:=FPalette.Color[OldPixels^[r*FWidth+c]];
  489. FreeMem(OldPixels);
  490. FPalette.Free;
  491. FPalette:=nil;
  492. end;
  493. end;