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

Last change on this file since 113 was 113, checked in by alloc, 18 years ago
File size: 26.6 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: // 16bit, RGB444, A4?
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: // 16bit, RGB555, A1?
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 8: // 32bit, RGB888, A8?
182 begin end;
183 9: // Compressed, RGB565
184 begin
185 DecompressImage;
186 end;
187 end;
188 Self.FDepth := 32;
189 if (Self.FStoreType <> 9) and (Self.FStoreType <> 8) then
190 begin
191 SetLength(Self.FData, Length(tempd));
192 for x := 0 to High(tempd) do
193 Self.FData[x] := tempd[x];
194 end;
195 Self.FStoreType := 8;
196 if DT_Oni in Self.FDataType then
197 Self.FDataType := Self.FDataType - [DT_Oni];
198 Self.FDataType := Self.FDataType + [DT_Decoded32];
199 end;
200 if DT_OniReverted in Self.FDataType then
201 Self.RevertImage;
202end;
203
204
205
206
207procedure TOniImage.DecompressImage;
208type
209 Tcolor = record
210 RGBb: Byte;
211 RGBg: Byte;
212 RGBr: Byte;
213 RGBa: Byte;
214 end;
215var
216 i, j, x, y: Integer;
217 color: array[1..4] of Tcolor;
218 pixel: array[1..16] of Byte;
219 tempd: TByteData;
220begin
221 x := 0;
222 y := 0;
223 SetLength(tempd, Self.FWidth * Self.FHeight * 4);
224 for i := 0 to ((Self.FWidth * Self.FHeight) div 16) - 1 do
225 begin
226 Color[1].RGBb := Round(((Self.FData[(i * 8) + 0] + Self.FData[(i * 8) + 1] * 256) and $001F) /
227 $001F * 255);
228 Color[1].RGBg := Round(((Self.FData[(i * 8) + 0] + Self.FData[(i * 8) + 1] * 256) and $07E0) /
229 $07E0 * 255);
230 Color[1].RGBr := Round(((Self.FData[(i * 8) + 0] + Self.FData[(i * 8) + 1] * 256) and $F800) /
231 $F800 * 255);
232 Color[1].RGBa := 255;
233 Color[2].RGBb := Round(((Self.FData[(i * 8) + 2] + Self.FData[(i * 8) + 3] * 256) and $001F) /
234 $001F * 255);
235 Color[2].RGBg := Round(((Self.FData[(i * 8) + 2] + Self.FData[(i * 8) + 3] * 256) and $07E0) /
236 $07E0 * 255);
237 Color[2].RGBr := Round(((Self.FData[(i * 8) + 2] + Self.FData[(i * 8) + 3] * 256) and $F800) /
238 $F800 * 255);
239 Color[2].RGBa := 255;
240 Color[3].RGBb := Round(Color[1].RGBb / 3 * 2 + Color[2].RGBb / 3);
241 Color[3].RGBg := Round(Color[1].RGBg / 3 * 2 + Color[2].RGBg / 3);
242 Color[3].RGBr := Round(Color[1].RGBr / 3 * 2 + Color[2].RGBr / 3);
243 Color[3].RGBa := 255;
244 Color[4].RGBb := Round(Color[1].RGBb / 3 + Color[2].RGBb / 3 * 2);
245 Color[4].RGBg := Round(Color[1].RGBg / 3 + Color[2].RGBg / 3 * 2);
246 Color[4].RGBr := Round(Color[1].RGBr / 3 + Color[2].RGBr / 3 * 2);
247 Color[4].RGBa := 255;
248 Pixel[1] := Round((Self.FData[(i * 8) + 4] and $C0) / $40 + 1);
249 Pixel[2] := Round((Self.FData[(i * 8) + 4] and $30) / $10 + 1);
250 Pixel[3] := Round((Self.FData[(i * 8) + 4] and $0C) / $04 + 1);
251 Pixel[4] := Round((Self.FData[(i * 8) + 4] and $03) + 1);
252 Pixel[5] := Round((Self.FData[(i * 8) + 5] and $C0) / $40 + 1);
253 Pixel[6] := Round((Self.FData[(i * 8) + 5] and $30) / $10 + 1);
254 Pixel[7] := Round((Self.FData[(i * 8) + 5] and $0C) / $04 + 1);
255 Pixel[8] := Round((Self.FData[(i * 8) + 5] and $03) + 1);
256 Pixel[9] := Round((Self.FData[(i * 8) + 6] and $C0) / $40 + 1);
257 Pixel[10] := Round((Self.FData[(i * 8) + 6] and $30) / $10 + 1);
258 Pixel[11] := Round((Self.FData[(i * 8) + 6] and $0C) / $04 + 1);
259 Pixel[12] := Round((Self.FData[(i * 8) + 6] and $03) + 1);
260 Pixel[13] := Round((Self.FData[(i * 8) + 7] and $C0) / $40 + 1);
261 Pixel[14] := Round((Self.FData[(i * 8) + 7] and $30) / $10 + 1);
262 Pixel[15] := Round((Self.FData[(i * 8) + 7] and $0C) / $04 + 1);
263 Pixel[16] := Round((Self.FData[(i * 8) + 7] and $03) + 1);
264 for j := 0 to 3 do
265 begin
266 tempd[((y + 3) * Self.FWidth + x + j) * 4 + 0] := Color[Pixel[16 - j]].RGBb;
267 tempd[((y + 3) * Self.FWidth + x + j) * 4 + 1] := Color[Pixel[16 - j]].RGBg;
268 tempd[((y + 3) * Self.FWidth + x + j) * 4 + 2] := Color[Pixel[16 - j]].RGBr;
269 tempd[((y + 3) * Self.FWidth + x + j) * 4 + 3] := 0;
270 end;
271 for j := 0 to 3 do
272 begin
273 tempd[((y + 2) * Self.FWidth + x + j) * 4 + 0] := Color[Pixel[12 - j]].RGBb;
274 tempd[((y + 2) * Self.FWidth + x + j) * 4 + 1] := Color[Pixel[12 - j]].RGBg;
275 tempd[((y + 2) * Self.FWidth + x + j) * 4 + 2] := Color[Pixel[12 - j]].RGBr;
276 tempd[((y + 2) * Self.FWidth + x + j) * 4 + 3] := 0;
277 end;
278 for j := 0 to 3 do
279 begin
280 tempd[((y + 1) * Self.FWidth + x + j) * 4 + 0] := Color[Pixel[8 - j]].RGBb;
281 tempd[((y + 1) * Self.FWidth + x + j) * 4 + 1] := Color[Pixel[8 - j]].RGBg;
282 tempd[((y + 1) * Self.FWidth + x + j) * 4 + 2] := Color[Pixel[8 - j]].RGBr;
283 tempd[((y + 1) * Self.FWidth + x + j) * 4 + 3] := 0;
284 end;
285 for j := 0 to 3 do
286 begin
287 tempd[((y + 0) * Self.FWidth + x + j) * 4 + 0] := Color[Pixel[4 - j]].RGBb;
288 tempd[((y + 0) * Self.FWidth + x + j) * 4 + 1] := Color[Pixel[4 - j]].RGBg;
289 tempd[((y + 0) * Self.FWidth + x + j) * 4 + 2] := Color[Pixel[4 - j]].RGBr;
290 tempd[((y + 0) * Self.FWidth + x + j) * 4 + 3] := 0;
291 end;
292 x := x + 4;
293 if x = Self.FWidth then
294 begin
295 y := y + 4;
296 x := 0;
297 end;
298 end;
299 SetLength(Self.FData, Length(tempd));
300 for i := 0 to High(tempd) do
301 Self.FData[i] := tempd[i];
302 Self.FStoreType := 8;
303 Self.FDepth := 32;
304 Self.FDataType := Self.FDataType - [DT_Oni] + [DT_Decoded32];
305end;
306
307
308
309
310
311function TOniImage.Load(ConnectionID, FileID: Integer): Boolean;
312var
313 FileInfo: TFileInfo;
314begin
315 FileInfo := ConManager.Connection[ConnectionID].GetFileInfo(fileid);
316 if FileInfo.Extension = 'PSpc' then
317 Result := LoadFromPSpc(ConnectionID, fileid)
318 else if FileInfo.Extension = 'TXMB' then
319 Result := LoadFromTXMB(ConnectionID, fileid)
320 else if FileInfo.Extension = 'TXMP' then
321 Result := LoadFromTXMP(ConnectionID, fileid)
322 else
323 Result := False;
324end;
325
326
327
328
329function TOniImage.LoadFromPSpc(ConnectionID, FileID: Integer): Boolean;
330type
331 TPoint = packed record
332 X, Y: Word;
333 end;
334
335 TPSpc = packed record
336 p1: array[0..8] of TPoint;
337 p2: array[0..8] of TPoint;
338 TXMP: Integer;
339 end;
340
341 TPart = packed record
342 x_txmp, y_txmp: Word;
343 x_pspc, y_pspc: Word;
344 w, h: Word;
345 imgdata: TByteData;
346 used: Boolean;
347 end;
348const
349 PartMatch: array[0..8] of Byte = (0, 3, 6, 1, 4, 7, 2, 5, 8);
350var
351 x, y, pixel: Word;
352 i: Integer;
353
354 PSpc: TPSpc;
355 txmpimg: TOniImage;
356 txmpdata: TByteData;
357
358 parts: array[0..8] of TPart;
359 part: Byte;
360 cols: array[0..2] of Word;
361 rows: array[0..2] of Word;
362 col, row: Byte;
363begin
364 ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $08, SizeOf(PSpc), @PSpc);
365 PSpc.TXMP := PSpc.TXMP div 256;
366 if PSpc.TXMP = 0 then
367 begin
368 Result := False;
369 Exit;
370 end;
371 txmpimg := TOniImage.Create;
372 txmpimg.LoadFromTXMP(ConnectionID, PSpc.TXMP);
373 txmpimg.DecodeImage;
374// txmpimg.WriteToBMP('C:\file.bmp');
375 txmpimg.GetAs32bit(txmpdata);
376{ ShowMessage(IntToStr(txmpimg.Width)+'x'+IntToStr(txmpimg.Height));
377 for i:=0 to High(txmpdata) do
378 txmpimg.Data[i]:=txmpdata[i];
379 txmpimg.WriteToBMP('D:\file2.bmp');
380}
381 with PSpc do
382 begin
383 for i := 0 to 2 do
384 begin
385 cols[i] := 0;
386 rows[i] := 0;
387 end;
388 for i := 0 to 8 do
389 begin
390 part := PartMatch[i];
391 col := i div 3;
392 row := i mod 3;
393 if (p2[i].X > 0) or (p2[i].Y > 0) then
394 begin
395 parts[part].x_txmp := p1[i].X - 1;
396 parts[part].y_txmp := p1[i].Y - 1;
397 parts[part].x_pspc := 0;
398 if col > 0 then
399 for x := 0 to col - 1 do
400 Inc(parts[part].x_pspc, cols[x]);
401 parts[part].y_pspc := 0;
402 if row > 0 then
403 for y := 0 to row - 1 do
404 Inc(parts[part].y_pspc, rows[y]);
405 parts[part].w := p2[i].X - p1[i].X + 1;
406 parts[part].h := p2[i].Y - p1[i].Y + 1;
407 parts[part].used := True;
408 cols[col] := parts[part].w;
409 rows[row] := parts[part].h;
410 SetLength(parts[part].imgdata, parts[part].w * parts[part].h * 4);
411 for y := 0 to parts[part].h - 1 do
412 begin
413 for x := 0 to parts[part].w - 1 do
414 begin
415 for pixel := 0 to 3 do
416 begin
417 parts[part].imgdata[(y * parts[part].w + x) * 4 + pixel] :=
418 txmpdata[((parts[part].y_txmp + y) * txmpimg.Width +
419 parts[part].x_txmp + x) * 4 + pixel];
420 end;
421 end;
422 end;
423 end
424 else
425 begin
426 parts[part].used := False;
427 end;
428 end;
429
430 end;
431
432 txmpimg.Free;
433 txmpimg := TOniImage.Create;
434 for i := 0 to 8 do
435 begin
436 if parts[i].used then
437 begin
438 SetLength(txmpimg.FData, Length(parts[i].imgdata));
439 for pixel := 0 to High(parts[i].imgdata) do
440 txmpimg.Data[pixel] := parts[i].imgdata[pixel];
441 txmpimg.Width := parts[i].w;
442 txmpimg.Height := parts[i].h;
443 txmpimg.StoreType := 8;
444 txmpimg.DataType := [DT_Decoded32];
445 txmpimg.Depth := 32;
446 txmpimg.WriteToBMP('M:\' + IntToStr(i) + '.bmp');
447 end;
448 end;
449 txmpimg.Free;
450
451 Self.FWidth := 0;
452 Self.FHeight := 0;
453 for i := 0 to 2 do
454 begin
455 Inc(Self.FWidth, cols[i]);
456 Inc(Self.FHeight, rows[i]);
457 end;
458 SetLength(Self.FData, Self.FWidth * Self.FHeight * 4);
459
460 //Combine data parts
461
462 Self.FDepth := 32;
463 Self.FStoreType := 8;
464 Self.FDataType := [DT_Decoded32];
465 // Self.RevertImage;
466end;
467
468
469
470
471function TOniImage.LoadFromTXMP(ConnectionID, FileID: Integer): Boolean;
472var
473 img_addr: Integer;
474begin
475 Result := True;
476 ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $8C, SizeOf(Self.FWidth), @Self.FWidth);
477 ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $8E, SizeOf(Self.FHeight), @Self.FHeight);
478 ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $90, SizeOf(Self.FStoreType),
479 @Self.FStoreType);
480 if ConManager.Connection[ConnectionID].DataOS = DOS_WIN then
481 ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $9C, SizeOf(img_addr), @img_addr)
482 else
483 ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $A0, SizeOf(img_addr), @img_addr);
484
485 case Self.FStoreType of
486 0, 1, 2:
487 begin
488 SetLength(Self.FData, Self.FWidth * Self.FHeight * 2);
489 Self.FDepth := 16;
490 end;
491 8:
492 begin
493 SetLength(Self.FData, Self.FWidth * Self.FHeight * 4);
494 Self.FDepth := 32;
495 end;
496 9:
497 begin
498 SetLength(Self.FData, Self.FWidth * Self.FHeight div 2);
499 Self.FDepth := 16;
500 end;
501 else
502 Result := False;
503 Exit;
504 end;
505
506 if ConManager.Connection[ConnectionID].DataOS = DOS_WIN then
507 ConManager.Connection[ConnectionID].LoadRawFile(fileid, $9C, FData)
508 else
509 ConManager.Connection[ConnectionID].LoadRawFile(fileid, $A0, FData);
510
511 Self.FDataType := [DT_OniReverted, DT_Oni];
512end;
513
514
515
516
517function TOniImage.LoadFromTXMB(ConnectionID, FileID: Integer): Boolean;
518var
519 i, x, y, x2, y2, pixelid, imgid: Integer;
520 rows, cols: Word;
521 linkcount: Integer;
522 link: Integer;
523 images_decoded: array of TOniImage;
524 x_start, y_start: Integer;
525begin
526 ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $10, SizeOf(Self.FWidth), @Self.FWidth);
527 ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $12, SizeOf(Self.FHeight), @Self.FHeight);
528 ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $18, SizeOf(cols), @cols);
529 ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $1A, SizeOf(rows), @rows);
530 ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $1C, SizeOf(linkcount), @linkcount);
531 SetLength(images_decoded, linkcount);
532 for i := 0 to linkcount - 1 do
533 begin
534 ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $20 + i * 4, SizeOf(link), @link);
535 link := link div 256;
536 images_decoded[i] := TOniImage.Create;
537 images_decoded[i].LoadFromTXMP(ConnectionID, link);
538 images_decoded[i].DecodeImage;
539 images_decoded[i].RevertImage;
540 end;
541 SetLength(Self.FData, Self.FWidth * Self.FHeight * 4);
542 for y := 0 to rows - 1 do
543 begin
544 for x := 0 to cols - 1 do
545 begin
546 imgid := y * cols + x;
547 x_start := 0;
548 y_start := 0;
549 for i := 0 to x do
550 if i < x then
551 x_start := x_start + images_decoded[i].Width;
552 for i := 0 to y do
553 if i < y then
554 y_start := y_start + images_decoded[i].Height;
555 for y2 := 0 to images_decoded[imgid].Height - 1 do
556 begin
557 for x2 := 0 to images_decoded[imgid].Width - 1 do
558 begin
559 if ((x_start + x2) < Self.FWidth) and ((y_start + y2) < Self.FHeight) then
560 begin
561 pixelid := y_start * Self.FWidth + x_start + y2 * Self.FWidth + x2;
562 Self.FData[pixelid * 4 + 0] :=
563 images_decoded[imgid].Data[(y2 * images_decoded[imgid].Width + x2) * 4 + 0];
564 Self.FData[pixelid * 4 + 1] :=
565 images_decoded[imgid].Data[(y2 * images_decoded[imgid].Width + x2) * 4 + 1];
566 Self.FData[pixelid * 4 + 2] :=
567 images_decoded[imgid].Data[(y2 * images_decoded[imgid].Width + x2) * 4 + 2];
568 Self.FData[pixelid * 4 + 3] :=
569 images_decoded[imgid].Data[(y2 * images_decoded[imgid].Width + x2) * 4 + 3];
570 end;
571 end;
572 end;
573 end;
574 end;
575 for i := 0 to linkcount - 1 do
576 images_decoded[i].Free;
577 Self.FDepth := 32;
578 Self.FStoreType := 8;
579 Self.FDataType := [DT_Decoded32];
580 Self.RevertImage;
581end;
582
583
584
585
586function TOniImage.GetImageDataSize(fading: Boolean): Integer;
587var
588 size: Integer;
589 x, y: Word;
590 bpp: Byte;
591begin
592 case Self.FStoreType of
593 9:
594 bpp := 8;
595 0, 1, 2:
596 bpp := 16;
597 8:
598 bpp := 32;
599 else
600 Result := 0;
601 Exit;
602 end;
603
604 x := Self.FWidth;
605 y := Self.FHeight;
606 size := x * y * bpp div 8;
607 if fading then
608 begin
609 repeat
610 x := x div 2;
611 y := y div 2;
612 size := size + x * y * bpp div 8;
613 until (x = 1) or (y = 1);
614 end;
615 Result := size;
616end;
617
618
619
620
621procedure TOniImage.GetAsData(var Target: TStream);
622var
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.