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

Last change on this file since 171 was 128, checked in by alloc, 18 years ago
File size: 26.7 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 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
40 procedure DecodeImageTo32bit;
41
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;
47 procedure GetAsBMP(var Target: TByteData); overload;
48 function LoadFromBMP(filename: String): Boolean;
49 function WriteToBMP(filename: String): Boolean;
50 function GetMipMappedImage(var Target: TStream): Boolean; overload;
51 function GetMipMappedImage(var Target: TByteData): Boolean; overload;
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
135procedure TOniImage.DecodeImageTo32bit;
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
144 0: // 16bit, RGB444, A4?
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;
163 1, 2: // 16bit, RGB555, A1?
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;
182 8: // 32bit, RGB888, A8?
183 begin end;
184 9: // Compressed, RGB565
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);
374 txmpimg.DecodeImageTo32bit;
375// txmpimg.WriteToBMP('C:\file.bmp');
376 txmpimg.GetAs32bit(txmpdata);
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);
539 images_decoded[i].DecodeImageTo32bit;
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
592 function GetImgSize(w,h, storetype: Integer): Integer;
593 begin
594 case storetype of
595 0, 1, 2:
596 Result := w*h*2;
597 8:
598 Result := w*h*4;
599 9:
600 Result := Max(1, w div 4) * Max(1, h div 4) * 8;
601 else
602 Result := -1;
603 end;
604 end;
605
606begin
607 x := Self.FWidth;
608 y := Self.FHeight;
609 size := GetImgSize(x, y, FStoreType);
610 if fading then
611 begin
612 repeat
613 x := Max(x div 2, 1);
614 y := Max(y div 2, 1);
615 size := size + GetImgSize(x, y, FStoreType);
616 until (x = 1) and (y = 1);
617 end;
618 Result := size;
619end;
620
621
622
623
624procedure TOniImage.GetAsData(var Target: TStream);
625var
626 revert: Boolean;
627begin
628 // if not (DT_Decoded32 in Self.FDataType) then
629 // Self.DecodeImage;
630 if not (DT_OniReverted in Self.FDataType) then
631 begin
632 revert := True;
633 Self.RevertImage;
634 end
635 else
636 revert := False;
637 if not Assigned(Target) then
638 Target := TMemoryStream.Create;
639 Target.Write(FData[0], Length(FData));
640 Target.Seek(0, soFromBeginning);
641 if revert then
642 Self.RevertImage;
643end;
644
645procedure TOniImage.GetAsData(var Target: TByteData);
646var
647 mem: TStream;
648begin
649 mem := TMemoryStream.Create;
650 GetAsData(mem);
651 SetLength(Target, mem.Size);
652 mem.Read(Target[0], mem.Size);
653 mem.Free;
654end;
655
656
657procedure TOniImage.GetAs32bit(var Target: TStream);
658begin
659 if not (DT_Decoded32 in Self.FDataType) then
660 Self.DecodeImageTo32bit;
661 if not Assigned(Target) then
662 Target := TMemoryStream.Create;
663 Target.Write(FData[0], Length(FData));
664 Target.Seek(0, soFromBeginning);
665end;
666
667procedure TOniImage.GetAs32bit(var Target: TByteData);
668var
669 mem: TStream;
670begin
671 mem := TMemoryStream.Create;
672 GetAs32bit(mem);
673 SetLength(Target, mem.Size);
674 mem.Read(Target[0], mem.Size);
675 mem.Free;
676end;
677
678
679procedure TOniImage.GetAsBMP(var Target: TByteData);
680const
681 BMPheader: array[0..53] of Byte =
682 ($42, $4D, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0,
683 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,
684 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
685var
686 i, x, y: Integer;
687begin
688 if not (DT_Decoded32 in Self.FDataType) then
689 Self.DecodeImageTo32bit;
690
691 SetLength(Target, Self.FWidth * Self.FHeight * 3 + 54);
692 for y := 0 to Self.FHeight - 1 do
693 begin
694 for x := 0 to Self.FWidth - 1 do
695 begin
696 Target[((Self.FWidth * y + x) * 3) + 0 + 54] := Self.FData[(Self.FWidth * y + x) * 4 + 0];
697 Target[((Self.FWidth * y + x) * 3) + 1 + 54] := Self.FData[(Self.FWidth * y + x) * 4 + 1];
698 Target[((Self.FWidth * y + x) * 3) + 2 + 54] := Self.FData[(Self.FWidth * y + x) * 4 + 2];
699 end;
700 end;
701
702 for i := 0 to High(BMPheader) do
703 Target[i] := BMPheader[i];
704 Target[2] := ((Self.FWidth * Self.FHeight * 3 + 54) and $000000FF) div $1;
705 Target[3] := ((Self.FWidth * Self.FHeight * 3 + 54) and $0000FF00) div $100;
706 Target[4] := ((Self.FWidth * Self.FHeight * 3 + 54) and $00FF0000) div $10000;
707 Target[5] := ((Self.FWidth * Self.FHeight * 3 + 54) and $FF000000) div $1000000;
708 Target[18] := (Self.FWidth and $000000FF) div $1;
709 Target[19] := (Self.FWidth and $0000FF00) div $100;
710 Target[20] := (Self.FWidth and $00FF0000) div $10000;
711 Target[21] := (Self.FWidth and $FF000000) div $1000000;
712 Target[22] := (Self.FHeight and $000000FF) div $1;
713 Target[23] := (Self.FHeight and $0000FF00) div $100;
714 Target[24] := (Self.FHeight and $00FF0000) div $10000;
715 Target[25] := (Self.FHeight and $FF000000) div $1000000;
716 Target[34] := ((Self.FWidth * Self.FHeight * 3) and $000000FF) div $1;
717 Target[35] := ((Self.FWidth * Self.FHeight * 3) and $0000FF00) div $100;
718 Target[36] := ((Self.FWidth * Self.FHeight * 3) and $00FF0000) div $10000;
719 Target[37] := ((Self.FWidth * Self.FHeight * 3) and $FF000000) div $1000000;
720end;
721
722
723procedure TOniImage.GetAsBMP(var Target: TStream);
724var
725 data: TByteData;
726 streampos: Integer;
727begin
728 GetAsBMP(data);
729 streampos := Target.Position;
730 Target.Write(data[0], Length(data));
731 Target.Seek(streampos, soFromBeginning);
732end;
733
734
735function TOniImage.LoadFromBMP(filename: String): Boolean;
736var
737 filestream: TFileStream;
738 tempd: TByteData;
739
740 x, y: Integer;
741begin
742 filestream := TFileStream.Create(filename, fmOpenRead);
743 SetLength(tempd, filestream.Size);
744 filestream.Read(tempd[0], filestream.Size);
745 filestream.Free;
746
747 if not ((tempd[00] = $42) and (tempd[01] = $4D)) then
748 begin
749 Result := False;
750 ShowMessage('Not a standard 24bit bitmap');
751 Exit;
752 end;
753 if not (tempd[10] = 54) then
754 begin
755 Result := False;
756 ShowMessage('Imagedata has to start at 0x54');
757 Exit;
758 end;
759 if not (tempd[14] = 40) then
760 begin
761 Result := False;
762 ShowMessage('Second bitmap header has to have 40 bytes');
763 Exit;
764 end;
765 if not (tempd[28] = 24) then
766 begin
767 Result := False;
768 ShowMessage('Bitmap has to have 24bits');
769 Exit;
770 end;
771 if not (tempd[30] = 0) then
772 begin
773 Result := False;
774 ShowMessage('Bitmap has to be uncompressed');
775 Exit;
776 end;
777
778 Self.FWidth := tempd[18] + tempd[19] * 256 + tempd[20] * 256 * 256 + tempd[21] * 256 * 256 * 256;
779 Self.FHeight := tempd[22] + tempd[23] * 256 + tempd[24] * 256 * 256 + tempd[25] * 256 * 256 * 256;
780 Self.FDepth := 32;
781 Self.FStoreType := 8;
782
783 SetLength(Self.FData, Self.FWidth * Self.FHeight * Self.FDepth div 8);
784 for y := 0 to Self.FHeight - 1 do
785 begin
786 for x := 0 to Self.FWidth - 1 do
787 begin
788 Self.FData[((Self.FWidth * y + x) * 4) + 0] := tempd[54 + (Self.FWidth * y + x) * 3 + 0];
789 Self.FData[((Self.FWidth * y + x) * 4) + 1] := tempd[54 + (Self.FWidth * y + x) * 3 + 1];
790 Self.FData[((Self.FWidth * y + x) * 4) + 2] := tempd[54 + (Self.FWidth * y + x) * 3 + 2];
791 Self.FData[((Self.FWidth * y + x) * 4) + 3] := 0;
792 end;
793 end;
794
795 Self.FDataType := [DT_Decoded32];
796end;
797
798
799
800
801function TOniImage.WriteToBMP(filename: String): Boolean;
802var
803 filestream: TFileStream;
804begin
805 filestream := TFileStream.Create(filename, fmCreate);
806 GetAsBMP(TStream(filestream));
807 filestream.Free;
808end;
809
810
811
812function TOniImage.GetMipMappedImage(var Target: TByteData): Boolean;
813var
814 i: Integer;
815 x, y: Word;
816 fadelvldata: TByteData;
817 revert: Boolean;
818begin
819 Result := False;
820
821 // if not (DT_Decoded32 in Self.FDataType) then
822 // Self.DecodeImage;
823 if Self.FStoreType = 9 then
824 Self.DecompressImage;
825 if not (DT_OniReverted in Self.FDataType) then
826 begin
827 revert := True;
828 Self.RevertImage;
829 end
830 else
831 revert := False;
832
833 x := Self.FWidth;
834 y := Self.FHeight;
835 SetLength(Target, x * y * Self.FDepth div 8);
836 SetLength(fadelvldata, x * y * Self.FDepth div 8);
837 for i := 0 to Length(Target) - 1 do
838 begin
839 Target[i] := Self.FData[i];
840 fadelvldata[i] := Self.FData[i];
841 end;
842 repeat
843 fadelvldata := Self.ResizeImage(x, y, fadelvldata);
844 x := x div 2;
845 y := y div 2;
846 SetLength(Target, Length(Target) + x * y * Self.FDepth div 8);
847 for i := 0 to Length(fadelvldata) - 1 do
848 Target[Length(Target) - x * y * Self.FDepth div 8 + i] := fadelvldata[i];
849 until (x = 1) or (y = 1) or ((x mod 2) = 1) or ((y mod 2) = 1);
850 if (x > 1) and (y > 1) then
851 Exit;
852 Result := True;
853
854 if revert then
855 Self.RevertImage;
856end;
857
858
859function TOniImage.GetMipMappedImage(var Target: TStream): Boolean;
860var
861 data: TByteData;
862 streampos: Integer;
863begin
864 Result := GetMipMappedImage(data);
865 if not Assigned(Target) then
866 Target := TMemoryStream.Create;
867 streampos := Target.Position;
868 Target.Write(data[0], Length(data));
869 Target.Seek(streampos, soFromBeginning);
870end;
871
872
873end.
Note: See TracBrowser for help on using the repository browser.