source: oup/rewrite/Global/OniImgClass.pas @ 105

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