source: oup/current/Code_OniImgClass.pas @ 43

Last change on this file since 43 was 43, checked in by alloc, 17 years ago

DevTree 0.33a.

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