source: oup/rewrite/Global/OniImgClass.pas@ 99

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