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

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