fpimage.inc 13 KB

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