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 128 by alloc, Wed Mar 28 00:57:53 2007 UTC vs.
Revision 193 by alloc, Sat May 26 14:24:55 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 <
20 <    function ResizeImage(oldx, oldy: Integer; img: TByteData): TByteData;
21 <    procedure RevertImage;
22 <    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 GetHasMipMaps: Boolean;
19    protected
20    public
21 <    property Loaded:    Boolean      Read FLoaded    Write FLoaded;
22 <    property DataType:  TImgDataType Read FDataType  Write FDataType;
23 <    property Width:     Word         Read FWidth     Write FWidth;
24 <    property Height:    Word         Read FHeight    Write FHeight;
25 <    property Depth:     Byte         Read FDepth     Write FDepth;
26 <    property StoreType: Byte         Read FStoreType Write FStoreType;
31 <    property Data:      TByteData    Read FData      Write FData;
21 >    property Images: TDynImageDataArray         read FImages;
22 >    property Image[MipGen: Integer]: TImageData read GetImage;
23 >    property Width[MipGen: Integer]: Integer    read GetWidth;
24 >    property Height[MipGen: Integer]: Integer   read GetHeight;
25 >    property Format: TImageFormat read GetImageFormat write SetImageFormat;
26 >    property HasMipMaps: Boolean read GetHasMipMaps;
27  
28      constructor Create;
29 +    procedure Free;
30      function Load(ConnectionID, FileID: Integer): Boolean;
31      function LoadFromPSpc(ConnectionID, FileID: Integer): Boolean;
32      function LoadFromTXMP(ConnectionID, FileID: Integer): Boolean;
33      function LoadFromTXMB(ConnectionID, FileID: Integer): Boolean;
38    function GetImageDataSize(fading: Boolean): Integer;
34  
35 <    procedure DecodeImageTo32bit;
35 >    procedure SaveDataToStream(MipMaps: Boolean; var Target: TStream);
36 >
37 >    function LoadFromFile(filename: String): Boolean;
38 >    function WriteToFile(filename: String): Boolean;
39  
40 <    procedure GetAsData(var Target: TStream); overload;
41 <    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;
40 >    procedure DrawOnCanvas(Canvas: TCanvas; Index: Integer);
41 >    function GetImageSize(MipMaps: Boolean): Integer;
42    published
43    end;
44  
# Line 56 | Line 46 | type
46   implementation
47  
48   //uses Functions;
49 + uses Img_DDSTypes, ImagingComponents;
50  
51  
52 + procedure TOniImage.DrawOnCanvas(Canvas: TCanvas; Index: Integer);
53 + var
54 +  singleimg: TImageData;
55 +  rect: TRect;
56 + begin
57 +  InitImage(singleimg);
58 +  CloneImage(FImages[Index-1], singleimg);
59 +  ConvertImage(singleimg, ifX8R8G8B8);
60 +  rect.Left := 0;
61 +  rect.Top := 0;
62 +  rect.Right := singleimg.Width - 1;
63 +  rect.Bottom := singleimg.Height - 1;
64 +  Canvas.Brush.Color := $C8D0D4;
65 +  Canvas.FillRect(Canvas.ClipRect);
66 +  DisplayImageData(Canvas, rect, singleimg, rect);
67 +  FreeImage(singleimg);
68 + end;
69 +
70  
71  
72   constructor TOniImage.Create;
73   begin
74 <  Self.FLoaded   := False;
75 <  Self.FDataType := [];
76 <  SetLength(Self.FData, 0);
77 <  Self.FWidth     := 0;
78 <  Self.FHeight    := 0;
79 <  Self.FDepth     := 0;
80 <  Self.FStoreType := 0;
74 > end;
75 >
76 >
77 >
78 > procedure TOniImage.Free;
79 > begin
80 >  FreeImagesInArray(FImages);
81   end;
82  
83  
84  
85  
86 < function TOniImage.ResizeImage(oldx, oldy: Integer; img: TByteData): TByteData;
78 < var
79 <  i, j: Integer;
80 <  col, row, row_orig: Integer;
86 > function TOniImage.GetImage(MipGen: Integer): TImageData;
87   begin
88 <  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
88 >  if MipGen <= Length(FImages) then
89    begin
90 <    if ((i mod oldx) = 0) and (i > 0) then
91 <    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;
90 >    InitImage(Result);
91 >    CloneImage(FImages[MipGen-1], Result);
92    end;
93   end;
94  
95  
96  
97 <
113 < procedure TOniImage.RevertImage;
114 < var
115 <  x, y, i: Integer;
116 <  tempd:   TByteData;
97 > function TOniImage.GetWidth(MipGen: Integer): Integer;
98   begin
99 <  SetLength(tempd, Self.FWidth * Self.FHeight * (Self.FDepth div 8));
100 <  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]
99 >  if MipGen <= Length(FImages) then
100 >    Result := FImages[MipGen-1].Width
101    else
102 <    Self.FDataType := Self.FDataType + [DT_OniReverted];
102 >    Result := -1;
103   end;
104  
105  
106 <
134 <
135 < procedure TOniImage.DecodeImageTo32bit;
136 < var
137 <  x, y:  Integer;
138 <  tempd: TByteData;
106 > function TOniImage.GetHeight(MipGen: Integer): Integer;
107   begin
108 <  if not (DT_Decoded32 in Self.FDataType) then
109 <  begin
110 <    SetLength(tempd, Self.FWidth * Self.FHeight * 4);
111 <    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;
108 >  if MipGen <= Length(FImages) then
109 >    Result := FImages[MipGen-1].Height
110 >  else
111 >    Result := -1;
112   end;
113  
114  
115 + function TOniImage.GetImageFormat: TImageFormat;
116 + begin
117 +  if Length(FImages) > 0 then
118 +    Result := FImages[0].Format
119 +  else
120 +    Result := ifUnknown;
121 + end;
122  
123 <
208 < procedure TOniImage.DecompressImage;
209 < type
210 <  Tcolor = record
211 <    RGBb: Byte;
212 <    RGBg: Byte;
213 <    RGBr: Byte;
214 <    RGBa: Byte;
215 <  end;
123 > procedure TOniImage.SetImageFormat(Format: TImageFormat);
124   var
125 <  i, j, x, y: Integer;
126 <  color:      array[1..4] of Tcolor;
127 <  pixel:      array[1..16] of Byte;
128 <  tempd:      TByteData;
129 < begin
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];
125 >  i: Integer;
126 > begin
127 >  if Length(FImages) > 0 then
128 >    for i := 0 to High(FImages) do
129 >      ConvertImage(FImages[i], Format);
130   end;
131  
132  
133 <
133 > function TOniImage.GetHasMipMaps: Boolean;
134 > begin
135 >  Result := Length(FImages) > 1;
136 > end;
137  
138  
139   function TOniImage.Load(ConnectionID, FileID: Integer): Boolean;
# Line 362 | Line 189 | var
189    rows:     array[0..2] of Word;
190    col, row: Byte;
191   begin
192 + (*
193    ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $08, SizeOf(PSpc), @PSpc);
194    PSpc.TXMP := PSpc.TXMP div 256;
195    if PSpc.TXMP = 0 then
# Line 464 | Line 292 | begin
292    Self.FStoreType := 8;
293    Self.FDataType  := [DT_Decoded32];
294    //    Self.RevertImage;
295 + *)
296   end;
297  
298  
# Line 472 | Line 301 | end;
301   function TOniImage.LoadFromTXMP(ConnectionID, FileID: Integer): Boolean;
302   var
303    img_addr: Integer;
304 +  data: TMemoryStream;
305 +  hdr: TDDSDXTHeader;
306 +  imginfo: Integer;
307 +  x,y, i: Integer;
308 +
309 +  _width, _height: Word;
310 +  _storetype: Byte;
311 +  _depth: Byte;
312   begin
313    Result := True;
314 <  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $8C, SizeOf(Self.FWidth), @Self.FWidth);
315 <  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $8E, SizeOf(Self.FHeight), @Self.FHeight);
316 <  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $90, SizeOf(Self.FStoreType),
317 <    @Self.FStoreType);
314 >  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $8C, SizeOf(_width), @_width);
315 >  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $8E, SizeOf(_height), @_height);
316 >  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $90, SizeOf(_storetype), @_storetype);
317 >  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $88, SizeOf(imginfo), @imginfo);
318    if ConManager.Connection[ConnectionID].DataOS = DOS_WIN then
319      ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $9C, SizeOf(img_addr), @img_addr)
320    else
321      ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $A0, SizeOf(img_addr), @img_addr);
322  
323 <  case Self.FStoreType of
323 >  case _storetype of
324      0, 1, 2:
325 <    begin
326 <      SetLength(Self.FData, Self.FWidth * Self.FHeight * 2);
327 <      Self.FDepth := 16;
491 <    end;
492 <    8:
493 <    begin
494 <      SetLength(Self.FData, Self.FWidth * Self.FHeight * 4);
495 <      Self.FDepth := 32;
496 <    end;
325 >      _depth := 16;
326 >    7, 8:
327 >      _depth := 32;
328      9:
329 <    begin
499 <      SetLength(Self.FData, Self.FWidth * Self.FHeight div 2);
500 <      Self.FDepth := 16;
501 <    end;
329 >      _depth := 16;
330      else
331        Result := False;
332        Exit;
333    end;
334  
335 +  with hdr do
336 +  begin
337 +    FOURCC := 'DDS ';
338 +    with SURFACEDESC2 do
339 +    begin
340 +      Size := 124;
341 +      Flags := DDSD_CAPS or DDSD_PIXELFORMAT or DDSD_WIDTH or DDSD_HEIGHT;
342 +      if _storetype = 9 then
343 +        Flags := Flags or DDSD_LINEARSIZE
344 +      else
345 +        Flags := Flags or DDSD_PITCH;
346 +      if (imginfo and $01) > 0 then
347 +        Flags := Flags or DDSD_MIPMAPCOUNT;
348 +      Height := _height;
349 +      Width := _width;
350 +      if _storetype = 9 then
351 +        PitchOrLinearSize := width * height div 2
352 +      else
353 +        PitchOrLinearSize := width * _depth div 8;
354 +      Depth := 0;
355 +      MipMapCount := 1;
356 +      if (imginfo and $01) > 0 then
357 +      begin
358 +        x := width;
359 +        y := height;
360 +        while (x > 1) and (y > 1) do
361 +        begin
362 +          x := x div 2;
363 +          y := y div 2;
364 +          Inc(MipMapCount);
365 +        end;
366 +      end;
367 +      for i := 1 to 11 do
368 +        Reserved[i] := 0;
369 +      with PIXELFORMAT do
370 +      begin
371 +        Size := 32;
372 +        if _storetype = 9 then
373 +          Flags := DDPF_FOURCC
374 +        else
375 +          Flags := DDPF_RGB;
376 +        if _storetype in [0, 2] then
377 +          Flags := Flags or DDPF_ALPHAPIXELS;
378 +        if _storetype = 9 then
379 +          FOURCC := 'DXT1'
380 +        else
381 +        begin
382 +          RGBBitCount := _depth;
383 +          case _storetype of
384 +            0: begin
385 +              RBitMask := $0F00;
386 +              GBitMask := $00F0;
387 +              BBitMask := $000F;
388 +              AlphaBitMask := $F000;
389 +            end;
390 +            1, 2: begin
391 +              RBitMask := $7C00;
392 +              GBitMask := $03E0;
393 +              BBitMask := $001F;
394 +              if _storetype = 2 then
395 +                AlphaBitMask := $8000
396 +              else
397 +                AlphaBitMask := $0000;
398 +            end;
399 +            8: begin
400 +              RBitMask := $00FF0000;
401 +              GBitMask := $0000FF00;
402 +              BBitMask := $000000FF;
403 +              AlphaBitMask := $00000000;
404 +            end;
405 +          end;
406 +        end;
407 +      end;
408 +      with DDSCAPS2 do
409 +      begin
410 +        Caps1 := DDSCAPS_TEXTURE;
411 +        if (imginfo and $01) > 0 then
412 +          Caps1 := Caps1 or DDSCAPS_COMPLEX or DDSCAPS_MIPMAP;
413 +        Caps2 := 0;
414 +        Reserved[1] := 0;
415 +        Reserved[2] := 0;
416 +      end;
417 +    end;
418 +  end;
419 +
420 +  data := TMemoryStream.Create;
421 +  data.Write(hdr, SizeOf(hdr));
422    if ConManager.Connection[ConnectionID].DataOS = DOS_WIN then
423 <    ConManager.Connection[ConnectionID].LoadRawFile(fileid, $9C, FData)
423 >    ConManager.Connection[ConnectionID].LoadRawFile(fileid, $9C, TStream(data))
424    else
425 <    ConManager.Connection[ConnectionID].LoadRawFile(fileid, $A0, FData);
425 >    ConManager.Connection[ConnectionID].LoadRawFile(fileid, $A0, TStream(data));
426  
427 <  Self.FDataType := [DT_OniReverted, DT_Oni];
427 > //  data.Seek(0, soFromBeginning);
428 > //  data.SaveToFile('m:\test.txmp');
429 >
430 >  data.Seek(0, soFromBeginning);
431 >  result := LoadMultiImageFromStream(data, FImages);
432 >  data.Free;
433 > {
434 >  if result then
435 >  begin
436 >    for i := 0 to High(FImages) do
437 >    begin
438 >      data := TMemoryStream.Create;
439 >      data.Write(FImages[i].Bits^, FImages[i].Size);
440 >      data.Seek(0, soFromBeginning);
441 >      data.SaveToFile('m:\test.txmp.'+IntToStr(i));
442 >      data.Free;
443 >    end;
444 >  end;
445 > }
446 >  if not result then
447 >  begin
448 >    ShowMessage('Error while loading file' + #13#10 + DetermineStreamFormat(data));
449 > //    data.SaveToFile('m:\prob.dds');
450 >  end;
451   end;
452  
453  
# Line 521 | Line 459 | var
459    rows, cols: Word;
460    linkcount: Integer;
461    link: Integer;
462 <  images_decoded: array of TOniImage;
462 >  images: array of TOniImage;
463    x_start, y_start: Integer;
464 +
465 +  width, height: Word;
466   begin
467 <  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $10, SizeOf(Self.FWidth), @Self.FWidth);
468 <  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $12, SizeOf(Self.FHeight), @Self.FHeight);
467 >  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $10, SizeOf(width), @width);
468 >  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $12, SizeOf(height), @height);
469    ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $18, SizeOf(cols), @cols);
470    ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $1A, SizeOf(rows), @rows);
471    ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $1C, SizeOf(linkcount), @linkcount);
472 <  SetLength(images_decoded, linkcount);
472 >  SetLength(images, linkcount);
473    for i := 0 to linkcount - 1 do
474    begin
475      ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $20 + i * 4, SizeOf(link), @link);
476      link := link div 256;
477 <    images_decoded[i] := TOniImage.Create;
478 <    images_decoded[i].LoadFromTXMP(ConnectionID, link);
479 <    images_decoded[i].DecodeImageTo32bit;
480 <    images_decoded[i].RevertImage;
477 >    images[i] := TOniImage.Create;
478 >    images[i].LoadFromTXMP(ConnectionID, link);
479 >    SetLength(FImages, 1);
480 >    NewImage(width, height, ifA1R5G5B5, FImages[0]);
481    end;
542  SetLength(Self.FData, Self.FWidth * Self.FHeight * 4);
482    for y := 0 to rows - 1 do
483    begin
484      for x := 0 to cols - 1 do
485      begin
486 <      imgid   := y * cols + x;
486 >      imgid := y * cols + x;
487        x_start := 0;
488        y_start := 0;
489        for i := 0 to x do
490          if i < x then
491 <          x_start := x_start + images_decoded[i].Width;
491 >          x_start := x_start + images[i].Image[0].Width;
492        for i := 0 to y do
493          if i < y then
494 <          y_start := y_start + images_decoded[i].Height;
495 <      for y2 := 0 to images_decoded[imgid].Height - 1 do
496 <      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;
494 >          y_start := y_start + images[i].Image[0].Height;
495 >      CopyRect(images[imgid].Image[0], 0, 0, images[imgid].Image[0].Width,
496 >          images[imgid].Image[0].Height, FImages[0], x_start, y_start);
497      end;
498    end;
499    for i := 0 to linkcount - 1 do
500 <    images_decoded[i].Free;
578 <  Self.FDepth     := 32;
579 <  Self.FStoreType := 8;
580 <  Self.FDataType  := [DT_Decoded32];
581 <  Self.RevertImage;
500 >    images[i].Free;
501   end;
502  
503  
504  
505 <
587 < function TOniImage.GetImageDataSize(fading: Boolean): Integer;
505 > procedure TOniImage.SaveDataToStream(MipMaps: Boolean; var Target: TStream);
506   var
507 <  size: Integer;
508 <  x, y: Word;
509 <
510 <  function GetImgSize(w,h, storetype: Integer): Integer;
507 >  images: TDynImageDataArray;
508 >  mem: TMemoryStream;
509 >  i: Integer;
510 > begin
511 >  if Length(FImages) = 0 then
512 >    Exit;
513 >  if MipMaps then
514    begin
515 <    case storetype of
516 <      0, 1, 2:
517 <        Result := w*h*2;
518 <      8:
519 <        Result := w*h*4;
520 <      9:
521 <        Result :=  Max(1, w div 4) * Max(1, h div 4) * 8;
515 >    if Length(FImages) = 1 then
516 >    begin
517 >      if not GenerateMipMaps(FImages[0], 0, images) then
518 >      begin
519 >        ShowMessage('Could not generate MipMaps');
520 >        Exit;
521 >      end;
522 >    end
523      else
524 <      Result := -1;
524 >    begin
525 >      SetLength(images, Length(FImages));
526 >      for i := 0 to High(FImages) do
527 >        CloneImage(FImages[i], images[i]);
528      end;
529 <  end;
530 <
531 < begin
532 <  x    := Self.FWidth;
533 <  y    := Self.FHeight;
534 <  size := GetImgSize(x, y, FStoreType);
535 <  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;
619 < end;
620 <
621 <
622 <
623 <
624 < procedure TOniImage.GetAsData(var Target: TStream);
625 < var
626 <  revert: Boolean;
627 < begin
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;
529 >    mem := TMemoryStream.Create;
530 >    if not SaveMultiImageToStream('dds', mem, images) then
531 >    begin
532 >      ShowMessage('Could not save images to stream');
533 >      Exit;
534 >    end;
535 >    FreeImagesInArray(images);
536    end
537    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;
643 end;
644
645 procedure TOniImage.GetAsData(var Target: TByteData);
646 var
647  mem: TStream;
648 begin
649  mem := TMemoryStream.Create;
650  GetAsData(mem);
651  SetLength(Target, mem.Size);
652  mem.Read(Target[0], mem.Size);
653  mem.Free;
654 end;
655
656
657 procedure TOniImage.GetAs32bit(var Target: TStream);
658 begin
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);
665 end;
666
667 procedure TOniImage.GetAs32bit(var Target: TByteData);
668 var
669  mem: TStream;
670 begin
671  mem := TMemoryStream.Create;
672  GetAs32bit(mem);
673  SetLength(Target, mem.Size);
674  mem.Read(Target[0], mem.Size);
675  mem.Free;
676 end;
677
678
679 procedure TOniImage.GetAsBMP(var Target: TByteData);
680 const
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);
685 var
686  i, x, y: Integer;
687 begin
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
538    begin
539 <    for x := 0 to Self.FWidth - 1 do
539 >    mem := TMemoryStream.Create;
540 >    if not SaveImageToStream('dds', mem, FImages[0]) then
541      begin
542 <      Target[((Self.FWidth * y + x) * 3) + 0 + 54] := Self.FData[(Self.FWidth * y + x) * 4 + 0];
543 <      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];
542 >      ShowMessage('Could not save image to stream');
543 >      Exit;
544      end;
545    end;
546 +  if not Assigned(Target) then
547 +    Target := TMemoryStream.Create;
548  
549 <  for i := 0 to High(BMPheader) do
550 <    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;
720 < end;
721 <
549 > //  mem.Seek(0, soFromBeginning);
550 > //  mem.SaveToFile('m:\dds.dds');
551  
552 < procedure TOniImage.GetAsBMP(var Target: TStream);
553 < var
554 <  data: TByteData;
555 <  streampos: Integer;
727 < begin
728 <  GetAsBMP(data);
729 <  streampos := Target.Position;
730 <  Target.Write(data[0], Length(data));
731 <  Target.Seek(streampos, soFromBeginning);
552 >  mem.Seek(128, soFromBeginning);
553 >  Target.CopyFrom(mem, mem.Size - 128);
554 >  mem.Free;
555 >  Target.Seek(0, soFromBeginning);
556   end;
557  
558  
559 < function TOniImage.LoadFromBMP(filename: String): Boolean;
736 < var
737 <  filestream: TFileStream;
738 <  tempd:      TByteData;
739 <
740 <  x, y: Integer;
559 > function TOniImage.LoadFromFile(filename: String): Boolean;
560   begin
561 <  filestream := TFileStream.Create(filename, fmOpenRead);
562 <  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];
561 >  if not LoadMultiImageFromFile(filename, FImages) then
562 >    ShowMessage('Couldn''t load image file');
563   end;
564  
565  
566 <
800 <
801 < function TOniImage.WriteToBMP(filename: String): Boolean;
802 < var
803 <  filestream: TFileStream;
566 > function TOniImage.WriteToFile(filename: String): Boolean;
567   begin
568 <  filestream := TFileStream.Create(filename, fmCreate);
806 <  GetAsBMP(TStream(filestream));
807 <  filestream.Free;
568 >  SaveMultiImageToFile(filename, FImages);
569   end;
570  
571  
572  
573 < function TOniImage.GetMipMappedImage(var Target: TByteData): Boolean;
573 > function TOniImage.GetImageSize(MipMaps: Boolean): Integer;
574   var
575 <  i:      Integer;
576 <  x, y:   Word;
577 <  fadelvldata: TByteData;
817 <  revert: Boolean;
818 < begin
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
575 >  i: Integer;
576 > begin
577 >  if Length(FImages) > 0 then
578    begin
579 <    revert := True;
580 <    Self.RevertImage;
579 >    Result := FImages[0].Size;
580 >    if mipmaps then
581 >      for i := 1 to High(FImages) do
582 >        Result := Result + FImages[i].Size;
583    end
584    else
585 <    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;
585 >    Result := -1;
586   end;
587  
858
859 function TOniImage.GetMipMappedImage(var Target: TStream): Boolean;
860 var
861  data: TByteData;
862  streampos: Integer;
863 begin
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);
870 end;
871
872
588   end.

Diff Legend

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