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

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