source: oup/current/Global/OniImgClass.pas@ 111

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