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

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