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

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