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

Comparing:
oup/rewrite/Global/OniImgClass.pas (file contents), Revision 101 by alloc, Tue Feb 20 20:43:29 2007 UTC vs.
oup/current/Global/OniImgClass.pas (file contents), Revision 194 by alloc, Sat May 26 18:26:48 2007 UTC

# Line 2 | Line 2 | unit OniImgClass;
2  
3   interface
4  
5 < uses Math, Dialogs, Types, SysUtils, Classes, Data, ConnectionManager, TypeDefs;
5 > uses Math, Dialogs, Types, SysUtils, Classes, Data, ConnectionManager, TypeDefs,
6 >  Imaging, ImagingTypes, Graphics;
7  
7 type
8  TImgDataType = set of (DT_OniReverted, DT_Oni, DT_Decoded32);
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 <    function ResizeImage(oldx, oldy: Integer; img: TByteData): TByteData;
21 <    procedure RevertImage;
22 <    procedure DecodeImage;
23 <    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 Loaded:    Boolean      Read FLoaded    Write FLoaded;
23 <    property DataType:  TImgDataType Read FDataType  Write FDataType;
24 <    property Width:     Word         Read FWidth     Write FWidth;
25 <    property Height:    Word         Read FHeight    Write FHeight;
26 <    property Depth:     Byte         Read FDepth     Write FDepth;
27 <    property StoreType: Byte         Read FStoreType Write FStoreType;
28 <    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      function Load(ConnectionID, FileID: Integer): Boolean;
33      function LoadFromPSpc(ConnectionID, FileID: Integer): Boolean;
34      function LoadFromTXMP(ConnectionID, FileID: Integer): Boolean;
35      function LoadFromTXMB(ConnectionID, FileID: Integer): Boolean;
39    function GetImageDataSize(fading: Boolean): Integer;
36  
37 <    function GetAsData: TByteData;
38 <    function GetAs32bit: TByteData;
39 <    procedure GetAsBMP(var Target: TByteData); overload;
40 <    procedure GetAsBMP(var Target: TStream); overload;
41 <    function LoadFromBMP(filename: String): Boolean;
42 <    function WriteToBMP(filename: String): Boolean;
43 <    function GetMipMappedImage(var faded: TByteData): Boolean;
37 >    procedure SaveDataToStream(MipMaps: Boolean; var Target: TStream);
38 >
39 >    function LoadFromFile(filename: String): Boolean;
40 >    function WriteToFile(filename: String): Boolean;
41 >
42 >    procedure DrawOnCanvas(Canvas: TCanvas; Index: Integer);
43 >    function GetImageSize(MipMaps: Boolean): Integer;
44    published
45    end;
46  
# Line 52 | Line 48 | type
48   implementation
49  
50   //uses Functions;
51 + uses Img_DDSTypes, ImagingComponents;
52 +
53  
54 + procedure TOniImage.DrawOnCanvas(Canvas: TCanvas; Index: Integer);
55 + var
56 +  singleimg: TImageData;
57 +  rect: TRect;
58 + begin
59 +  InitImage(singleimg);
60 +  CloneImage(FImages[Index-1], singleimg);
61 +  ConvertImage(singleimg, ifX8R8G8B8);
62 +  rect.Left := 0;
63 +  rect.Top := 0;
64 +  rect.Right := singleimg.Width - 1;
65 +  rect.Bottom := singleimg.Height - 1;
66 +  Canvas.Brush.Color := $C8D0D4;
67 +  Canvas.FillRect(Canvas.ClipRect);
68 +  DisplayImageData(Canvas, rect, singleimg, rect);
69 +  FreeImage(singleimg);
70 + end;
71  
72  
73  
74   constructor TOniImage.Create;
75   begin
61  Self.FLoaded   := False;
62  Self.FDataType := [];
63  SetLength(Self.FData, 0);
64  Self.FWidth     := 0;
65  Self.FHeight    := 0;
66  Self.FDepth     := 0;
67  Self.FStoreType := 0;
76   end;
77  
78  
79  
80 + procedure TOniImage.Free;
81 + begin
82 +  FreeImagesInArray(FImages);
83 + end;
84  
85 < function TOniImage.ResizeImage(oldx, oldy: Integer; img: TByteData): TByteData;
86 < var
87 <  i, j: Integer;
88 <  col, row, row_orig: Integer;
85 >
86 >
87 >
88 > function TOniImage.GetImage(MipGen: Integer): TImageData;
89   begin
90 <  SetLength(Result, (oldx div 2) * (oldy div 2) * (Self.FDepth div 8));
79 <  row_orig := 0;
80 <  row      := 0;
81 <  col      := 0;
82 <  for i := 0 to (oldx * oldy) - 1 do
90 >  if MipGen <= Length(FImages) then
91    begin
92 <    if ((i mod oldx) = 0) and (i > 0) then
93 <    begin
86 <      Inc(row_orig);
87 <      if (row_orig mod 2) = 0 then
88 <      begin
89 <        Inc(row);
90 <        col := 0;
91 <      end;
92 <    end;
93 <    if (row_orig mod 2) = 0 then
94 <    begin
95 <      if (i mod 2) = 0 then
96 <      begin
97 <        for j := 0 to (Self.FDepth div 8) - 1 do
98 <          Result[((row * (oldx div 2)) + col) * (Self.FDepth div 8) + j] :=
99 <            img[(i * (Self.FDepth div 8)) + j];
100 <        Inc(col);
101 <      end;
102 <    end;
92 >    InitImage(Result);
93 >    CloneImage(FImages[MipGen-1], Result);
94    end;
95   end;
96  
97  
98  
99 <
109 < procedure TOniImage.RevertImage;
110 < var
111 <  x, y, i: Integer;
112 <  tempd:   TByteData;
99 > function TOniImage.GetWidth(MipGen: Integer): Integer;
100   begin
101 <  SetLength(tempd, Self.FWidth * Self.FHeight * (Self.FDepth div 8));
102 <  for y := 0 to Self.FHeight - 1 do
116 <    for x := 0 to Self.FWidth - 1 do
117 <      for i := 0 to (Self.FDepth div 8) - 1 do
118 <        tempd[((Self.FWidth * (Self.FHeight - 1 - y) + x) * (Self.FDepth div 8)) + i] :=
119 <          Self.FData[(Self.FWidth * y + x) * (Self.FDepth div 8) + i];
120 <  for x := 0 to High(tempd) do
121 <    Self.FData[x] := tempd[x];
122 <  if DT_OniReverted in Self.FDataType then
123 <    Self.FDataType := Self.FDataType - [DT_OniReverted]
101 >  if MipGen <= Length(FImages) then
102 >    Result := FImages[MipGen-1].Width
103    else
104 <    Self.FDataType := Self.FDataType + [DT_OniReverted];
104 >    Result := -1;
105   end;
106  
107  
108 <
130 <
131 < procedure TOniImage.DecodeImage;
132 < var
133 <  x, y:  Integer;
134 <  tempd: TByteData;
108 > function TOniImage.GetHeight(MipGen: Integer): Integer;
109   begin
110 <  if not (DT_Decoded32 in Self.FDataType) then
111 <  begin
112 <    SetLength(tempd, Self.FWidth * Self.FHeight * 4);
113 <    case Self.FStoreType of
140 <      0:
141 <      begin
142 <        for y := 0 to Self.FHeight - 1 do
143 <        begin
144 <          for x := 0 to Self.FWidth - 1 do
145 <          begin
146 <            tempd[((Self.FWidth * y + x) * 4) + 0] :=
147 <              Round(((Self.FData[(Self.FWidth * y + x) * 2] + Self.FData[(Self.FWidth * y + x) * 2 + 1] * 256) and
148 <              $000F) / $000F * 255);
149 <            tempd[((Self.FWidth * y + x) * 4) + 1] :=
150 <              Round(((Self.FData[(Self.FWidth * y + x) * 2] + Self.FData[(Self.FWidth * y + x) * 2 + 1] * 256) and
151 <              $00F0) / $00F0 * 255);
152 <            tempd[((Self.FWidth * y + x) * 4) + 2] :=
153 <              Round(((Self.FData[(Self.FWidth * y + x) * 2] + Self.FData[(Self.FWidth * y + x) * 2 + 1] * 256) and
154 <              $0F00) / $0F00 * 255);
155 <            tempd[((Self.FWidth * y + x) * 4) + 3] := 0;
156 <          end;
157 <        end;
158 <      end;
159 <      1, 2:
160 <      begin
161 <        for y := 0 to Self.FHeight - 1 do
162 <        begin
163 <          for x := 0 to Self.FWidth - 1 do
164 <          begin
165 <            tempd[((Self.FWidth * y + x) * 4) + 0] :=
166 <              Round(((Self.FData[(Self.FWidth * y + x) * 2] + Self.FData[(Self.FWidth * y + x) * 2 + 1] * 256) and
167 <              $001F) / $001F * 255);
168 <            tempd[((Self.FWidth * y + x) * 4) + 1] :=
169 <              Round(((Self.FData[(Self.FWidth * y + x) * 2] + Self.FData[(Self.FWidth * y + x) * 2 + 1] * 256) and
170 <              $03E0) / $03E0 * 255);
171 <            tempd[((Self.FWidth * y + x) * 4) + 2] :=
172 <              Round(((Self.FData[(Self.FWidth * y + x) * 2] + Self.FData[(Self.FWidth * y + x) * 2 + 1] * 256) and
173 <              $7C00) / $7C00 * 255);
174 <            tempd[((Self.FWidth * y + x) * 4) + 3] := 0;
175 <          end;
176 <        end;
177 <      end;
178 <      9:
179 <      begin
180 <        DecompressImage;
181 <      end;
182 <    end;
183 <    Self.FDepth := 32;
184 <    if (Self.FStoreType <> 9) and (Self.FStoreType <> 8) then
185 <    begin
186 <      SetLength(Self.FData, Length(tempd));
187 <      for x := 0 to High(tempd) do
188 <        Self.FData[x] := tempd[x];
189 <    end;
190 <    Self.FStoreType := 8;
191 <    if DT_Oni in Self.FDataType then
192 <      Self.FDataType := Self.FDataType - [DT_Oni];
193 <    Self.FDataType := Self.FDataType + [DT_Decoded32];
194 <  end;
195 <  if DT_OniReverted in Self.FDataType then
196 <    Self.RevertImage;
110 >  if MipGen <= Length(FImages) then
111 >    Result := FImages[MipGen-1].Height
112 >  else
113 >    Result := -1;
114   end;
115  
116  
117 + function TOniImage.GetImageFormat: TImageFormat;
118 + begin
119 +  if Length(FImages) > 0 then
120 +    Result := FImages[0].Format
121 +  else
122 +    Result := ifUnknown;
123 + end;
124  
125 <
202 < procedure TOniImage.DecompressImage;
203 < type
204 <  Tcolor = record
205 <    RGBb: Byte;
206 <    RGBg: Byte;
207 <    RGBr: Byte;
208 <    RGBa: Byte;
209 <  end;
125 > procedure TOniImage.SetImageFormat(Format: TImageFormat);
126   var
127 <  i, j, x, y: Integer;
128 <  color:      array[1..4] of Tcolor;
129 <  pixel:      array[1..16] of Byte;
130 <  tempd:      TByteData;
131 < begin
216 <  x := 0;
217 <  y := 0;
218 <  SetLength(tempd, Self.FWidth * Self.FHeight * 4);
219 <  for i := 0 to ((Self.FWidth * Self.FHeight) div 16) - 1 do
220 <  begin
221 <    Color[1].RGBb := Round(((Self.FData[(i * 8) + 0] + Self.FData[(i * 8) + 1] * 256) and $001F) /
222 <      $001F * 255);
223 <    Color[1].RGBg := Round(((Self.FData[(i * 8) + 0] + Self.FData[(i * 8) + 1] * 256) and $07E0) /
224 <      $07E0 * 255);
225 <    Color[1].RGBr := Round(((Self.FData[(i * 8) + 0] + Self.FData[(i * 8) + 1] * 256) and $F800) /
226 <      $F800 * 255);
227 <    Color[1].RGBa := 255;
228 <    Color[2].RGBb := Round(((Self.FData[(i * 8) + 2] + Self.FData[(i * 8) + 3] * 256) and $001F) /
229 <      $001F * 255);
230 <    Color[2].RGBg := Round(((Self.FData[(i * 8) + 2] + Self.FData[(i * 8) + 3] * 256) and $07E0) /
231 <      $07E0 * 255);
232 <    Color[2].RGBr := Round(((Self.FData[(i * 8) + 2] + Self.FData[(i * 8) + 3] * 256) and $F800) /
233 <      $F800 * 255);
234 <    Color[2].RGBa := 255;
235 <    Color[3].RGBb := Round(Color[1].RGBb / 3 * 2 + Color[2].RGBb / 3);
236 <    Color[3].RGBg := Round(Color[1].RGBg / 3 * 2 + Color[2].RGBg / 3);
237 <    Color[3].RGBr := Round(Color[1].RGBr / 3 * 2 + Color[2].RGBr / 3);
238 <    Color[3].RGBa := 255;
239 <    Color[4].RGBb := Round(Color[1].RGBb / 3 + Color[2].RGBb / 3 * 2);
240 <    Color[4].RGBg := Round(Color[1].RGBg / 3 + Color[2].RGBg / 3 * 2);
241 <    Color[4].RGBr := Round(Color[1].RGBr / 3 + Color[2].RGBr / 3 * 2);
242 <    Color[4].RGBa := 255;
243 <    Pixel[1]      := Round((Self.FData[(i * 8) + 4] and $C0) / $40 + 1);
244 <    Pixel[2]      := Round((Self.FData[(i * 8) + 4] and $30) / $10 + 1);
245 <    Pixel[3]      := Round((Self.FData[(i * 8) + 4] and $0C) / $04 + 1);
246 <    Pixel[4]      := Round((Self.FData[(i * 8) + 4] and $03) + 1);
247 <    Pixel[5]      := Round((Self.FData[(i * 8) + 5] and $C0) / $40 + 1);
248 <    Pixel[6]      := Round((Self.FData[(i * 8) + 5] and $30) / $10 + 1);
249 <    Pixel[7]      := Round((Self.FData[(i * 8) + 5] and $0C) / $04 + 1);
250 <    Pixel[8]      := Round((Self.FData[(i * 8) + 5] and $03) + 1);
251 <    Pixel[9]      := Round((Self.FData[(i * 8) + 6] and $C0) / $40 + 1);
252 <    Pixel[10]     := Round((Self.FData[(i * 8) + 6] and $30) / $10 + 1);
253 <    Pixel[11]     := Round((Self.FData[(i * 8) + 6] and $0C) / $04 + 1);
254 <    Pixel[12]     := Round((Self.FData[(i * 8) + 6] and $03) + 1);
255 <    Pixel[13]     := Round((Self.FData[(i * 8) + 7] and $C0) / $40 + 1);
256 <    Pixel[14]     := Round((Self.FData[(i * 8) + 7] and $30) / $10 + 1);
257 <    Pixel[15]     := Round((Self.FData[(i * 8) + 7] and $0C) / $04 + 1);
258 <    Pixel[16]     := Round((Self.FData[(i * 8) + 7] and $03) + 1);
259 <    for j := 0 to 3 do
260 <    begin
261 <      tempd[((y + 3) * Self.FWidth + x + j) * 4 + 0] := Color[Pixel[16 - j]].RGBb;
262 <      tempd[((y + 3) * Self.FWidth + x + j) * 4 + 1] := Color[Pixel[16 - j]].RGBg;
263 <      tempd[((y + 3) * Self.FWidth + x + j) * 4 + 2] := Color[Pixel[16 - j]].RGBr;
264 <      tempd[((y + 3) * Self.FWidth + x + j) * 4 + 3] := 0;
265 <    end;
266 <    for j := 0 to 3 do
267 <    begin
268 <      tempd[((y + 2) * Self.FWidth + x + j) * 4 + 0] := Color[Pixel[12 - j]].RGBb;
269 <      tempd[((y + 2) * Self.FWidth + x + j) * 4 + 1] := Color[Pixel[12 - j]].RGBg;
270 <      tempd[((y + 2) * Self.FWidth + x + j) * 4 + 2] := Color[Pixel[12 - j]].RGBr;
271 <      tempd[((y + 2) * Self.FWidth + x + j) * 4 + 3] := 0;
272 <    end;
273 <    for j := 0 to 3 do
274 <    begin
275 <      tempd[((y + 1) * Self.FWidth + x + j) * 4 + 0] := Color[Pixel[8 - j]].RGBb;
276 <      tempd[((y + 1) * Self.FWidth + x + j) * 4 + 1] := Color[Pixel[8 - j]].RGBg;
277 <      tempd[((y + 1) * Self.FWidth + x + j) * 4 + 2] := Color[Pixel[8 - j]].RGBr;
278 <      tempd[((y + 1) * Self.FWidth + x + j) * 4 + 3] := 0;
279 <    end;
280 <    for j := 0 to 3 do
281 <    begin
282 <      tempd[((y + 0) * Self.FWidth + x + j) * 4 + 0] := Color[Pixel[4 - j]].RGBb;
283 <      tempd[((y + 0) * Self.FWidth + x + j) * 4 + 1] := Color[Pixel[4 - j]].RGBg;
284 <      tempd[((y + 0) * Self.FWidth + x + j) * 4 + 2] := Color[Pixel[4 - j]].RGBr;
285 <      tempd[((y + 0) * Self.FWidth + x + j) * 4 + 3] := 0;
286 <    end;
287 <    x := x + 4;
288 <    if x = Self.FWidth then
289 <    begin
290 <      y := y + 4;
291 <      x := 0;
292 <    end;
293 <  end;
294 <  SetLength(Self.FData, Length(tempd));
295 <  for i := 0 to High(tempd) do
296 <    Self.FData[i] := tempd[i];
297 <  Self.FStoreType := 8;
298 <  Self.FDepth    := 32;
299 <  Self.FDataType := Self.FDataType - [DT_Oni] + [DT_Decoded32];
127 >  i: Integer;
128 > begin
129 >  if Length(FImages) > 0 then
130 >    for i := 0 to High(FImages) do
131 >      ConvertImage(FImages[i], Format);
132   end;
133  
134  
135 + function TOniImage.pGetImageFormatInfo: TImageFormatInfo;
136 + begin
137 +  if Length(FImages) > 0 then
138 +    GetImageFormatInfo(FImages[0].Format, Result);
139 + end;
140  
141  
142 + function TOniImage.GetHasMipMaps: Boolean;
143 + begin
144 +  Result := Length(FImages) > 1;
145 + end;
146 +
147  
148   function TOniImage.Load(ConnectionID, FileID: Integer): Boolean;
149   var
150    FileInfo: TFileInfo;
309  ext:      String;
151   begin
152    FileInfo := ConManager.Connection[ConnectionID].GetFileInfo(fileid);
153    if FileInfo.Extension = 'PSpc' then
# Line 357 | Line 198 | var
198    rows:     array[0..2] of Word;
199    col, row: Byte;
200   begin
201 + (*
202    ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $08, SizeOf(PSpc), @PSpc);
203    PSpc.TXMP := PSpc.TXMP div 256;
204    if PSpc.TXMP = 0 then
# Line 366 | Line 208 | begin
208    end;
209    txmpimg := TOniImage.Create;
210    txmpimg.LoadFromTXMP(ConnectionID, PSpc.TXMP);
211 <  txmpimg.DecodeImage;
211 >  txmpimg.DecodeImageTo32bit;
212   //  txmpimg.WriteToBMP('C:\file.bmp');
213 <  txmpdata := txmpimg.GetAs32bit;
213 >  txmpimg.GetAs32bit(txmpdata);
214   {    ShowMessage(IntToStr(txmpimg.Width)+'x'+IntToStr(txmpimg.Height));
215      for i:=0 to High(txmpdata) do
216        txmpimg.Data[i]:=txmpdata[i];
# Line 459 | Line 301 | begin
301    Self.FStoreType := 8;
302    Self.FDataType  := [DT_Decoded32];
303    //    Self.RevertImage;
304 + *)
305   end;
306  
307  
# Line 467 | Line 310 | end;
310   function TOniImage.LoadFromTXMP(ConnectionID, FileID: Integer): Boolean;
311   var
312    img_addr: Integer;
313 +  data: TMemoryStream;
314 +  hdr: TDDSDXTHeader;
315 +  imginfo: Integer;
316 +  x,y, i: Integer;
317 +
318 +  _width, _height: Word;
319 +  _storetype: Byte;
320 +  _depth: Byte;
321   begin
322    Result := True;
323 <  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $8C, SizeOf(Self.FWidth), @Self.FWidth);
324 <  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $8E, SizeOf(Self.FHeight), @Self.FHeight);
325 <  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $90, SizeOf(Self.FStoreType),
326 <    @Self.FStoreType);
323 >  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $8C, SizeOf(_width), @_width);
324 >  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $8E, SizeOf(_height), @_height);
325 >  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $90, SizeOf(_storetype), @_storetype);
326 >  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $88, SizeOf(imginfo), @imginfo);
327    if ConManager.Connection[ConnectionID].DataOS = DOS_WIN then
328      ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $9C, SizeOf(img_addr), @img_addr)
329    else
330      ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $A0, SizeOf(img_addr), @img_addr);
331  
332 <  case Self.FStoreType of
332 >  case _storetype of
333      0, 1, 2:
334 <    begin
335 <      SetLength(Self.FData, Self.FWidth * Self.FHeight * 2);
336 <      Self.FDepth := 16;
486 <    end;
487 <    8:
488 <    begin
489 <      SetLength(Self.FData, Self.FWidth * Self.FHeight * 4);
490 <      Self.FDepth := 32;
491 <    end;
334 >      _depth := 16;
335 >    7, 8:
336 >      _depth := 32;
337      9:
338 <    begin
494 <      SetLength(Self.FData, Self.FWidth * Self.FHeight div 2);
495 <      Self.FDepth := 16;
496 <    end;
338 >      _depth := 16;
339      else
340        Result := False;
341        Exit;
342    end;
343  
344 +  with hdr do
345 +  begin
346 +    FOURCC := 'DDS ';
347 +    with SURFACEDESC2 do
348 +    begin
349 +      Size := 124;
350 +      Flags := DDSD_CAPS or DDSD_PIXELFORMAT or DDSD_WIDTH or DDSD_HEIGHT;
351 +      if _storetype = 9 then
352 +        Flags := Flags or DDSD_LINEARSIZE
353 +      else
354 +        Flags := Flags or DDSD_PITCH;
355 +      if (imginfo and $01) > 0 then
356 +        Flags := Flags or DDSD_MIPMAPCOUNT;
357 +      Height := _height;
358 +      Width := _width;
359 +      if _storetype = 9 then
360 +        PitchOrLinearSize := width * height div 2
361 +      else
362 +        PitchOrLinearSize := width * _depth div 8;
363 +      Depth := 0;
364 +      MipMapCount := 1;
365 +      if (imginfo and $01) > 0 then
366 +      begin
367 +        x := width;
368 +        y := height;
369 +        while (x > 1) and (y > 1) do
370 +        begin
371 +          x := x div 2;
372 +          y := y div 2;
373 +          Inc(MipMapCount);
374 +        end;
375 +      end;
376 +      for i := 1 to 11 do
377 +        Reserved[i] := 0;
378 +      with PIXELFORMAT do
379 +      begin
380 +        Size := 32;
381 +        if _storetype = 9 then
382 +          Flags := DDPF_FOURCC
383 +        else
384 +          Flags := DDPF_RGB;
385 +        if _storetype in [0, 2] then
386 +          Flags := Flags or DDPF_ALPHAPIXELS;
387 +        if _storetype = 9 then
388 +          FOURCC := 'DXT1'
389 +        else
390 +        begin
391 +          RGBBitCount := _depth;
392 +          case _storetype of
393 +            0: begin
394 +              RBitMask := $0F00;
395 +              GBitMask := $00F0;
396 +              BBitMask := $000F;
397 +              AlphaBitMask := $F000;
398 +            end;
399 +            1, 2: begin
400 +              RBitMask := $7C00;
401 +              GBitMask := $03E0;
402 +              BBitMask := $001F;
403 +              if _storetype = 2 then
404 +                AlphaBitMask := $8000
405 +              else
406 +                AlphaBitMask := $0000;
407 +            end;
408 +            8: begin
409 +              RBitMask := $00FF0000;
410 +              GBitMask := $0000FF00;
411 +              BBitMask := $000000FF;
412 +              AlphaBitMask := $00000000;
413 +            end;
414 +          end;
415 +        end;
416 +      end;
417 +      with DDSCAPS2 do
418 +      begin
419 +        Caps1 := DDSCAPS_TEXTURE;
420 +        if (imginfo and $01) > 0 then
421 +          Caps1 := Caps1 or DDSCAPS_COMPLEX or DDSCAPS_MIPMAP;
422 +        Caps2 := 0;
423 +        Reserved[1] := 0;
424 +        Reserved[2] := 0;
425 +      end;
426 +    end;
427 +  end;
428 +
429 +  data := TMemoryStream.Create;
430 +  data.Write(hdr, SizeOf(hdr));
431    if ConManager.Connection[ConnectionID].DataOS = DOS_WIN then
432 <    ConManager.Connection[ConnectionID].LoadRawFile(fileid, $9C, FData)
432 >    ConManager.Connection[ConnectionID].LoadRawFile(fileid, $9C, TStream(data))
433    else
434 <    ConManager.Connection[ConnectionID].LoadRawFile(fileid, $A0, FData);
434 >    ConManager.Connection[ConnectionID].LoadRawFile(fileid, $A0, TStream(data));
435 >
436 > //  data.Seek(0, soFromBeginning);
437 > //  data.SaveToFile('m:\test.txmp');
438  
439 <  Self.FDataType := [DT_OniReverted, DT_Oni];
439 >  data.Seek(0, soFromBeginning);
440 >  result := LoadMultiImageFromStream(data, FImages);
441 >  data.Free;
442 > {
443 >  if result then
444 >  begin
445 >    for i := 0 to High(FImages) do
446 >    begin
447 >      data := TMemoryStream.Create;
448 >      data.Write(FImages[i].Bits^, FImages[i].Size);
449 >      data.Seek(0, soFromBeginning);
450 >      data.SaveToFile('m:\test.txmp.'+IntToStr(i));
451 >      data.Free;
452 >    end;
453 >  end;
454 > }
455 >  if not result then
456 >  begin
457 >    ShowMessage('Error while loading file' + #13#10 + DetermineStreamFormat(data));
458 > //    data.SaveToFile('m:\prob.dds');
459 >  end;
460   end;
461  
462  
# Line 516 | Line 468 | var
468    rows, cols: Word;
469    linkcount: Integer;
470    link: Integer;
471 <  images_decoded: array of TOniImage;
471 >  images: array of TOniImage;
472    x_start, y_start: Integer;
473 +
474 +  width, height: Word;
475   begin
476 <  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $10, SizeOf(Self.FWidth), @Self.FWidth);
477 <  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $12, SizeOf(Self.FHeight), @Self.FHeight);
476 >  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $10, SizeOf(width), @width);
477 >  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $12, SizeOf(height), @height);
478    ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $18, SizeOf(cols), @cols);
479    ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $1A, SizeOf(rows), @rows);
480    ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $1C, SizeOf(linkcount), @linkcount);
481 <  SetLength(images_decoded, linkcount);
481 >  SetLength(images, linkcount);
482    for i := 0 to linkcount - 1 do
483    begin
484      ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $20 + i * 4, SizeOf(link), @link);
485      link := link div 256;
486 <    images_decoded[i] := TOniImage.Create;
487 <    images_decoded[i].LoadFromTXMP(ConnectionID, link);
488 <    images_decoded[i].DecodeImage;
489 <    images_decoded[i].RevertImage;
486 >    images[i] := TOniImage.Create;
487 >    images[i].LoadFromTXMP(ConnectionID, link);
488 >    SetLength(FImages, 1);
489 >    NewImage(width, height, ifA1R5G5B5, FImages[0]);
490    end;
537  SetLength(Self.FData, Self.FWidth * Self.FHeight * 4);
491    for y := 0 to rows - 1 do
492    begin
493      for x := 0 to cols - 1 do
494      begin
495 <      imgid   := y * cols + x;
495 >      imgid := y * cols + x;
496        x_start := 0;
497        y_start := 0;
498        for i := 0 to x do
499          if i < x then
500 <          x_start := x_start + images_decoded[i].Width;
500 >          x_start := x_start + images[i].Image[0].Width;
501        for i := 0 to y do
502          if i < y then
503 <          y_start := y_start + images_decoded[i].Height;
504 <      for y2 := 0 to images_decoded[imgid].Height - 1 do
505 <      begin
553 <        for x2 := 0 to images_decoded[imgid].Width - 1 do
554 <        begin
555 <          if ((x_start + x2) < Self.FWidth) and ((y_start + y2) < Self.FHeight) then
556 <          begin
557 <            pixelid := y_start * Self.FWidth + x_start + y2 * Self.FWidth + x2;
558 <            Self.FData[pixelid * 4 + 0] :=
559 <              images_decoded[imgid].Data[(y2 * images_decoded[imgid].Width + x2) * 4 + 0];
560 <            Self.FData[pixelid * 4 + 1] :=
561 <              images_decoded[imgid].Data[(y2 * images_decoded[imgid].Width + x2) * 4 + 1];
562 <            Self.FData[pixelid * 4 + 2] :=
563 <              images_decoded[imgid].Data[(y2 * images_decoded[imgid].Width + x2) * 4 + 2];
564 <            Self.FData[pixelid * 4 + 3] :=
565 <              images_decoded[imgid].Data[(y2 * images_decoded[imgid].Width + x2) * 4 + 3];
566 <          end;
567 <        end;
568 <      end;
503 >          y_start := y_start + images[i].Image[0].Height;
504 >      CopyRect(images[imgid].Image[0], 0, 0, images[imgid].Image[0].Width,
505 >          images[imgid].Image[0].Height, FImages[0], x_start, y_start);
506      end;
507    end;
508    for i := 0 to linkcount - 1 do
509 <    images_decoded[i].Free;
573 <  Self.FDepth     := 32;
574 <  Self.FStoreType := 8;
575 <  Self.FDataType  := [DT_Decoded32];
576 <  Self.RevertImage;
509 >    images[i].Free;
510   end;
511  
512  
513  
514 <
582 < function TOniImage.GetImageDataSize(fading: Boolean): Integer;
514 > procedure TOniImage.SaveDataToStream(MipMaps: Boolean; var Target: TStream);
515   var
516 <  size: Integer;
517 <  x, y: Word;
518 <  bpp:  Byte;
516 >  images: TDynImageDataArray;
517 >  mem: TMemoryStream;
518 >  i: Integer;
519   begin
520 <  case Self.FStoreType of
521 <    9:
522 <      bpp := 8;
523 <    0, 1, 2:
524 <      bpp := 16;
525 <    8:
526 <      bpp := 32;
520 >  if Length(FImages) = 0 then
521 >    Exit;
522 >  if MipMaps then
523 >  begin
524 >    if Length(FImages) = 1 then
525 >    begin
526 >      if not GenerateMipMaps(FImages[0], 0, images) then
527 >      begin
528 >        ShowMessage('Could not generate MipMaps');
529 >        Exit;
530 >      end;
531 >    end
532      else
533 <      Result := 0;
533 >    begin
534 >      SetLength(images, Length(FImages));
535 >      for i := 0 to High(FImages) do
536 >        CloneImage(FImages[i], images[i]);
537 >    end;
538 >    mem := TMemoryStream.Create;
539 >    if not SaveMultiImageToStream('dds', mem, images) then
540 >    begin
541 >      ShowMessage('Could not save images to stream');
542        Exit;
543 <  end;
544 <
600 <  x    := Self.FWidth;
601 <  y    := Self.FHeight;
602 <  size := x * y * bpp div 8;
603 <  if fading then
604 <  begin
605 <    repeat
606 <      x    := x div 2;
607 <      y    := y div 2;
608 <      size := size + x * y * bpp div 8;
609 <    until (x = 1) or (y = 1);
610 <  end;
611 <  Result := size;
612 < end;
613 <
614 <
615 <
616 <
617 < function TOniImage.GetAsData: TByteData;
618 < var
619 <  i:      Integer;
620 <  revert: Boolean;
621 < begin
622 <  //    if not (DT_Decoded32 in Self.FDataType) then
623 <  //      Self.DecodeImage;
624 <  if not (DT_OniReverted in Self.FDataType) then
625 <  begin
626 <    revert := True;
627 <    Self.RevertImage;
543 >    end;
544 >    FreeImagesInArray(images);
545    end
546    else
630    revert := False;
631  SetLength(Result, Length(Self.FData));
632  for i := 0 to High(Result) do
633    Result[i] := Self.FData[i];
634  if revert then
635    Self.RevertImage;
636 end;
637
638
639
640
641 function TOniImage.GetAs32bit: TByteData;
642 var
643  i: Integer;
644 begin
645  if not (DT_Decoded32 in Self.FDataType) then
646    Self.DecodeImage;
647  SetLength(Result, Length(Self.FData));
648  for i := 0 to High(Result) do
649    Result[i] := Self.FData[i];
650 end;
651
652
653
654
655 procedure TOniImage.GetAsBMP(var Target: TByteData);
656 const
657  BMPheader: array[0..53] of Byte =
658    ($42, $4D, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0,
659    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,
660    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
661 var
662  i, x, y: Integer;
663 begin
664  if not (DT_Decoded32 in Self.FDataType) then
665    Self.DecodeImage;
666
667  SetLength(Target, Self.FWidth * Self.FHeight * 3 + 54);
668  for y := 0 to Self.FHeight - 1 do
547    begin
548 <    for x := 0 to Self.FWidth - 1 do
548 >    mem := TMemoryStream.Create;
549 >    if not SaveImageToStream('dds', mem, FImages[0]) then
550      begin
551 <      Target[((Self.FWidth * y + x) * 3) + 0 + 54] := Self.FData[(Self.FWidth * y + x) * 4 + 0];
552 <      Target[((Self.FWidth * y + x) * 3) + 1 + 54] := Self.FData[(Self.FWidth * y + x) * 4 + 1];
674 <      Target[((Self.FWidth * y + x) * 3) + 2 + 54] := Self.FData[(Self.FWidth * y + x) * 4 + 2];
551 >      ShowMessage('Could not save image to stream');
552 >      Exit;
553      end;
554    end;
555 +  if not Assigned(Target) then
556 +    Target := TMemoryStream.Create;
557  
558 <  for i := 0 to High(BMPheader) do
559 <    Target[i] := BMPheader[i];
680 <  Target[2] := ((Self.FWidth * Self.FHeight * 3 + 54) and $000000FF) div $1;
681 <  Target[3]  := ((Self.FWidth * Self.FHeight * 3 + 54) and $0000FF00) div $100;
682 <  Target[4]  := ((Self.FWidth * Self.FHeight * 3 + 54) and $00FF0000) div $10000;
683 <  Target[5]  := ((Self.FWidth * Self.FHeight * 3 + 54) and $FF000000) div $1000000;
684 <  Target[18] := (Self.FWidth and $000000FF) div $1;
685 <  Target[19] := (Self.FWidth and $0000FF00) div $100;
686 <  Target[20] := (Self.FWidth and $00FF0000) div $10000;
687 <  Target[21] := (Self.FWidth and $FF000000) div $1000000;
688 <  Target[22] := (Self.FHeight and $000000FF) div $1;
689 <  Target[23] := (Self.FHeight and $0000FF00) div $100;
690 <  Target[24] := (Self.FHeight and $00FF0000) div $10000;
691 <  Target[25] := (Self.FHeight and $FF000000) div $1000000;
692 <  Target[34] := ((Self.FWidth * Self.FHeight * 3) and $000000FF) div $1;
693 <  Target[35] := ((Self.FWidth * Self.FHeight * 3) and $0000FF00) div $100;
694 <  Target[36] := ((Self.FWidth * Self.FHeight * 3) and $00FF0000) div $10000;
695 <  Target[37] := ((Self.FWidth * Self.FHeight * 3) and $FF000000) div $1000000;
696 < end;
697 <
558 > //  mem.Seek(0, soFromBeginning);
559 > //  mem.SaveToFile('m:\dds.dds');
560  
561 < procedure TOniImage.GetAsBMP(var Target: TStream);
562 < var
563 <  data: TByteData;
564 <  streampos: Integer;
703 < begin
704 <  GetAsBMP(data);
705 <  streampos := Target.Position;
706 <  Target.Write(data[0], Length(data));
707 <  Target.Seek(streampos, soFromBeginning);
561 >  mem.Seek(128, soFromBeginning);
562 >  Target.CopyFrom(mem, mem.Size - 128);
563 >  mem.Free;
564 >  Target.Seek(0, soFromBeginning);
565   end;
566  
567  
568 < function TOniImage.LoadFromBMP(filename: String): Boolean;
712 < var
713 <  filestream: TFileStream;
714 <  tempd:      TByteData;
715 <
716 <  x, y: Integer;
568 > function TOniImage.LoadFromFile(filename: String): Boolean;
569   begin
570 <  filestream := TFileStream.Create(filename, fmOpenRead);
571 <  SetLength(tempd, filestream.Size);
720 <  filestream.Read(tempd[0], filestream.Size);
721 <  filestream.Free;
722 <
723 <  if not ((tempd[00] = $42) and (tempd[01] = $4D)) then
724 <  begin
725 <    Result := False;
726 <    ShowMessage('Not a standard 24bit bitmap');
727 <    Exit;
728 <  end;
729 <  if not (tempd[10] = 54) then
730 <  begin
731 <    Result := False;
732 <    ShowMessage('Imagedata has to start at 0x54');
733 <    Exit;
734 <  end;
735 <  if not (tempd[14] = 40) then
736 <  begin
737 <    Result := False;
738 <    ShowMessage('Second bitmap header has to have 40 bytes');
739 <    Exit;
740 <  end;
741 <  if not (tempd[28] = 24) then
742 <  begin
743 <    Result := False;
744 <    ShowMessage('Bitmap has to have 24bits');
745 <    Exit;
746 <  end;
747 <  if not (tempd[30] = 0) then
748 <  begin
749 <    Result := False;
750 <    ShowMessage('Bitmap has to be uncompressed');
751 <    Exit;
752 <  end;
753 <
754 <  Self.FWidth     := tempd[18] + tempd[19] * 256 + tempd[20] * 256 * 256 + tempd[21] * 256 * 256 * 256;
755 <  Self.FHeight    := tempd[22] + tempd[23] * 256 + tempd[24] * 256 * 256 + tempd[25] * 256 * 256 * 256;
756 <  Self.FDepth     := 32;
757 <  Self.FStoreType := 8;
758 <
759 <  SetLength(Self.FData, Self.FWidth * Self.FHeight * Self.FDepth div 8);
760 <  for y := 0 to Self.FHeight - 1 do
761 <  begin
762 <    for x := 0 to Self.FWidth - 1 do
763 <    begin
764 <      Self.FData[((Self.FWidth * y + x) * 4) + 0] := tempd[54 + (Self.FWidth * y + x) * 3 + 0];
765 <      Self.FData[((Self.FWidth * y + x) * 4) + 1] := tempd[54 + (Self.FWidth * y + x) * 3 + 1];
766 <      Self.FData[((Self.FWidth * y + x) * 4) + 2] := tempd[54 + (Self.FWidth * y + x) * 3 + 2];
767 <      Self.FData[((Self.FWidth * y + x) * 4) + 3] := 0;
768 <    end;
769 <  end;
770 <
771 <  Self.FDataType := [DT_Decoded32];
570 >  if not LoadMultiImageFromFile(filename, FImages) then
571 >    ShowMessage('Couldn''t load image file');
572   end;
573  
574  
575 <
776 <
777 < function TOniImage.WriteToBMP(filename: String): Boolean;
778 < var
779 <  filestream: TFileStream;
575 > function TOniImage.WriteToFile(filename: String): Boolean;
576   begin
577 <  filestream := TFileStream.Create(filename, fmCreate);
782 <  GetAsBMP(TStream(filestream));
783 <  filestream.Free;
577 >  SaveMultiImageToFile(filename, FImages);
578   end;
579  
580  
581  
582 <
789 < function TOniImage.GetMipMappedImage(var faded: TByteData): Boolean;
582 > function TOniImage.GetImageSize(MipMaps: Boolean): Integer;
583   var
584 <  i:      Integer;
585 <  x, y:   Word;
586 <  fadelvldata: TByteData;
794 <  revert: Boolean;
795 < begin
796 <  Result := False;
797 <
798 <  //    if not (DT_Decoded32 in Self.FDataType) then
799 <  //      Self.DecodeImage;
800 <  if Self.FStoreType = 9 then
801 <    Self.DecompressImage;
802 <  if not (DT_OniReverted in Self.FDataType) then
584 >  i: Integer;
585 > begin
586 >  if Length(FImages) > 0 then
587    begin
588 <    revert := True;
589 <    Self.RevertImage;
588 >    Result := FImages[0].Size;
589 >    if mipmaps then
590 >      for i := 1 to High(FImages) do
591 >        Result := Result + FImages[i].Size;
592    end
593    else
594 <    revert := False;
809 <
810 <  x := Self.FWidth;
811 <  y := Self.FHeight;
812 <  SetLength(faded, x * y * Self.FDepth div 8);
813 <  SetLength(fadelvldata, x * y * Self.FDepth div 8);
814 <  for i := 0 to Length(faded) - 1 do
815 <  begin
816 <    faded[i] := Self.FData[i];
817 <    fadelvldata[i] := Self.FData[i];
818 <  end;
819 <  repeat
820 <    fadelvldata := Self.ResizeImage(x, y, fadelvldata);
821 <    x := x div 2;
822 <    y := y div 2;
823 <    SetLength(faded, Length(faded) + x * y * Self.FDepth div 8);
824 <    for i := 0 to Length(fadelvldata) - 1 do
825 <      faded[Length(faded) - x * y * Self.FDepth div 8 + i] := fadelvldata[i];
826 <  until (x = 1) or (y = 1) or ((x mod 2) = 1) or ((y mod 2) = 1);
827 <  if (x > 1) and (y > 1) then
828 <    Exit;
829 <  Result := True;
830 <
831 <  if revert then
832 <    Self.RevertImage;
594 >    Result := -1;
595   end;
596  
835
597   end.

Diff Legend

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