ViewVC Help
View File | Revision Log | View Changeset | Root Listing
root/Oni2/oup/current/Global/OniImgClass.pas
(Generate patch)

Comparing oup/current/Global/OniImgClass.pas (file contents):
Revision 181 by alloc, Sat May 19 17:54:34 2007 UTC vs.
Revision 244 by alloc, Fri Aug 17 21:09:51 2007 UTC

# Line 3 | Line 3 | unit OniImgClass;
3   interface
4  
5   uses Math, Dialogs, Types, SysUtils, Classes, Data, ConnectionManager, TypeDefs,
6 <  Imaging, ImagingTypes;
7 <
8 < type
9 <  TImgDataType = set of (DT_OniReverted, DT_Oni, DT_Decoded32);
6 >  Imaging, ImagingTypes, Graphics;
7  
8  
9   type
10    TOniImage = class
11    private
12 <    FLoaded:    Boolean;
13 <    FDataType:  TImgDataType;
14 <    FData:      TByteData;
15 <    FWidth, FHeight: Word;
16 <    FDepth:     Byte;
17 <    FStoreType: Byte;
18 <
19 <    FImage:     TImageData;
23 <
24 <    function ResizeImage(oldx, oldy: Integer; img: TByteData): TByteData;
25 <    procedure RevertImage;
26 <    procedure DecompressImage;
12 >    FImages: TDynImageDataArray;
13 >    function GetImage(MipGen: Integer): TImageData;
14 >    function GetWidth(MipGen: Integer): Integer;
15 >    function GetHeight(MipGen: Integer): Integer;
16 >    function GetImageFormat: TImageFormat;
17 >    procedure SetImageFormat(Format: TImageFormat);
18 >    function pGetImageFormatInfo: TImageFormatInfo;
19 >    function GetHasMipMaps: Boolean;
20    protected
21    public
22 <    property Image:     TImageData   Read FImage     Write FImage;
23 <    property Loaded:    Boolean      Read FLoaded    Write FLoaded;
24 <    property DataType:  TImgDataType Read FDataType  Write FDataType;
25 <    property Width:     Word         Read FWidth     Write FWidth;
26 <    property Height:    Word         Read FHeight    Write FHeight;
27 <    property Depth:     Byte         Read FDepth     Write FDepth;
28 <    property StoreType: Byte         Read FStoreType Write FStoreType;
36 <    property Data:      TByteData    Read FData      Write FData;
22 >    property Images: TDynImageDataArray         read FImages;
23 >    property Image[MipGen: Integer]: TImageData read GetImage;
24 >    property Width[MipGen: Integer]: Integer    read GetWidth;
25 >    property Height[MipGen: Integer]: Integer   read GetHeight;
26 >    property Format: TImageFormat read GetImageFormat write SetImageFormat;
27 >    property FormatInfo: TImageFormatInfo read pGetImageFormatInfo;
28 >    property HasMipMaps: Boolean read GetHasMipMaps;
29  
30      constructor Create;
31 +    procedure Free;
32 +
33 +    function GetImageSize(MipMaps: Boolean): Integer;
34 +
35 +    function LoadFromFile(filename: String): Boolean;
36 +    function WriteToFile(filename: String): Boolean;
37 +    procedure SaveDataToStream(MipMaps: Boolean; var Target: TStream);
38 +    procedure DrawOnCanvas(Canvas: TCanvas; Index: Integer);
39 +
40      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;
43 >    function LoadFromPSpc(ConnectionID, FileID: Integer): Boolean;
44    published
45    end;
46  
47  
48   implementation
49  
50 < //uses Functions;
65 < uses Img_DDSTypes;
50 > uses Img_DDSTypes, ImagingComponents;
51  
52  
53 < constructor TOniImage.Create;
53 > function TOniImage.GetImage(MipGen: Integer): TImageData;
54   begin
55 <  Self.FLoaded   := False;
56 <  Self.FDataType := [];
57 <  SetLength(Self.FData, 0);
58 <  Self.FWidth     := 0;
59 <  Self.FHeight    := 0;
75 <  Self.FDepth     := 0;
76 <  Self.FStoreType := 0;
77 <
78 <  InitImage(FImage);
55 >  if MipGen <= Length(FImages) then
56 >  begin
57 >    InitImage(Result);
58 >    CloneImage(FImages[MipGen-1], Result);
59 >  end;
60   end;
61  
62  
63 + function TOniImage.GetWidth(MipGen: Integer): Integer;
64 + begin
65 +  if MipGen <= Length(FImages) then
66 +    Result := FImages[MipGen-1].Width
67 +  else
68 +    Result := -1;
69 + end;
70  
71  
72 < function TOniImage.ResizeImage(oldx, oldy: Integer; img: TByteData): TByteData;
85 < var
86 <  i, j: Integer;
87 <  col, row, row_orig: Integer;
72 > function TOniImage.GetHeight(MipGen: Integer): Integer;
73   begin
74 <  SetLength(Result, (oldx div 2) * (oldy div 2) * (Self.FDepth div 8));
75 <  row_orig := 0;
76 <  row      := 0;
77 <  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;
74 >  if MipGen <= Length(FImages) then
75 >    Result := FImages[MipGen-1].Height
76 >  else
77 >    Result := -1;
78   end;
79  
80  
81 + function TOniImage.GetImageFormat: TImageFormat;
82 + begin
83 +  if Length(FImages) > 0 then
84 +    Result := FImages[0].Format
85 +  else
86 +    Result := ifUnknown;
87 + end;
88  
89 <
120 < procedure TOniImage.RevertImage;
89 > procedure TOniImage.SetImageFormat(Format: TImageFormat);
90   var
91 <  x, y, i: Integer;
123 <  tempd:   TByteData;
91 >  i: Integer;
92   begin
93 <  SetLength(tempd, Self.FWidth * Self.FHeight * (Self.FDepth div 8));
94 <  for y := 0 to Self.FHeight - 1 do
95 <    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];
93 >  if Length(FImages) > 0 then
94 >    for i := 0 to High(FImages) do
95 >      ConvertImage(FImages[i], Format);
96   end;
97  
98  
99 + function TOniImage.pGetImageFormatInfo: TImageFormatInfo;
100 + begin
101 +  if Length(FImages) > 0 then
102 +    GetImageFormatInfo(FImages[0].Format, Result);
103 + end;
104  
105  
106 < procedure TOniImage.DecodeImageTo32bit;
143 < var
144 <  x, y:  Integer;
145 <  tempd: TByteData;
106 > function TOniImage.GetHasMipMaps: Boolean;
107   begin
108 <  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;
108 >  Result := Length(FImages) > 1;
109   end;
110  
111  
112  
113  
114 < procedure TOniImage.DecompressImage;
216 < type
217 <  Tcolor = record
218 <    RGBb: Byte;
219 <    RGBg: Byte;
220 <    RGBr: Byte;
221 <    RGBa: Byte;
222 <  end;
223 < var
224 <  i, j, x, y: Integer;
225 <  color:      array[1..4] of Tcolor;
226 <  pixel:      array[1..16] of Byte;
227 <  tempd:      TByteData;
114 > constructor TOniImage.Create;
115   begin
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];
116   end;
117  
118 + procedure TOniImage.Free;
119 + begin
120 +  FreeImagesInArray(FImages);
121 + end;
122  
123  
124  
125  
126 < function TOniImage.Load(ConnectionID, FileID: Integer): Boolean;
126 > function TOniImage.GetImageSize(MipMaps: Boolean): Integer;
127   var
128 <  FileInfo: TFileInfo;
128 >  i: Integer;
129   begin
130 <  FileInfo := ConManager.Connection[ConnectionID].GetFileInfo(fileid);
131 <  if FileInfo.Extension = 'PSpc' then
132 <    Result := LoadFromPSpc(ConnectionID, fileid)
133 <  else if FileInfo.Extension = 'TXMB' then
134 <    Result := LoadFromTXMB(ConnectionID, fileid)
135 <  else if FileInfo.Extension = 'TXMP' then
136 <    Result := LoadFromTXMP(ConnectionID, fileid)
130 >  if Length(FImages) > 0 then
131 >  begin
132 >    Result := FImages[0].Size;
133 >    if mipmaps then
134 >      for i := 1 to High(FImages) do
135 >        Result := Result + FImages[i].Size;
136 >  end
137    else
138 <    Result := False;
138 >    Result := -1;
139   end;
140  
141  
142  
143  
144 < function TOniImage.LoadFromPSpc(ConnectionID, FileID: Integer): Boolean;
145 < type
146 <  TPoint = packed record
147 <    X, Y: Word;
148 <  end;
144 > function TOniImage.LoadFromFile(filename: String): Boolean;
145 > begin
146 >  Result := LoadMultiImageFromFile(filename, FImages);
147 >  if not Result then
148 >    ShowMessage('Couldn''t load image file');
149 > end;
150  
343  TPSpc = packed record
344    p1:   array[0..8] of TPoint;
345    p2:   array[0..8] of TPoint;
346    TXMP: Integer;
347  end;
151  
152 <  TPart = packed record
153 <    x_txmp, y_txmp: Word;
154 <    x_pspc, y_pspc: Word;
155 <    w, h:    Word;
156 <    imgdata: TByteData;
157 <    used:    Boolean;
158 <  end;
159 < const
357 <  PartMatch: array[0..8] of Byte = (0, 3, 6, 1, 4, 7, 2, 5, 8);
152 > function TOniImage.WriteToFile(filename: String): Boolean;
153 > begin
154 >  Result := SaveMultiImageToFile(filename, FImages);
155 > end;
156 >
157 >
158 >
159 > procedure TOniImage.DrawOnCanvas(Canvas: TCanvas; Index: Integer);
160   var
161 <  x, y, pixel: Word;
162 <  i: Integer;
161 >  singleimg: TImageData;
162 >  rect: TRect;
163 > begin
164 >  InitImage(singleimg);
165 >  CloneImage(FImages[Index-1], singleimg);
166 >  ConvertImage(singleimg, ifX8R8G8B8);
167 >  rect.Left := 0;
168 >  rect.Top := 0;
169 >  rect.Right := singleimg.Width - 1;
170 >  rect.Bottom := singleimg.Height - 1;
171 >  Canvas.Brush.Color := $C8D0D4;
172 >  Canvas.FillRect(Canvas.ClipRect);
173 >  DisplayImageData(Canvas, rect, singleimg, rect);
174 >  FreeImage(singleimg);
175 > end;
176  
362  PSpc:     TPSpc;
363  txmpimg:  TOniImage;
364  txmpdata: TByteData;
177  
178 <  parts:    array[0..8] of TPart;
179 <  part:     Byte;
180 <  cols:     array[0..2] of Word;
181 <  rows:     array[0..2] of Word;
182 <  col, row: Byte;
178 >
179 >
180 > procedure TOniImage.SaveDataToStream(MipMaps: Boolean; var Target: TStream);
181 > var
182 >  images: TDynImageDataArray;
183 >  mem: TMemoryStream;
184 >  i: Integer;
185   begin
186 <  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;
186 >  if Length(FImages) = 0 then
187      Exit;
188 <  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
188 >  if MipMaps then
189    begin
190 <    for i := 0 to 2 do
190 >    if Length(FImages) = 1 then
191      begin
192 <      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
192 >      if not GenerateMipMaps(FImages[0], 0, images) then
193        begin
194 <        parts[part].x_txmp := p1[i].X - 1;
195 <        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;
194 >        ShowMessage('Could not generate MipMaps');
195 >        Exit;
196        end;
197 +    end
198 +    else
199 +    begin
200 +      SetLength(images, Length(FImages));
201 +      for i := 0 to High(FImages) do
202 +        CloneImage(FImages[i], images[i]);
203      end;
204 <
205 <  end;
206 <
207 <  txmpimg.Free;
208 <  txmpimg := TOniImage.Create;
209 <  for i := 0 to 8 do
204 >    mem := TMemoryStream.Create;
205 >    if not SaveMultiImageToStream('dds', mem, images) then
206 >    begin
207 >      ShowMessage('Could not save images to stream');
208 >      Exit;
209 >    end;
210 >    FreeImagesInArray(images);
211 >  end
212 >  else
213    begin
214 <    if parts[i].used then
214 >    mem := TMemoryStream.Create;
215 >    if not SaveImageToStream('dds', mem, FImages[0]) then
216      begin
217 <      SetLength(txmpimg.FData, Length(parts[i].imgdata));
218 <      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');
217 >      ShowMessage('Could not save image to stream');
218 >      Exit;
219      end;
220    end;
221 <  txmpimg.Free;
221 >  if not Assigned(Target) then
222 >    Target := TMemoryStream.Create;
223 >
224 >  mem.Seek(128, soFromBeginning);
225 >  Target.CopyFrom(mem, mem.Size - 128);
226 >  mem.Free;
227 >  Target.Seek(0, soFromBeginning);
228 > end;
229  
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);
230  
468  //Combine data parts
231  
232 <  Self.FDepth     := 32;
233 <  Self.FStoreType := 8;
234 <  Self.FDataType  := [DT_Decoded32];
235 <  //    Self.RevertImage;
232 >
233 >
234 > function TOniImage.Load(ConnectionID, FileID: Integer): Boolean;
235 > var
236 >  FileInfo: TFileInfo;
237 > begin
238 >  FileInfo := ConManager.Connection[ConnectionID].GetFileInfo(fileid);
239 >  if FileInfo.Extension = 'PSpc' then
240 >    Result := LoadFromPSpc(ConnectionID, fileid)
241 >  else if FileInfo.Extension = 'TXMB' then
242 >    Result := LoadFromTXMB(ConnectionID, fileid)
243 >  else if FileInfo.Extension = 'TXMP' then
244 >    Result := LoadFromTXMP(ConnectionID, fileid)
245 >  else
246 >    Result := False;
247   end;
248  
249  
# Line 483 | Line 256 | var
256    hdr: TDDSDXTHeader;
257    imginfo: Integer;
258    x,y, i: Integer;
259 +
260 +  _width, _height: Word;
261 +  _storetype: Byte;
262 +  _depth: Byte;
263   begin
264 <  Result := True;
265 <  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $8C, SizeOf(Self.FWidth), @Self.FWidth);
266 <  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $8E, SizeOf(Self.FHeight), @Self.FHeight);
267 <  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $90, SizeOf(Self.FStoreType), @Self.FStoreType);
264 >  Result := False;
265 >  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $8C, SizeOf(_width), @_width);
266 >  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $8E, SizeOf(_height), @_height);
267 >  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $90, SizeOf(_storetype), @_storetype);
268    ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $88, SizeOf(imginfo), @imginfo);
269    if ConManager.Connection[ConnectionID].DataOS = DOS_WIN then
270      ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $9C, SizeOf(img_addr), @img_addr)
271    else
272      ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $A0, SizeOf(img_addr), @img_addr);
273  
274 <  case Self.FStoreType of
274 >  case _storetype of
275      0, 1, 2:
276 <      Self.FDepth := 16;
277 <    8:
278 <      Self.FDepth := 32;
276 >      _depth := 16;
277 >    7, 8:
278 >      _depth := 32;
279      9:
280 <      Self.FDepth := 16;
280 >      _depth := 16;
281      else
282        Result := False;
283        Exit;
284    end;
285  
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
286    with hdr do
287    begin
288      FOURCC := 'DDS ';
# Line 518 | Line 290 | begin
290      begin
291        Size := 124;
292        Flags := DDSD_CAPS or DDSD_PIXELFORMAT or DDSD_WIDTH or DDSD_HEIGHT;
293 <      if FStoreType = 9 then
293 >      if _storetype = 9 then
294          Flags := Flags or DDSD_LINEARSIZE
295        else
296          Flags := Flags or DDSD_PITCH;
297        if (imginfo and $01) > 0 then
298          Flags := Flags or DDSD_MIPMAPCOUNT;
299 <      Height := FHeight;
300 <      Width := FWidth;
301 <      if FStoreType = 9 then
302 <        PitchOrLinearSize := FWidth * FHeight div 2
299 >      Height := _height;
300 >      Width := _width;
301 >      if _storetype = 9 then
302 >        PitchOrLinearSize := width * height div 2
303        else
304 <        PitchOrLinearSize := FWidth * FDepth div 2;
304 >        PitchOrLinearSize := width * _depth div 8;
305        Depth := 0;
306        MipMapCount := 1;
307 <      x := FWidth;
536 <      y := FHeight;
537 <      while (x > 1) and (y > 1) do
307 >      if (imginfo and $01) > 0 then
308        begin
309 <        x := x div 2;
310 <        y := y div 2;
311 <        Inc(MipMapCount);
309 >        x := width;
310 >        y := height;
311 >        while (x > 1) and (y > 1) do
312 >        begin
313 >          x := x div 2;
314 >          y := y div 2;
315 >          Inc(MipMapCount);
316 >        end;
317        end;
318        for i := 1 to 11 do
319          Reserved[i] := 0;
320        with PIXELFORMAT do
321        begin
322          Size := 32;
323 <        if FStoreType = 9 then
323 >        if _storetype = 9 then
324            Flags := DDPF_FOURCC
325          else
326            Flags := DDPF_RGB;
327 +        if _storetype in [0, 2] then
328 +          Flags := Flags or DDPF_ALPHAPIXELS;
329 +        if _storetype = 9 then
330 +          FOURCC := 'DXT1'
331 +        else
332 +        begin
333 +          RGBBitCount := _depth;
334 +          case _storetype of
335 +            0: begin
336 +              RBitMask := $0F00;
337 +              GBitMask := $00F0;
338 +              BBitMask := $000F;
339 +              AlphaBitMask := $F000;
340 +            end;
341 +            1, 2: begin
342 +              RBitMask := $7C00;
343 +              GBitMask := $03E0;
344 +              BBitMask := $001F;
345 +              if _storetype = 2 then
346 +                AlphaBitMask := $8000
347 +              else
348 +                AlphaBitMask := $0000;
349 +            end;
350 +            8: begin
351 +              RBitMask := $00FF0000;
352 +              GBitMask := $0000FF00;
353 +              BBitMask := $000000FF;
354 +              AlphaBitMask := $00000000;
355 +            end;
356 +          end;
357 +        end;
358 +      end;
359 +      with DDSCAPS2 do
360 +      begin
361 +        Caps1 := DDSCAPS_TEXTURE;
362 +        if (imginfo and $01) > 0 then
363 +          Caps1 := Caps1 or DDSCAPS_COMPLEX or DDSCAPS_MIPMAP;
364 +        Caps2 := 0;
365 +        Reserved[1] := 0;
366 +        Reserved[2] := 0;
367        end;
368      end;
369 <  end;
370 <  LoadImageFromStream(data, FImage);
371 < {
369 >  end;
370 >
371 >  data := TMemoryStream.Create;
372 >  data.Write(hdr, SizeOf(hdr));
373    if ConManager.Connection[ConnectionID].DataOS = DOS_WIN then
374 <    ConManager.Connection[ConnectionID].LoadRawFile(fileid, $9C, FData)
374 >    ConManager.Connection[ConnectionID].LoadRawFile(fileid, $9C, TStream(data))
375    else
376 <    ConManager.Connection[ConnectionID].LoadRawFile(fileid, $A0, FData);
377 < }
378 <  Self.FDataType := [DT_OniReverted, DT_Oni];
376 >    ConManager.Connection[ConnectionID].LoadRawFile(fileid, $A0, TStream(data));
377 >
378 >  data.Seek(0, soFromBeginning);
379 >  Result := LoadMultiImageFromStream(data, FImages);
380 >  data.Free;
381 >
382 >  if not result then
383 >  begin
384 >    ShowMessage('Error while loading file' + #13#10 + DetermineStreamFormat(data));
385 >  end;
386   end;
387  
388  
389  
390  
391 +
392   function TOniImage.LoadFromTXMB(ConnectionID, FileID: Integer): Boolean;
393   var
394 <  i, x, y, x2, y2, pixelid, imgid: Integer;
394 >  i, x, y, imgid: Integer;
395    rows, cols: Word;
396    linkcount: Integer;
397    link: Integer;
398 <  images_decoded: array of TOniImage;
398 >  images: array of TOniImage;
399    x_start, y_start: Integer;
400 +
401 +  width, height: Word;
402   begin
403 <  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $10, SizeOf(Self.FWidth), @Self.FWidth);
404 <  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $12, SizeOf(Self.FHeight), @Self.FHeight);
403 >  Result := False;
404 >  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $10, SizeOf(width), @width);
405 >  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $12, SizeOf(height), @height);
406    ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $18, SizeOf(cols), @cols);
407    ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $1A, SizeOf(rows), @rows);
408    ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $1C, SizeOf(linkcount), @linkcount);
409 <  SetLength(images_decoded, linkcount);
409 >  SetLength(images, linkcount);
410    for i := 0 to linkcount - 1 do
411    begin
412      ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $20 + i * 4, SizeOf(link), @link);
413      link := link div 256;
414 <    images_decoded[i] := TOniImage.Create;
415 <    images_decoded[i].LoadFromTXMP(ConnectionID, link);
589 <    images_decoded[i].DecodeImageTo32bit;
590 <    images_decoded[i].RevertImage;
414 >    images[i] := TOniImage.Create;
415 >    images[i].LoadFromTXMP(ConnectionID, link);
416    end;
417 <  SetLength(Self.FData, Self.FWidth * Self.FHeight * 4);
417 >  SetLength(FImages, 1);
418 >  NewImage(width, height, images[0].Format {ifA1R5G5B5}, FImages[0]);
419    for y := 0 to rows - 1 do
420    begin
421      for x := 0 to cols - 1 do
422      begin
423 <      imgid   := y * cols + x;
423 >      imgid := y * cols + x;
424        x_start := 0;
425        y_start := 0;
426        for i := 0 to x do
427          if i < x then
428 <          x_start := x_start + images_decoded[i].Width;
428 >          x_start := x_start + images[i].Image[1].Width;
429        for i := 0 to y do
430          if i < y then
431 <          y_start := y_start + images_decoded[i].Height;
432 <      for y2 := 0 to images_decoded[imgid].Height - 1 do
433 <      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;
431 >          y_start := y_start + images[i].Image[1].Height;
432 >      CopyRect(images[imgid].Image[1], 0, 0, images[imgid].Image[1].Width,
433 >          images[imgid].Image[1].Height, FImages[0], x_start, y_start);
434      end;
435    end;
436    for i := 0 to linkcount - 1 do
437 <    images_decoded[i].Free;
438 <  Self.FDepth     := 32;
629 <  Self.FStoreType := 8;
630 <  Self.FDataType  := [DT_Decoded32];
631 <  Self.RevertImage;
437 >    images[i].Free;
438 >  Result := True;
439   end;
440  
441  
442  
443 < function TOniImage.GetImgSize(w,h, storetype: Integer): Integer;
444 < begin
445 <  case storetype of
446 <    0, 1, 2:
447 <      Result := w*h*2;
448 <    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;
443 >
444 >
445 > function TOniImage.LoadFromPSpc(ConnectionID, FileID: Integer): Boolean;
446 > type
447 >  TPoint = packed record
448 >    X, Y: Word;
449    end;
648 end;
450  
451 +  TPSpc = packed record
452 +    p1:   array[0..8] of TPoint;
453 +    p2:   array[0..8] of TPoint;
454 +    TXMP: Integer;
455 +  end;
456  
457 < function TOniImage.GetImageDataSize(fading: Boolean): Integer;
457 >  TPart = packed record
458 >    x_txmp, y_txmp: Word;
459 >    x_pspc, y_pspc: Word;
460 >    w, h:    Word;
461 >    imgdata: TImageData;
462 >    used:    Boolean;
463 >  end;
464 > const
465 >  PartMatch: array[0..8] of Byte = (0, 3, 6, 1, 4, 7, 2, 5, 8);
466 >  stretch_x: Integer = 1;
467 >  stretch_y: Integer = 1;
468   var
653  size: Integer;
469    x, y: Word;
470 < begin
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;
668 < end;
669 <
470 >  i: Integer;
471  
472 +  PSpc:     TPSpc;
473 +  txmpimg:  TOniImage;
474  
475 +  parts:    array[0..8] of TPart;
476 +  part:     Byte;
477 +  cols:     array[0..2] of Word;
478 +  rows:     array[0..2] of Word;
479 +  col, row: Byte;
480  
481 < procedure TOniImage.GetAsData(var Target: TStream);
674 < var
675 <  revert: Boolean;
481 >  pspcimage: TImageData;
482   begin
483 <  //    if not (DT_Decoded32 in Self.FDataType) then
484 <  //      Self.DecodeImage;
485 <  if not (DT_OniReverted in Self.FDataType) then
483 >  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $08, SizeOf(PSpc), @PSpc);
484 >  PSpc.TXMP := PSpc.TXMP div 256;
485 >  if PSpc.TXMP = 0 then
486    begin
487 <    revert := True;
488 <    Self.RevertImage;
489 <  end
490 <  else
491 <    revert := False;
492 <  if not Assigned(Target) then
493 <    Target := TMemoryStream.Create;
688 <  Target.Write(FData[0], Length(FData));
689 <  Target.Seek(0, soFromBeginning);
690 <  if revert then
691 <    Self.RevertImage;
692 < end;
693 <
694 < procedure TOniImage.GetAsData(var Target: TByteData);
695 < var
696 <  mem: TStream;
697 < begin
698 <  mem := TMemoryStream.Create;
699 <  GetAsData(mem);
700 <  SetLength(Target, mem.Size);
701 <  mem.Read(Target[0], mem.Size);
702 <  mem.Free;
703 < end;
487 >    Result := False;
488 >    Exit;
489 >  end;
490 >  txmpimg := TOniImage.Create;
491 >  txmpimg.Load(ConnectionID, PSpc.TXMP);
492 >  CloneImage(txmpimg.Image[1], pspcimage);
493 >  txmpimg.Free;
494  
495 +  Result := False;
496  
497 < procedure TOniImage.GetAs32bit(var Target: TStream);
498 < begin
499 <  if not (DT_Decoded32 in Self.FDataType) then
500 <    Self.DecodeImageTo32bit;
501 <  if not Assigned(Target) then
502 <    Target := TMemoryStream.Create;
503 <  Target.Write(FData[0], Length(FData));
504 <  Target.Seek(0, soFromBeginning);
505 < end;
497 >  with pspc do
498 >  begin
499 >    for i := 0 to 2 do
500 >    begin
501 >      cols[i] := 0;
502 >      rows[i] := 0;
503 >    end;
504 >    for i := 0 to 8 do
505 >    begin
506 >      part := PartMatch[i];
507 >      col  := i div 3;
508 >      row  := i mod 3;
509 >      if (p2[i].X > 0) or (p2[i].Y > 0) then
510 >      begin
511 >        parts[part].x_txmp := p1[i].X;// - 1;
512 >        parts[part].y_txmp := p1[i].Y;// - 1;
513 >        parts[part].x_pspc := 0;
514 >        if col > 0 then
515 >          for x := 0 to col - 1 do
516 >            Inc(parts[part].x_pspc, cols[x]);
517 >        parts[part].y_pspc := 0;
518 >        if row > 0 then
519 >          for y := 0 to row - 1 do
520 >            Inc(parts[part].y_pspc, rows[y]);
521 >        parts[part].w := Max(p2[i].X - p1[i].X, 1);// + 1;
522 >        parts[part].h := Max(p2[i].Y - p1[i].Y, 1);// + 1;
523 >        parts[part].used := True;
524 >        cols[col] := parts[part].w;
525 >        rows[row] := parts[part].h;
526  
527 < procedure TOniImage.GetAs32bit(var Target: TByteData);
717 < var
718 <  mem: TStream;
719 < begin
720 <  mem := TMemoryStream.Create;
721 <  GetAs32bit(mem);
722 <  SetLength(Target, mem.Size);
723 <  mem.Read(Target[0], mem.Size);
724 <  mem.Free;
725 < end;
527 >        NewImage(parts[part].w, parts[part].h, pspcimage.Format, parts[part].imgdata);
528  
529 +        CopyRect(pspcimage,
530 +            parts[part].x_txmp, parts[part].y_txmp, parts[part].w, parts[part].h,
531 +            parts[part].imgdata, 0, 0);
532 +      end
533 +      else
534 +      begin
535 +        parts[part].used := False;
536 +      end;
537 +    end;
538  
539 < procedure TOniImage.GetAsBMP(var Target: TByteData);
729 < const
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);
734 < var
735 <  i, x, y: Integer;
736 < begin
737 <  if not (DT_Decoded32 in Self.FDataType) then
738 <    Self.DecodeImageTo32bit;
539 >  end;
540  
541 <  SetLength(Target, Self.FWidth * Self.FHeight * 3 + 54);
741 <  for y := 0 to Self.FHeight - 1 do
541 >  for i := 0 to 8 do
542    begin
543 <    for x := 0 to Self.FWidth - 1 do
543 >    if parts[i].used then
544      begin
545 <      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];
545 > //      SaveImageToFile('M:\' + IntToStr(i) + '.bmp', parts[i].imgdata);
546      end;
547    end;
548  
549 <  for i := 0 to High(BMPheader) do
550 <    Target[i] := BMPheader[i];
551 <  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;
769 < end;
770 <
771 <
772 < procedure TOniImage.GetAsBMP(var Target: TStream);
773 < var
774 <  data: TByteData;
775 <  streampos: Integer;
776 < begin
777 <  GetAsBMP(data);
778 <  streampos := Target.Position;
779 <  Target.Write(data[0], Length(data));
780 <  Target.Seek(streampos, soFromBeginning);
781 < end;
782 <
549 >  SetLength(FImages, 1);
550 >  x := cols[0] + cols[1] * stretch_x + cols[2];
551 >  y := rows[0] + rows[1] * stretch_y + rows[2];
552  
553 < function TOniImage.LoadFromBMP(filename: String): Boolean;
785 < var
786 <  filestream: TFileStream;
787 <  tempd:      TByteData;
788 <
789 <  x, y: Integer;
790 < begin
791 <  filestream := TFileStream.Create(filename, fmOpenRead);
792 <  SetLength(tempd, filestream.Size);
793 <  filestream.Read(tempd[0], filestream.Size);
794 <  filestream.Free;
553 >  NewImage(x, y, pspcimage.Format, FImages[0]);
554  
555 <  if not ((tempd[00] = $42) and (tempd[01] = $4D)) then
556 <  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
555 >  x := 0;
556 >  for col := 0 to 2 do
557    begin
558 <    Result := False;
559 <    ShowMessage('Bitmap has to be uncompressed');
560 <    Exit;
561 <  end;
562 <
563 <  Self.FWidth     := tempd[18] + tempd[19] * 256 + tempd[20] * 256 * 256 + tempd[21] * 256 * 256 * 256;
564 <  Self.FHeight    := tempd[22] + tempd[23] * 256 + tempd[24] * 256 * 256 + tempd[25] * 256 * 256 * 256;
565 <  Self.FDepth     := 32;
566 <  Self.FStoreType := 8;
567 <
568 <  SetLength(Self.FData, Self.FWidth * Self.FHeight * Self.FDepth div 8);
569 <  for y := 0 to Self.FHeight - 1 do
570 <  begin
571 <    for x := 0 to Self.FWidth - 1 do
572 <    begin
573 <      Self.FData[((Self.FWidth * y + x) * 4) + 0] := tempd[54 + (Self.FWidth * y + x) * 3 + 0];
574 <      Self.FData[((Self.FWidth * y + x) * 4) + 1] := tempd[54 + (Self.FWidth * y + x) * 3 + 1];
575 <      Self.FData[((Self.FWidth * y + x) * 4) + 2] := tempd[54 + (Self.FWidth * y + x) * 3 + 2];
576 <      Self.FData[((Self.FWidth * y + x) * 4) + 3] := 0;
558 >    y := 0;
559 >    for row := 0 to 2 do
560 >    begin
561 >      part := row*3 + col;
562 >      if parts[part].used then
563 >      begin
564 >        if (row = 1) and (col = 1) then
565 >          StretchRect(parts[part].imgdata, 0, 0, parts[part].w, parts[part].h,
566 >              FImages[0], x, y, parts[part].w * stretch_x, parts[part].h * stretch_y, rfNearest)
567 >        else
568 >        if (row = 1) then
569 >          StretchRect(parts[part].imgdata, 0, 0, parts[part].w, parts[part].h,
570 >              FImages[0], x, y, parts[part].w, parts[part].h * stretch_y, rfNearest)
571 >        else
572 >        if (col = 1) then
573 >          StretchRect(parts[part].imgdata, 0, 0, parts[part].w, parts[part].h,
574 >              FImages[0], x, y, parts[part].w * stretch_x, parts[part].h, rfNearest)
575 >        else
576 >          CopyRect(parts[part].imgdata, 0, 0, parts[part].w, parts[part].h,
577 >              FImages[0], x, y );
578 >        if row = 1 then
579 >          y := y + parts[part].h * stretch_y
580 >        else
581 >          y := y + parts[part].h;
582 >      end;
583 >    end;
584 >    if cols[col] > 0 then
585 >    begin
586 >      if (col = 1) then
587 >        x := x + parts[part].w * stretch_x
588 >      else
589 >        x := x + parts[part].w;
590      end;
591    end;
592  
593 <  Self.FDataType := [DT_Decoded32];
594 < end;
595 <
596 <
848 <
849 <
850 < function TOniImage.WriteToBMP(filename: String): Boolean;
851 < var
852 <  filestream: TFileStream;
853 < begin
854 <  filestream := TFileStream.Create(filename, fmCreate);
855 <  GetAsBMP(TStream(filestream));
856 <  filestream.Free;
857 < end;
858 <
859 <
860 <
861 < function TOniImage.GetMipMappedImage(var Target: TByteData): Boolean;
862 < var
863 <  i:      Integer;
864 <  x, y:   Word;
865 <  fadelvldata: TByteData;
866 <  revert: Boolean;
867 < begin
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;
593 >  FreeImage(pspcimage);
594 >  for i := 0 to 8 do
595 >    if parts[i].used then
596 >      FreeImage(parts[i].imgdata);
597  
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;
598    Result := True;
902
903  if revert then
904    Self.RevertImage;
905 end;
906
907
908 function TOniImage.GetMipMappedImage(var Target: TStream): Boolean;
909 var
910  data: TByteData;
911  streampos: Integer;
912 begin
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);
599   end;
600  
921
601   end.

Diff Legend

Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)