source: oup/releases/0.33a/Code/OniImgClass.pas@ 230

Last change on this file since 230 was 46, checked in by alloc, 18 years ago
File size: 24.5 KB
Line 
1unit OniImgClass;
2
3interface
4
5uses Math, Dialogs, Types, SysUtils, Classes, Data, OniDataClass;
6
7type
8 TImgDataType = set of (DT_OniReverted, DT_Oni, DT_Decoded32);
9
10type
11 TOniImage = class
12 private
13 FLoaded: Boolean;
14 FDataType: TImgDataType;
15 FData: Tdata;
16 FWidth, FHeight: Word;
17 FDepth: Byte;
18 FStoreType: Byte;
19
20 function ResizeImage(oldx, oldy: LongWord; img: Tdata): Tdata;
21 procedure RevertImage;
22 procedure DecodeImage;
23 procedure DecompressImage;
24 protected
25 public
26 property Loaded: Boolean Read FLoaded Write FLoaded;
27 property DataType: TImgDataType Read FDataType Write FDataType;
28 property Width: Word Read FWidth Write FWidth;
29 property Height: Word Read FHeight Write FHeight;
30 property Depth: Byte Read FDepth Write FDepth;
31 property StoreType: Byte Read FStoreType Write FStoreType;
32 property Data: Tdata Read FData Write FData;
33
34 constructor Create;
35 function Load(fileid: LongWord): Boolean;
36 function LoadFromPSpc(fileid: LongWord): Boolean;
37 function LoadFromTXMP(fileid: LongWord): Boolean;
38 function LoadFromTXMB(fileid: LongWord): Boolean;
39 function GetImageDataSize(fading: Boolean): LongWord;
40
41 function GetAsData: Tdata;
42 function GetAs32bit: Tdata;
43 function GetAsBMP: Tdata;
44 function LoadFromBMP(filename: String): Boolean;
45 function WriteToBMP(filename: String): Boolean;
46 function GetMipMappedImage(var faded: Tdata): Boolean;
47 published
48 end;
49
50
51implementation
52
53uses Functions;
54
55
56
57
58constructor TOniImage.Create;
59begin
60 Self.FLoaded := False;
61 Self.FDataType := [];
62 SetLength(Self.FData, 0);
63 Self.FWidth := 0;
64 Self.FHeight := 0;
65 Self.FDepth := 0;
66 Self.FStoreType := 0;
67end;
68
69
70
71
72function TOniImage.ResizeImage(oldx, oldy: LongWord; img: Tdata): Tdata;
73var
74 i, j: LongWord;
75 col, row, row_orig: LongWord;
76begin
77 SetLength(Result, (oldx div 2) * (oldy div 2) * (Self.FDepth div 8));
78 row_orig := 0;
79 row := 0;
80 col := 0;
81 for i := 0 to (oldx * oldy) - 1 do
82 begin
83 if ((i mod oldx) = 0) and (i > 0) then
84 begin
85 Inc(row_orig);
86 if (row_orig mod 2) = 0 then
87 begin
88 Inc(row);
89 col := 0;
90 end;
91 end;
92 if (row_orig mod 2) = 0 then
93 begin
94 if (i mod 2) = 0 then
95 begin
96 for j := 0 to (Self.FDepth div 8) - 1 do
97 Result[((row * (oldx div 2)) + col) * (Self.FDepth div 8) + j] :=
98 img[(i * (Self.FDepth div 8)) + j];
99 Inc(col);
100 end;
101 end;
102 end;
103end;
104
105
106
107
108procedure TOniImage.RevertImage;
109var
110 x, y, i: LongWord;
111 tempd: Tdata;
112begin
113 SetLength(tempd, Self.FWidth * Self.FHeight * (Self.FDepth div 8));
114 for y := 0 to Self.FHeight - 1 do
115 for x := 0 to Self.FWidth - 1 do
116 for i := 0 to (Self.FDepth div 8) - 1 do
117 tempd[((Self.FWidth * (Self.FHeight - 1 - y) + x) * (Self.FDepth div 8)) + i] :=
118 Self.FData[(Self.FWidth * y + x) * (Self.FDepth div 8) + i];
119 for x := 0 to High(tempd) do
120 Self.FData[x] := tempd[x];
121 if DT_OniReverted in Self.FDataType then
122 Self.FDataType := Self.FDataType - [DT_OniReverted]
123 else
124 Self.FDataType := Self.FDataType + [DT_OniReverted];
125end;
126
127
128
129
130procedure TOniImage.DecodeImage;
131var
132 x, y: LongWord;
133 tempd: Tdata;
134begin
135 if not (DT_Decoded32 in Self.FDataType) then
136 begin
137 SetLength(tempd, Self.FWidth * Self.FHeight * 4);
138 case Self.FStoreType of
139 0:
140 begin
141 for y := 0 to Self.FHeight - 1 do
142 begin
143 for x := 0 to Self.FWidth - 1 do
144 begin
145 tempd[((Self.FWidth * y + x) * 4) + 0] :=
146 Round(((Self.FData[(Self.FWidth * y + x) * 2] + Self.FData[(Self.FWidth * y + x) * 2 + 1] * 256) and
147 $000F) / $000F * 255);
148 tempd[((Self.FWidth * y + x) * 4) + 1] :=
149 Round(((Self.FData[(Self.FWidth * y + x) * 2] + Self.FData[(Self.FWidth * y + x) * 2 + 1] * 256) and
150 $00F0) / $00F0 * 255);
151 tempd[((Self.FWidth * y + x) * 4) + 2] :=
152 Round(((Self.FData[(Self.FWidth * y + x) * 2] + Self.FData[(Self.FWidth * y + x) * 2 + 1] * 256) and
153 $0F00) / $0F00 * 255);
154 tempd[((Self.FWidth * y + x) * 4) + 3] := 0;
155 end;
156 end;
157 end;
158 1, 2:
159 begin
160 for y := 0 to Self.FHeight - 1 do
161 begin
162 for x := 0 to Self.FWidth - 1 do
163 begin
164 tempd[((Self.FWidth * y + x) * 4) + 0] :=
165 Round(((Self.FData[(Self.FWidth * y + x) * 2] + Self.FData[(Self.FWidth * y + x) * 2 + 1] * 256) and
166 $001F) / $001F * 255);
167 tempd[((Self.FWidth * y + x) * 4) + 1] :=
168 Round(((Self.FData[(Self.FWidth * y + x) * 2] + Self.FData[(Self.FWidth * y + x) * 2 + 1] * 256) and
169 $03E0) / $03E0 * 255);
170 tempd[((Self.FWidth * y + x) * 4) + 2] :=
171 Round(((Self.FData[(Self.FWidth * y + x) * 2] + Self.FData[(Self.FWidth * y + x) * 2 + 1] * 256) and
172 $7C00) / $7C00 * 255);
173 tempd[((Self.FWidth * y + x) * 4) + 3] := 0;
174 end;
175 end;
176 end;
177 9:
178 begin
179 DecompressImage;
180 end;
181 end;
182 Self.FDepth := 32;
183 if (Self.FStoreType <> 9) and (Self.FStoreType <> 8) then
184 begin
185 SetLength(Self.FData, Length(tempd));
186 for x := 0 to High(tempd) do
187 Self.FData[x] := tempd[x];
188 end;
189 Self.FStoreType := 8;
190 if DT_Oni in Self.FDataType then
191 Self.FDataType := Self.FDataType - [DT_Oni];
192 Self.FDataType := Self.FDataType + [DT_Decoded32];
193 end;
194 if DT_OniReverted in Self.FDataType then
195 Self.RevertImage;
196end;
197
198
199
200
201procedure TOniImage.DecompressImage;
202type
203 Tcolor = record
204 RGBb: Byte;
205 RGBg: Byte;
206 RGBr: Byte;
207 RGBa: Byte;
208 end;
209var
210 i, j, x, y: LongWord;
211 color: array[1..4] of Tcolor;
212 pixel: array[1..16] of Byte;
213 tempd: Tdata;
214begin
215 x := 0;
216 y := 0;
217 SetLength(tempd, Self.FWidth * Self.FHeight * 4);
218 for i := 0 to ((Self.FWidth * Self.FHeight) div 16) - 1 do
219 begin
220 Color[1].RGBb := Round(((Self.FData[(i * 8) + 0] + Self.FData[(i * 8) + 1] * 256) and $001F) /
221 $001F * 255);
222 Color[1].RGBg := Round(((Self.FData[(i * 8) + 0] + Self.FData[(i * 8) + 1] * 256) and $07E0) /
223 $07E0 * 255);
224 Color[1].RGBr := Round(((Self.FData[(i * 8) + 0] + Self.FData[(i * 8) + 1] * 256) and $F800) /
225 $F800 * 255);
226 Color[1].RGBa := 255;
227 Color[2].RGBb := Round(((Self.FData[(i * 8) + 2] + Self.FData[(i * 8) + 3] * 256) and $001F) /
228 $001F * 255);
229 Color[2].RGBg := Round(((Self.FData[(i * 8) + 2] + Self.FData[(i * 8) + 3] * 256) and $07E0) /
230 $07E0 * 255);
231 Color[2].RGBr := Round(((Self.FData[(i * 8) + 2] + Self.FData[(i * 8) + 3] * 256) and $F800) /
232 $F800 * 255);
233 Color[2].RGBa := 255;
234 Color[3].RGBb := Round(Color[1].RGBb / 3 * 2 + Color[2].RGBb / 3);
235 Color[3].RGBg := Round(Color[1].RGBg / 3 * 2 + Color[2].RGBg / 3);
236 Color[3].RGBr := Round(Color[1].RGBr / 3 * 2 + Color[2].RGBr / 3);
237 Color[3].RGBa := 255;
238 Color[4].RGBb := Round(Color[1].RGBb / 3 + Color[2].RGBb / 3 * 2);
239 Color[4].RGBg := Round(Color[1].RGBg / 3 + Color[2].RGBg / 3 * 2);
240 Color[4].RGBr := Round(Color[1].RGBr / 3 + Color[2].RGBr / 3 * 2);
241 Color[4].RGBa := 255;
242 Pixel[1] := Round((Self.FData[(i * 8) + 4] and $C0) / $40 + 1);
243 Pixel[2] := Round((Self.FData[(i * 8) + 4] and $30) / $10 + 1);
244 Pixel[3] := Round((Self.FData[(i * 8) + 4] and $0C) / $04 + 1);
245 Pixel[4] := Round((Self.FData[(i * 8) + 4] and $03) + 1);
246 Pixel[5] := Round((Self.FData[(i * 8) + 5] and $C0) / $40 + 1);
247 Pixel[6] := Round((Self.FData[(i * 8) + 5] and $30) / $10 + 1);
248 Pixel[7] := Round((Self.FData[(i * 8) + 5] and $0C) / $04 + 1);
249 Pixel[8] := Round((Self.FData[(i * 8) + 5] and $03) + 1);
250 Pixel[9] := Round((Self.FData[(i * 8) + 6] and $C0) / $40 + 1);
251 Pixel[10] := Round((Self.FData[(i * 8) + 6] and $30) / $10 + 1);
252 Pixel[11] := Round((Self.FData[(i * 8) + 6] and $0C) / $04 + 1);
253 Pixel[12] := Round((Self.FData[(i * 8) + 6] and $03) + 1);
254 Pixel[13] := Round((Self.FData[(i * 8) + 7] and $C0) / $40 + 1);
255 Pixel[14] := Round((Self.FData[(i * 8) + 7] and $30) / $10 + 1);
256 Pixel[15] := Round((Self.FData[(i * 8) + 7] and $0C) / $04 + 1);
257 Pixel[16] := Round((Self.FData[(i * 8) + 7] and $03) + 1);
258 for j := 0 to 3 do
259 begin
260 tempd[((y + 3) * Self.FWidth + x + j) * 4 + 0] := Color[Pixel[16 - j]].RGBb;
261 tempd[((y + 3) * Self.FWidth + x + j) * 4 + 1] := Color[Pixel[16 - j]].RGBg;
262 tempd[((y + 3) * Self.FWidth + x + j) * 4 + 2] := Color[Pixel[16 - j]].RGBr;
263 tempd[((y + 3) * Self.FWidth + x + j) * 4 + 3] := 0;
264 end;
265 for j := 0 to 3 do
266 begin
267 tempd[((y + 2) * Self.FWidth + x + j) * 4 + 0] := Color[Pixel[12 - j]].RGBb;
268 tempd[((y + 2) * Self.FWidth + x + j) * 4 + 1] := Color[Pixel[12 - j]].RGBg;
269 tempd[((y + 2) * Self.FWidth + x + j) * 4 + 2] := Color[Pixel[12 - j]].RGBr;
270 tempd[((y + 2) * Self.FWidth + x + j) * 4 + 3] := 0;
271 end;
272 for j := 0 to 3 do
273 begin
274 tempd[((y + 1) * Self.FWidth + x + j) * 4 + 0] := Color[Pixel[8 - j]].RGBb;
275 tempd[((y + 1) * Self.FWidth + x + j) * 4 + 1] := Color[Pixel[8 - j]].RGBg;
276 tempd[((y + 1) * Self.FWidth + x + j) * 4 + 2] := Color[Pixel[8 - j]].RGBr;
277 tempd[((y + 1) * Self.FWidth + x + j) * 4 + 3] := 0;
278 end;
279 for j := 0 to 3 do
280 begin
281 tempd[((y + 0) * Self.FWidth + x + j) * 4 + 0] := Color[Pixel[4 - j]].RGBb;
282 tempd[((y + 0) * Self.FWidth + x + j) * 4 + 1] := Color[Pixel[4 - j]].RGBg;
283 tempd[((y + 0) * Self.FWidth + x + j) * 4 + 2] := Color[Pixel[4 - j]].RGBr;
284 tempd[((y + 0) * Self.FWidth + x + j) * 4 + 3] := 0;
285 end;
286 x := x + 4;
287 if x = Self.FWidth then
288 begin
289 y := y + 4;
290 x := 0;
291 end;
292 end;
293 SetLength(Self.FData, Length(tempd));
294 for i := 0 to High(tempd) do
295 Self.FData[i] := tempd[i];
296 Self.FStoreType := 8;
297 Self.FDepth := 32;
298 Self.FDataType := Self.FDataType - [DT_Oni] + [DT_Decoded32];
299end;
300
301
302
303
304
305function TOniImage.Load(fileid: LongWord): Boolean;
306var
307 FileInfo: TFileInfo;
308 ext: String;
309begin
310 FileInfo := OniDataConnection.GetFileInfo(fileid);
311 if FileInfo.Extension = 'PSpc' then
312 Result := LoadFromPSpc(fileid)
313 else if FileInfo.Extension = 'TXMB' then
314 Result := LoadFromTXMB(fileid)
315 else if FileInfo.Extension = 'TXMP' then
316 Result := LoadFromTXMP(fileid)
317 else
318 Result := False;
319end;
320
321
322
323
324function TOniImage.LoadFromPSpc(fileid: LongWord): Boolean;
325type
326 TPoint = packed record
327 X, Y: Word;
328 end;
329
330 TPSpc = packed record
331 p1: array[0..8] of TPoint;
332 p2: array[0..8] of TPoint;
333 TXMP: LongWord;
334 end;
335
336 TPart = packed record
337 x_txmp, y_txmp: Word;
338 x_pspc, y_pspc: Word;
339 w, h: Word;
340 imgdata: Tdata;
341 used: Boolean;
342 end;
343const
344 PartMatch: array[0..8] of Byte = (0, 3, 6, 1, 4, 7, 2, 5, 8);
345var
346 x, y, pixel: Word;
347 i: Integer;
348
349 PSpc: TPSpc;
350 txmpimg: TOniImage;
351 txmpdata: Tdata;
352
353 parts: array[0..8] of TPart;
354 part: Byte;
355 cols: array[0..2] of Word;
356 rows: array[0..2] of Word;
357 col, row: Byte;
358begin
359 OniDataConnection.LoadDatFilePart(fileid, $08, SizeOf(PSpc), @PSpc);
360 PSpc.TXMP := PSpc.TXMP div 256;
361 if PSpc.TXMP = 0 then
362 begin
363 Result := False;
364 Exit;
365 end;
366 txmpimg := TOniImage.Create;
367 txmpimg.LoadFromTXMP(PSpc.TXMP);
368 txmpimg.DecodeImage;
369 txmpimg.WriteToBMP('C:\file.bmp');
370 txmpdata := txmpimg.GetAs32bit;
371{ ShowMessage(IntToStr(txmpimg.Width)+'x'+IntToStr(txmpimg.Height));
372 for i:=0 to High(txmpdata) do
373 txmpimg.Data[i]:=txmpdata[i];
374 txmpimg.WriteToBMP('D:\file2.bmp');
375}
376 with PSpc do
377 begin
378 for i := 0 to 2 do
379 begin
380 cols[i] := 0;
381 rows[i] := 0;
382 end;
383 for i := 0 to 8 do
384 begin
385 part := PartMatch[i];
386 col := i div 3;
387 row := i mod 3;
388 if (p2[i].X > 0) or (p2[i].Y > 0) then
389 begin
390 parts[part].x_txmp := p1[i].X - 1;
391 parts[part].y_txmp := p1[i].Y - 1;
392 parts[part].x_pspc := 0;
393 if col > 0 then
394 for x := 0 to col - 1 do
395 Inc(parts[part].x_pspc, cols[x]);
396 parts[part].y_pspc := 0;
397 if row > 0 then
398 for y := 0 to row - 1 do
399 Inc(parts[part].y_pspc, rows[y]);
400 parts[part].w := p2[i].X - p1[i].X + 1;
401 parts[part].h := p2[i].Y - p1[i].Y + 1;
402 parts[part].used := True;
403 cols[col] := parts[part].w;
404 rows[row] := parts[part].h;
405 SetLength(parts[part].imgdata, parts[part].w * parts[part].h * 4);
406 for y := 0 to parts[part].h - 1 do
407 begin
408 for x := 0 to parts[part].w - 1 do
409 begin
410 for pixel := 0 to 3 do
411 begin
412 parts[part].imgdata[(y * parts[part].w + x) * 4 + pixel] :=
413 txmpdata[((parts[part].y_txmp + y) * txmpimg.Width +
414 parts[part].x_txmp + x) * 4 + pixel];
415 end;
416 end;
417 end;
418 end
419 else
420 begin
421 parts[part].used := False;
422 end;
423 end;
424
425 end;
426
427 txmpimg.Free;
428 txmpimg := TOniImage.Create;
429 for i := 0 to 8 do
430 begin
431 if parts[i].used then
432 begin
433 SetLength(txmpimg.FData, Length(parts[i].imgdata));
434 for pixel := 0 to High(parts[i].imgdata) do
435 txmpimg.Data[pixel] := parts[i].imgdata[pixel];
436 txmpimg.Width := parts[i].w;
437 txmpimg.Height := parts[i].h;
438 txmpimg.StoreType := 8;
439 txmpimg.DataType := [DT_Decoded32];
440 txmpimg.Depth := 32;
441 txmpimg.WriteToBMP('D:\' + IntToStr(i) + '.bmp');
442 end;
443 end;
444 txmpimg.Free;
445
446 Self.FWidth := 0;
447 Self.FHeight := 0;
448 for i := 0 to 2 do
449 begin
450 Inc(Self.FWidth, cols[i]);
451 Inc(Self.FHeight, rows[i]);
452 end;
453 SetLength(Self.FData, Self.FWidth * Self.FHeight * 4);
454
455 //Combine data parts
456
457 Self.FDepth := 32;
458 Self.FStoreType := 8;
459 Self.FDataType := [DT_Decoded32];
460 // Self.RevertImage;
461end;
462
463
464
465
466function TOniImage.LoadFromTXMP(fileid: LongWord): Boolean;
467var
468 img_addr: LongWord;
469begin
470 Result := True;
471 OniDataConnection.LoadDatFilePart(fileid, $8C, SizeOf(Self.FWidth), @Self.FWidth);
472 OniDataConnection.LoadDatFilePart(fileid, $8E, SizeOf(Self.FHeight), @Self.FHeight);
473 OniDataConnection.LoadDatFilePart(fileid, $90, SizeOf(Self.FStoreType),
474 @Self.FStoreType);
475 if not OniDataConnection.OSisMac then
476 OniDataConnection.LoadDatFilePart(fileid, $9C, SizeOf(img_addr), @img_addr)
477 else
478 OniDataConnection.LoadDatFilePart(fileid, $A0, SizeOf(img_addr), @img_addr);
479
480 case Self.FStoreType of
481 0, 1, 2:
482 begin
483 SetLength(Self.FData, Self.FWidth * Self.FHeight * 2);
484 Self.FDepth := 16;
485 end;
486 8:
487 begin
488 SetLength(Self.FData, Self.FWidth * Self.FHeight * 4);
489 Self.FDepth := 32;
490 end;
491 9:
492 begin
493 SetLength(Self.FData, Self.FWidth * Self.FHeight div 2);
494 Self.FDepth := 16;
495 end;
496 else
497 Result := False;
498 Exit;
499 end;
500
501 if not OniDataConnection.OSisMac then
502 OniDataConnection.LoadRawFile(fileid, $9C, @Self.FData[0])
503 else
504 OniDataConnection.LoadRawFile(fileid, $A0, @Self.FData[0]);
505
506 Self.FDataType := [DT_OniReverted, DT_Oni];
507end;
508
509
510
511
512function TOniImage.LoadFromTXMB(fileid: LongWord): Boolean;
513var
514 i, x, y, x2, y2, pixelid, imgid: LongWord;
515 rows, cols: Word;
516 linkcount: LongWord;
517 link: LongWord;
518 images_decoded: array of TOniImage;
519 x_start, y_start: LongWord;
520begin
521 OniDataConnection.LoadDatFilePart(fileid, $10, SizeOf(Self.FWidth), @Self.FWidth);
522 OniDataConnection.LoadDatFilePart(fileid, $12, SizeOf(Self.FHeight), @Self.FHeight);
523 OniDataConnection.LoadDatFilePart(fileid, $18, SizeOf(cols), @cols);
524 OniDataConnection.LoadDatFilePart(fileid, $1A, SizeOf(rows), @rows);
525 OniDataConnection.LoadDatFilePart(fileid, $1C, SizeOf(linkcount), @linkcount);
526 SetLength(images_decoded, linkcount);
527 for i := 0 to linkcount - 1 do
528 begin
529 OniDataConnection.LoadDatFilePart(fileid, $20 + i * 4, SizeOf(link), @link);
530 link := link div 256;
531 images_decoded[i] := TOniImage.Create;
532 images_decoded[i].LoadFromTXMP(link);
533 images_decoded[i].DecodeImage;
534 images_decoded[i].RevertImage;
535 end;
536 SetLength(Self.FData, Self.FWidth * Self.FHeight * 4);
537 for y := 0 to rows - 1 do
538 begin
539 for x := 0 to cols - 1 do
540 begin
541 imgid := y * cols + x;
542 x_start := 0;
543 y_start := 0;
544 for i := 0 to x do
545 if i < x then
546 x_start := x_start + images_decoded[i].Width;
547 for i := 0 to y do
548 if i < y then
549 y_start := y_start + images_decoded[i].Height;
550 for y2 := 0 to images_decoded[imgid].Height - 1 do
551 begin
552 for x2 := 0 to images_decoded[imgid].Width - 1 do
553 begin
554 if ((x_start + x2) < Self.FWidth) and ((y_start + y2) < Self.FHeight) then
555 begin
556 pixelid := y_start * Self.FWidth + x_start + y2 * Self.FWidth + x2;
557 Self.FData[pixelid * 4 + 0] :=
558 images_decoded[imgid].Data[(y2 * images_decoded[imgid].Width + x2) * 4 + 0];
559 Self.FData[pixelid * 4 + 1] :=
560 images_decoded[imgid].Data[(y2 * images_decoded[imgid].Width + x2) * 4 + 1];
561 Self.FData[pixelid * 4 + 2] :=
562 images_decoded[imgid].Data[(y2 * images_decoded[imgid].Width + x2) * 4 + 2];
563 Self.FData[pixelid * 4 + 3] :=
564 images_decoded[imgid].Data[(y2 * images_decoded[imgid].Width + x2) * 4 + 3];
565 end;
566 end;
567 end;
568 end;
569 end;
570 for i := 0 to linkcount - 1 do
571 images_decoded[i].Free;
572 Self.FDepth := 32;
573 Self.FStoreType := 8;
574 Self.FDataType := [DT_Decoded32];
575 Self.RevertImage;
576end;
577
578
579
580
581function TOniImage.GetImageDataSize(fading: Boolean): LongWord;
582var
583 size: LongWord;
584 x, y: Word;
585 bpp: Byte;
586begin
587 case Self.FStoreType of
588 9:
589 bpp := 8;
590 0, 1, 2:
591 bpp := 16;
592 8:
593 bpp := 32;
594 else
595 Result := 0;
596 Exit;
597 end;
598
599 x := Self.FWidth;
600 y := Self.FHeight;
601 size := x * y * bpp div 8;
602 if fading then
603 begin
604 repeat
605 x := x div 2;
606 y := y div 2;
607 size := size + x * y * bpp div 8;
608 until (x = 1) or (y = 1);
609 end;
610 Result := size;
611end;
612
613
614
615
616function TOniImage.GetAsData: Tdata;
617var
618 i: Integer;
619 revert: Boolean;
620begin
621 // if not (DT_Decoded32 in Self.FDataType) then
622 // Self.DecodeImage;
623 if not (DT_OniReverted in Self.FDataType) then
624 begin
625 revert := True;
626 Self.RevertImage;
627 end
628 else
629 revert := False;
630 SetLength(Result, Length(Self.FData));
631 for i := 0 to High(Result) do
632 Result[i] := Self.FData[i];
633 if revert then
634 Self.RevertImage;
635end;
636
637
638
639
640function TOniImage.GetAs32bit: Tdata;
641var
642 i: Integer;
643begin
644 if not (DT_Decoded32 in Self.FDataType) then
645 Self.DecodeImage;
646 SetLength(Result, Length(Self.FData));
647 for i := 0 to High(Result) do
648 Result[i] := Self.FData[i];
649end;
650
651
652
653
654function TOniImage.GetAsBMP: Tdata;
655const
656 BMPheader: array[0..53] of Byte =
657 ($42, $4D, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0,
658 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, $18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
659 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
660var
661 i, x, y: LongWord;
662begin
663 if not (DT_Decoded32 in Self.FDataType) then
664 Self.DecodeImage;
665
666 SetLength(Result, Self.FWidth * Self.FHeight * 3 + 54);
667 for y := 0 to Self.FHeight - 1 do
668 begin
669 for x := 0 to Self.FWidth - 1 do
670 begin
671 Result[((Self.FWidth * y + x) * 3) + 0 + 54] := Self.FData[(Self.FWidth * y + x) * 4 + 0];
672 Result[((Self.FWidth * y + x) * 3) + 1 + 54] := Self.FData[(Self.FWidth * y + x) * 4 + 1];
673 Result[((Self.FWidth * y + x) * 3) + 2 + 54] := Self.FData[(Self.FWidth * y + x) * 4 + 2];
674 end;
675 end;
676
677 for i := 0 to High(BMPheader) do
678 Result[i] := BMPheader[i];
679 Result[2] := ((Self.FWidth * Self.FHeight * 3 + 54) and $000000FF) div $1;
680 Result[3] := ((Self.FWidth * Self.FHeight * 3 + 54) and $0000FF00) div $100;
681 Result[4] := ((Self.FWidth * Self.FHeight * 3 + 54) and $00FF0000) div $10000;
682 Result[5] := ((Self.FWidth * Self.FHeight * 3 + 54) and $FF000000) div $1000000;
683 Result[18] := (Self.FWidth and $000000FF) div $1;
684 Result[19] := (Self.FWidth and $0000FF00) div $100;
685 Result[20] := (Self.FWidth and $00FF0000) div $10000;
686 Result[21] := (Self.FWidth and $FF000000) div $1000000;
687 Result[22] := (Self.FHeight and $000000FF) div $1;
688 Result[23] := (Self.FHeight and $0000FF00) div $100;
689 Result[24] := (Self.FHeight and $00FF0000) div $10000;
690 Result[25] := (Self.FHeight and $FF000000) div $1000000;
691 Result[34] := ((Self.FWidth * Self.FHeight * 3) and $000000FF) div $1;
692 Result[35] := ((Self.FWidth * Self.FHeight * 3) and $0000FF00) div $100;
693 Result[36] := ((Self.FWidth * Self.FHeight * 3) and $00FF0000) div $10000;
694 Result[37] := ((Self.FWidth * Self.FHeight * 3) and $FF000000) div $1000000;
695end;
696
697
698
699
700function TOniImage.LoadFromBMP(filename: String): Boolean;
701var
702 filestream: TFileStream;
703 tempd: Tdata;
704
705 x, y: LongWord;
706begin
707 filestream := TFileStream.Create(filename, fmOpenRead);
708 SetLength(tempd, filestream.Size);
709 filestream.Read(tempd[0], filestream.Size);
710 filestream.Free;
711
712 if not ((tempd[00] = $42) and (tempd[01] = $4D)) then
713 begin
714 Result := False;
715 ShowMessage('Not a standard 24bit bitmap');
716 Exit;
717 end;
718 if not (tempd[10] = 54) then
719 begin
720 Result := False;
721 ShowMessage('Imagedata has to start at 0x54');
722 Exit;
723 end;
724 if not (tempd[14] = 40) then
725 begin
726 Result := False;
727 ShowMessage('Second bitmap header has to have 40 bytes');
728 Exit;
729 end;
730 if not (tempd[28] = 24) then
731 begin
732 Result := False;
733 ShowMessage('Bitmap has to have 24bits');
734 Exit;
735 end;
736 if not (tempd[30] = 0) then
737 begin
738 Result := False;
739 ShowMessage('Bitmap has to be uncompressed');
740 Exit;
741 end;
742
743 Self.FWidth := tempd[18] + tempd[19] * 256 + tempd[20] * 256 * 256 + tempd[21] * 256 * 256 * 256;
744 Self.FHeight := tempd[22] + tempd[23] * 256 + tempd[24] * 256 * 256 + tempd[25] * 256 * 256 * 256;
745 Self.FDepth := 32;
746 Self.FStoreType := 8;
747
748 SetLength(Self.FData, Self.FWidth * Self.FHeight * Self.FDepth div 8);
749 for y := 0 to Self.FHeight - 1 do
750 begin
751 for x := 0 to Self.FWidth - 1 do
752 begin
753 Self.FData[((Self.FWidth * y + x) * 4) + 0] := tempd[54 + (Self.FWidth * y + x) * 3 + 0];
754 Self.FData[((Self.FWidth * y + x) * 4) + 1] := tempd[54 + (Self.FWidth * y + x) * 3 + 1];
755 Self.FData[((Self.FWidth * y + x) * 4) + 2] := tempd[54 + (Self.FWidth * y + x) * 3 + 2];
756 Self.FData[((Self.FWidth * y + x) * 4) + 3] := 0;
757 end;
758 end;
759
760 Self.FDataType := [DT_Decoded32];
761end;
762
763
764
765
766function TOniImage.WriteToBMP(filename: String): Boolean;
767var
768 filestream: TFileStream;
769 tempd: Tdata;
770begin
771 tempd := Self.GetAsBMP;
772 filestream := TFileStream.Create(filename, fmCreate);
773 filestream.Write(tempd[0], Length(tempd));
774 filestream.Free;
775end;
776
777
778
779
780function TOniImage.GetMipMappedImage(var faded: Tdata): Boolean;
781var
782 i: LongWord;
783 x, y: Word;
784 fadelvldata: Tdata;
785 revert: Boolean;
786begin
787 Result := False;
788
789 // if not (DT_Decoded32 in Self.FDataType) then
790 // Self.DecodeImage;
791 if Self.FStoreType = 9 then
792 Self.DecompressImage;
793 if not (DT_OniReverted in Self.FDataType) then
794 begin
795 revert := True;
796 Self.RevertImage;
797 end
798 else
799 revert := False;
800
801 x := Self.FWidth;
802 y := Self.FHeight;
803 SetLength(faded, x * y * Self.FDepth div 8);
804 SetLength(fadelvldata, x * y * Self.FDepth div 8);
805 for i := 0 to Length(faded) - 1 do
806 begin
807 faded[i] := Self.FData[i];
808 fadelvldata[i] := Self.FData[i];
809 end;
810 repeat
811 fadelvldata := Self.ResizeImage(x, y, fadelvldata);
812 x := x div 2;
813 y := y div 2;
814 SetLength(faded, Length(faded) + x * y * Self.FDepth div 8);
815 for i := 0 to Length(fadelvldata) - 1 do
816 faded[Length(faded) - x * y * Self.FDepth div 8 + i] := fadelvldata[i];
817 until (x = 1) or (y = 1) or ((x mod 2) = 1) or ((y mod 2) = 1);
818 if (x > 1) and (y > 1) then
819 Exit;
820 Result := True;
821
822 if revert then
823 Self.RevertImage;
824end;
825
826
827end.
Note: See TracBrowser for help on using the repository browser.