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 127 by alloc, Fri Mar 23 17:14:40 2007 UTC vs.
Revision 204 by alloc, Sun May 27 20:03:41 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 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 +
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;
35    function LoadFromPSpc(ConnectionID, FileID: Integer): Boolean;
41      function LoadFromTXMP(ConnectionID, FileID: Integer): Boolean;
42      function LoadFromTXMB(ConnectionID, FileID: Integer): Boolean;
43 <    function GetImageDataSize(fading: Boolean): Integer;
39 <
40 <    procedure DecodeImageTo32bit;
41 <
42 <    procedure GetAsData(var Target: TStream); overload;
43 <    procedure GetAsData(var Target: TByteData); overload;
44 <    procedure GetAs32bit(var Target: TStream); overload;
45 <    procedure GetAs32bit(var Target: TByteData); overload;
46 <    procedure GetAsBMP(var Target: TStream); overload;
47 <    procedure GetAsBMP(var Target: TByteData); overload;
48 <    function LoadFromBMP(filename: String): Boolean;
49 <    function WriteToBMP(filename: String): Boolean;
50 <    function GetMipMappedImage(var Target: TStream): Boolean; overload;
51 <    function GetMipMappedImage(var Target: TByteData): Boolean; overload;
43 >    function LoadFromPSpc(ConnectionID, FileID: Integer): Boolean;
44    published
45    end;
46  
47  
48   implementation
49  
50 < //uses Functions;
50 > uses Img_DDSTypes, ImagingComponents;
51 >
52 >
53 > function TOniImage.GetImage(MipGen: Integer): TImageData;
54 > begin
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.GetHeight(MipGen: Integer): Integer;
73 > begin
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 > procedure TOniImage.SetImageFormat(Format: TImageFormat);
90 > var
91 >  i: Integer;
92 > begin
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 > function TOniImage.GetHasMipMaps: Boolean;
107 > begin
108 >  Result := Length(FImages) > 1;
109 > end;
110  
111  
112  
113  
114   constructor TOniImage.Create;
115   begin
116 <  Self.FLoaded   := False;
117 <  Self.FDataType := [];
118 <  SetLength(Self.FData, 0);
119 <  Self.FWidth     := 0;
120 <  Self.FHeight    := 0;
121 <  Self.FDepth     := 0;
122 <  Self.FStoreType := 0;
116 > end;
117 >
118 > procedure TOniImage.Free;
119 > begin
120 >  FreeImagesInArray(FImages);
121 > end;
122 >
123 >
124 >
125 >
126 > function TOniImage.GetImageSize(MipMaps: Boolean): Integer;
127 > var
128 >  i: Integer;
129 > begin
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 := -1;
139   end;
140  
141  
142  
143  
144 < function TOniImage.ResizeImage(oldx, oldy: Integer; img: TByteData): TByteData;
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 >
151 >
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 >  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 >
177 >
178 >
179 >
180 > procedure TOniImage.SaveDataToStream(MipMaps: Boolean; var Target: TStream);
181   var
182 <  i, j: Integer;
183 <  col, row, row_orig: Integer;
182 >  images: TDynImageDataArray;
183 >  mem: TMemoryStream;
184 >  i: Integer;
185   begin
186 <  SetLength(Result, (oldx div 2) * (oldy div 2) * (Self.FDepth div 8));
187 <  row_orig := 0;
188 <  row      := 0;
85 <  col      := 0;
86 <  for i := 0 to (oldx * oldy) - 1 do
186 >  if Length(FImages) = 0 then
187 >    Exit;
188 >  if MipMaps then
189    begin
190 <    if ((i mod oldx) = 0) and (i > 0) then
190 >    if Length(FImages) = 1 then
191      begin
192 <      Inc(row_orig);
91 <      if (row_orig mod 2) = 0 then
192 >      if not GenerateMipMaps(FImages[0], 0, images) then
193        begin
194 <        Inc(row);
195 <        col := 0;
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 <    if (row_orig mod 2) = 0 then
204 >    mem := TMemoryStream.Create;
205 >    if not SaveMultiImageToStream('dds', mem, images) then
206      begin
207 <      if (i mod 2) = 0 then
208 <      begin
209 <        for j := 0 to (Self.FDepth div 8) - 1 do
210 <          Result[((row * (oldx div 2)) + col) * (Self.FDepth div 8) + j] :=
211 <            img[(i * (Self.FDepth div 8)) + j];
212 <        Inc(col);
213 <      end;
207 >      ShowMessage('Could not save images to stream');
208 >      Exit;
209 >    end;
210 >    FreeImagesInArray(images);
211 >  end
212 >  else
213 >  begin
214 >    mem := TMemoryStream.Create;
215 >    if not SaveImageToStream('dds', mem, FImages[0]) then
216 >    begin
217 >      ShowMessage('Could not save image to stream');
218 >      Exit;
219      end;
220    end;
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  
230  
231  
232  
233 < procedure TOniImage.RevertImage;
233 >
234 > function TOniImage.Load(ConnectionID, FileID: Integer): Boolean;
235   var
236 <  x, y, i: Integer;
116 <  tempd:   TByteData;
236 >  FileInfo: TFileInfo;
237   begin
238 <  SetLength(tempd, Self.FWidth * Self.FHeight * (Self.FDepth div 8));
239 <  for y := 0 to Self.FHeight - 1 do
240 <    for x := 0 to Self.FWidth - 1 do
241 <      for i := 0 to (Self.FDepth div 8) - 1 do
242 <        tempd[((Self.FWidth * (Self.FHeight - 1 - y) + x) * (Self.FDepth div 8)) + i] :=
243 <          Self.FData[(Self.FWidth * y + x) * (Self.FDepth div 8) + i];
244 <  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]
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 <    Self.FDataType := Self.FDataType + [DT_OniReverted];
246 >    Result := False;
247   end;
248  
249  
250  
251  
252 < procedure TOniImage.DecodeImageTo32bit;
252 > function TOniImage.LoadFromTXMP(ConnectionID, FileID: Integer): Boolean;
253   var
254 <  x, y:  Integer;
255 <  tempd: TByteData;
254 >  img_addr: Integer;
255 >  data: TMemoryStream;
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 <  if not (DT_Decoded32 in Self.FDataType) then
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 _storetype of
275 >    0, 1, 2:
276 >      _depth := 16;
277 >    7, 8:
278 >      _depth := 32;
279 >    9:
280 >      _depth := 16;
281 >    else
282 >      Result := False;
283 >      Exit;
284 >  end;
285 >
286 >  with hdr do
287    begin
288 <    SetLength(tempd, Self.FWidth * Self.FHeight * 4);
289 <    case Self.FStoreType of
290 <      0: // 16bit, RGB444, A4?
288 >    FOURCC := 'DDS ';
289 >    with SURFACEDESC2 do
290 >    begin
291 >      Size := 124;
292 >      Flags := DDSD_CAPS or DDSD_PIXELFORMAT or DDSD_WIDTH or DDSD_HEIGHT;
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 := _height;
300 >      Width := _width;
301 >      if _storetype = 9 then
302 >        PitchOrLinearSize := width * height div 2
303 >      else
304 >        PitchOrLinearSize := width * _depth div 8;
305 >      Depth := 0;
306 >      MipMapCount := 1;
307 >      if (imginfo and $01) > 0 then
308        begin
309 <        for y := 0 to Self.FHeight - 1 do
309 >        x := width;
310 >        y := height;
311 >        while (x > 1) and (y > 1) do
312          begin
313 <          for x := 0 to Self.FWidth - 1 do
314 <          begin
315 <            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;
313 >          x := x div 2;
314 >          y := y div 2;
315 >          Inc(MipMapCount);
316          end;
317        end;
318 <      1, 2: // 16bit, RGB555, A1?
318 >      for i := 1 to 11 do
319 >        Reserved[i] := 0;
320 >      with PIXELFORMAT do
321        begin
322 <        for y := 0 to Self.FHeight - 1 do
322 >        Size := 32;
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 <          for x := 0 to Self.FWidth - 1 do
334 <          begin
335 <            tempd[((Self.FWidth * y + x) * 4) + 0] :=
336 <              Round(((Self.FData[(Self.FWidth * y + x) * 2] + Self.FData[(Self.FWidth * y + x) * 2 + 1] * 256) and
337 <              $001F) / $001F * 255);
338 <            tempd[((Self.FWidth * y + x) * 4) + 1] :=
339 <              Round(((Self.FData[(Self.FWidth * y + x) * 2] + Self.FData[(Self.FWidth * y + x) * 2 + 1] * 256) and
340 <              $03E0) / $03E0 * 255);
341 <            tempd[((Self.FWidth * y + x) * 4) + 2] :=
342 <              Round(((Self.FData[(Self.FWidth * y + x) * 2] + Self.FData[(Self.FWidth * y + x) * 2 + 1] * 256) and
343 <              $7C00) / $7C00 * 255);
344 <            tempd[((Self.FWidth * y + x) * 4) + 3] := 0;
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 <      8: // 32bit, RGB888, A8?
183 <      begin end;
184 <      9: // Compressed, RGB565
359 >      with DDSCAPS2 do
360        begin
361 <        DecompressImage;
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;
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];
369    end;
201  if DT_OniReverted in Self.FDataType then
202    Self.RevertImage;
203 end;
204
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, TStream(data))
375 +  else
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 < procedure TOniImage.DecompressImage;
383 < type
384 <  Tcolor = record
211 <    RGBb: Byte;
212 <    RGBg: Byte;
213 <    RGBr: Byte;
214 <    RGBa: Byte;
215 <  end;
216 < var
217 <  i, j, x, y: Integer;
218 <  color:      array[1..4] of Tcolor;
219 <  pixel:      array[1..16] of Byte;
220 <  tempd:      TByteData;
221 < 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;
382 >  if not result then
383 >  begin
384 >    ShowMessage('Error while loading file' + #13#10 + DetermineStreamFormat(data));
385    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];
386   end;
387  
388  
389  
390  
391  
392 < function TOniImage.Load(ConnectionID, FileID: Integer): Boolean;
392 > function TOniImage.LoadFromTXMB(ConnectionID, FileID: Integer): Boolean;
393   var
394 <  FileInfo: TFileInfo;
394 >  i, x, y, imgid: Integer;
395 >  rows, cols: Word;
396 >  linkcount: Integer;
397 >  link: Integer;
398 >  images: array of TOniImage;
399 >  x_start, y_start: Integer;
400 >
401 >  width, height: Word;
402   begin
403 <  FileInfo := ConManager.Connection[ConnectionID].GetFileInfo(fileid);
404 <  if FileInfo.Extension = 'PSpc' then
405 <    Result := LoadFromPSpc(ConnectionID, fileid)
406 <  else if FileInfo.Extension = 'TXMB' then
407 <    Result := LoadFromTXMB(ConnectionID, fileid)
408 <  else if FileInfo.Extension = 'TXMP' then
409 <    Result := LoadFromTXMP(ConnectionID, fileid)
410 <  else
411 <    Result := False;
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, 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[i] := TOniImage.Create;
415 >    images[i].LoadFromTXMP(ConnectionID, link);
416 >    SetLength(FImages, 1);
417 >    NewImage(width, height, ifA1R5G5B5, FImages[0]);
418 >  end;
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;
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[i].Image[0].Width;
429 >      for i := 0 to y do
430 >        if i < y then
431 >          y_start := y_start + images[i].Image[0].Height;
432 >      CopyRect(images[imgid].Image[0], 0, 0, images[imgid].Image[0].Width,
433 >          images[imgid].Image[0].Height, FImages[0], x_start, y_start);
434 >    end;
435 >  end;
436 >  for i := 0 to linkcount - 1 do
437 >    images[i].Free;
438 >  Result := True;
439   end;
440  
441  
442  
443  
444 +
445   function TOniImage.LoadFromPSpc(ConnectionID, FileID: Integer): Boolean;
446   type
447    TPoint = packed record
# Line 343 | Line 458 | type
458      x_txmp, y_txmp: Word;
459      x_pspc, y_pspc: Word;
460      w, h:    Word;
461 <    imgdata: TByteData;
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
469 <  x, y, pixel: Word;
469 >  x, y: Word;
470    i: Integer;
471  
472    PSpc:     TPSpc;
473    txmpimg:  TOniImage;
357  txmpdata: TByteData;
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 +  pspcimage: TImageData;
482   begin
483    ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $08, SizeOf(PSpc), @PSpc);
484    PSpc.TXMP := PSpc.TXMP div 256;
# Line 370 | Line 488 | begin
488      Exit;
489    end;
490    txmpimg := TOniImage.Create;
491 <  txmpimg.LoadFromTXMP(ConnectionID, PSpc.TXMP);
492 <  txmpimg.DecodeImageTo32bit;
493 < //  txmpimg.WriteToBMP('C:\file.bmp');
494 <  txmpimg.GetAs32bit(txmpdata);
495 < {    ShowMessage(IntToStr(txmpimg.Width)+'x'+IntToStr(txmpimg.Height));
496 <    for i:=0 to High(txmpdata) do
497 <      txmpimg.Data[i]:=txmpdata[i];
380 <    txmpimg.WriteToBMP('D:\file2.bmp');
381 < }
382 <  with PSpc do
491 >  txmpimg.Load(ConnectionID, PSpc.TXMP);
492 >  CloneImage(txmpimg.Image[1], pspcimage);
493 >  txmpimg.Free;
494 >
495 >  Result := False;
496 >
497 >  with pspc do
498    begin
499      for i := 0 to 2 do
500      begin
# Line 393 | Line 508 | begin
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;
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
# Line 403 | Line 518 | begin
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 := p2[i].X - p1[i].X + 1;
522 <        parts[part].h := p2[i].Y - p1[i].Y + 1;
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 <        SetLength(parts[part].imgdata, parts[part].w * parts[part].h * 4);
527 <        for y := 0 to parts[part].h - 1 do
528 <        begin
529 <          for x := 0 to parts[part].w - 1 do
530 <          begin
531 <            for pixel := 0 to 3 do
417 <            begin
418 <              parts[part].imgdata[(y * parts[part].w + x) * 4 + pixel] :=
419 <                txmpdata[((parts[part].y_txmp + y) * txmpimg.Width +
420 <                parts[part].x_txmp + x) * 4 + pixel];
421 <            end;
422 <          end;
423 <        end;
526 >
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
# Line 430 | Line 538 | begin
538  
539    end;
540  
433  txmpimg.Free;
434  txmpimg := TOniImage.Create;
541    for i := 0 to 8 do
542    begin
543      if parts[i].used then
544      begin
545 <      SetLength(txmpimg.FData, Length(parts[i].imgdata));
440 <      for pixel := 0 to High(parts[i].imgdata) do
441 <        txmpimg.Data[pixel] := parts[i].imgdata[pixel];
442 <      txmpimg.Width := parts[i].w;
443 <      txmpimg.Height    := parts[i].h;
444 <      txmpimg.StoreType := 8;
445 <      txmpimg.DataType  := [DT_Decoded32];
446 <      txmpimg.Depth     := 32;
447 <      txmpimg.WriteToBMP('M:\' + IntToStr(i) + '.bmp');
545 > //      SaveImageToFile('M:\' + IntToStr(i) + '.bmp', parts[i].imgdata);
546      end;
547    end;
450  txmpimg.Free;
548  
549 <  Self.FWidth  := 0;
550 <  Self.FHeight := 0;
551 <  for i := 0 to 2 do
455 <  begin
456 <    Inc(Self.FWidth, cols[i]);
457 <    Inc(Self.FHeight, rows[i]);
458 <  end;
459 <  SetLength(Self.FData, Self.FWidth * Self.FHeight * 4);
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 <  //Combine data parts
553 >  NewImage(x, y, pspcimage.Format, FImages[0]);
554  
555 <  Self.FDepth     := 32;
556 <  Self.FStoreType := 8;
465 <  Self.FDataType  := [DT_Decoded32];
466 <  //    Self.RevertImage;
467 < end;
468 <
469 <
470 <
471 <
472 < function TOniImage.LoadFromTXMP(ConnectionID, FileID: Integer): Boolean;
473 < var
474 <  img_addr: Integer;
475 < begin
476 <  Result := True;
477 <  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $8C, SizeOf(Self.FWidth), @Self.FWidth);
478 <  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $8E, SizeOf(Self.FHeight), @Self.FHeight);
479 <  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $90, SizeOf(Self.FStoreType),
480 <    @Self.FStoreType);
481 <  if ConManager.Connection[ConnectionID].DataOS = DOS_WIN then
482 <    ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $9C, SizeOf(img_addr), @img_addr)
483 <  else
484 <    ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $A0, SizeOf(img_addr), @img_addr);
485 <
486 <  case Self.FStoreType of
487 <    0, 1, 2:
488 <    begin
489 <      SetLength(Self.FData, Self.FWidth * Self.FHeight * 2);
490 <      Self.FDepth := 16;
491 <    end;
492 <    8:
493 <    begin
494 <      SetLength(Self.FData, Self.FWidth * Self.FHeight * 4);
495 <      Self.FDepth := 32;
496 <    end;
497 <    9:
498 <    begin
499 <      SetLength(Self.FData, Self.FWidth * Self.FHeight div 2);
500 <      Self.FDepth := 16;
501 <    end;
502 <    else
503 <      Result := False;
504 <      Exit;
505 <  end;
506 <
507 <  if ConManager.Connection[ConnectionID].DataOS = DOS_WIN then
508 <    ConManager.Connection[ConnectionID].LoadRawFile(fileid, $9C, FData)
509 <  else
510 <    ConManager.Connection[ConnectionID].LoadRawFile(fileid, $A0, FData);
511 <
512 <  Self.FDataType := [DT_OniReverted, DT_Oni];
513 < end;
514 <
515 <
516 <
517 <
518 < function TOniImage.LoadFromTXMB(ConnectionID, FileID: Integer): Boolean;
519 < var
520 <  i, x, y, x2, y2, pixelid, imgid: Integer;
521 <  rows, cols: Word;
522 <  linkcount: Integer;
523 <  link: Integer;
524 <  images_decoded: array of TOniImage;
525 <  x_start, y_start: Integer;
526 < begin
527 <  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $10, SizeOf(Self.FWidth), @Self.FWidth);
528 <  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $12, SizeOf(Self.FHeight), @Self.FHeight);
529 <  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $18, SizeOf(cols), @cols);
530 <  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $1A, SizeOf(rows), @rows);
531 <  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $1C, SizeOf(linkcount), @linkcount);
532 <  SetLength(images_decoded, linkcount);
533 <  for i := 0 to linkcount - 1 do
534 <  begin
535 <    ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $20 + i * 4, SizeOf(link), @link);
536 <    link := link div 256;
537 <    images_decoded[i] := TOniImage.Create;
538 <    images_decoded[i].LoadFromTXMP(ConnectionID, link);
539 <    images_decoded[i].DecodeImageTo32bit;
540 <    images_decoded[i].RevertImage;
541 <  end;
542 <  SetLength(Self.FData, Self.FWidth * Self.FHeight * 4);
543 <  for y := 0 to rows - 1 do
555 >  x := 0;
556 >  for col := 0 to 2 do
557    begin
558 <    for x := 0 to cols - 1 do
558 >    y := 0;
559 >    for row := 0 to 2 do
560      begin
561 <      imgid   := y * cols + x;
562 <      x_start := 0;
549 <      y_start := 0;
550 <      for i := 0 to x do
551 <        if i < x then
552 <          x_start := x_start + images_decoded[i].Width;
553 <      for i := 0 to y do
554 <        if i < y then
555 <          y_start := y_start + images_decoded[i].Height;
556 <      for y2 := 0 to images_decoded[imgid].Height - 1 do
561 >      part := row*3 + col;
562 >      if parts[part].used then
563        begin
564 <        for x2 := 0 to images_decoded[imgid].Width - 1 do
565 <        begin
566 <          if ((x_start + x2) < Self.FWidth) and ((y_start + y2) < Self.FHeight) then
567 <          begin
568 <            pixelid := y_start * Self.FWidth + x_start + y2 * Self.FWidth + x2;
569 <            Self.FData[pixelid * 4 + 0] :=
570 <              images_decoded[imgid].Data[(y2 * images_decoded[imgid].Width + x2) * 4 + 0];
571 <            Self.FData[pixelid * 4 + 1] :=
572 <              images_decoded[imgid].Data[(y2 * images_decoded[imgid].Width + x2) * 4 + 1];
573 <            Self.FData[pixelid * 4 + 2] :=
574 <              images_decoded[imgid].Data[(y2 * images_decoded[imgid].Width + x2) * 4 + 2];
575 <            Self.FData[pixelid * 4 + 3] :=
576 <              images_decoded[imgid].Data[(y2 * images_decoded[imgid].Width + x2) * 4 + 3];
577 <          end;
578 <        end;
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 <  end;
576 <  for i := 0 to linkcount - 1 do
577 <    images_decoded[i].Free;
578 <  Self.FDepth     := 32;
579 <  Self.FStoreType := 8;
580 <  Self.FDataType  := [DT_Decoded32];
581 <  Self.RevertImage;
582 < end;
583 <
584 <
585 <
586 <
587 < function TOniImage.GetImageDataSize(fading: Boolean): Integer;
588 < var
589 <  size: Integer;
590 <  x, y: Word;
591 <  bpp:  Byte;
592 <  minside: Byte;
593 < begin
594 <  minside := 1;
595 <  case Self.FStoreType of
596 <    9:
584 >    if cols[col] > 0 then
585      begin
586 <      bpp := 4;
587 <      minside := 4;
588 <    end;
589 <    0, 1, 2:
602 <      bpp := 16;
603 <    8:
604 <      bpp := 32;
605 <    else
606 <      Result := 0;
607 <      Exit;
608 <  end;
609 <
610 <  x    := Self.FWidth;
611 <  y    := Self.FHeight;
612 <  size := (x * y * bpp) div 8;
613 <  if fading then
614 <  begin
615 <    repeat
616 <      x    := x div 2;
617 <      y    := y div 2;
618 <      size := size + (x * y * bpp) div 8;
619 <    until (x = minside) or (y = minside);
620 <    if FStoreType = 9 then
621 <    begin
622 <      repeat
623 <        x    := x div 2;
624 <        y    := y div 2;
625 <        size := size + (x * y * 16) div 8;
626 <      until (x = 1) or (y = 1);
627 <    end;
628 <  end;
629 <  Result := size;
630 < end;
631 <
632 <
633 <
634 <
635 < procedure TOniImage.GetAsData(var Target: TStream);
636 < var
637 <  revert: Boolean;
638 < begin
639 <  //    if not (DT_Decoded32 in Self.FDataType) then
640 <  //      Self.DecodeImage;
641 <  if not (DT_OniReverted in Self.FDataType) then
642 <  begin
643 <    revert := True;
644 <    Self.RevertImage;
645 <  end
646 <  else
647 <    revert := False;
648 <  if not Assigned(Target) then
649 <    Target := TMemoryStream.Create;
650 <  Target.Write(FData[0], Length(FData));
651 <  Target.Seek(0, soFromBeginning);
652 <  if revert then
653 <    Self.RevertImage;
654 < end;
655 <
656 < procedure TOniImage.GetAsData(var Target: TByteData);
657 < var
658 <  mem: TStream;
659 < begin
660 <  mem := TMemoryStream.Create;
661 <  GetAsData(mem);
662 <  SetLength(Target, mem.Size);
663 <  mem.Read(Target[0], mem.Size);
664 <  mem.Free;
665 < end;
666 <
667 <
668 < procedure TOniImage.GetAs32bit(var Target: TStream);
669 < begin
670 <  if not (DT_Decoded32 in Self.FDataType) then
671 <    Self.DecodeImageTo32bit;
672 <  if not Assigned(Target) then
673 <    Target := TMemoryStream.Create;
674 <  Target.Write(FData[0], Length(FData));
675 <  Target.Seek(0, soFromBeginning);
676 < end;
677 <
678 < procedure TOniImage.GetAs32bit(var Target: TByteData);
679 < var
680 <  mem: TStream;
681 < begin
682 <  mem := TMemoryStream.Create;
683 <  GetAs32bit(mem);
684 <  SetLength(Target, mem.Size);
685 <  mem.Read(Target[0], mem.Size);
686 <  mem.Free;
687 < end;
688 <
689 <
690 < procedure TOniImage.GetAsBMP(var Target: TByteData);
691 < const
692 <  BMPheader: array[0..53] of Byte =
693 <    ($42, $4D, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0,
694 <    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,
695 <    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
696 < var
697 <  i, x, y: Integer;
698 < begin
699 <  if not (DT_Decoded32 in Self.FDataType) then
700 <    Self.DecodeImageTo32bit;
701 <
702 <  SetLength(Target, Self.FWidth * Self.FHeight * 3 + 54);
703 <  for y := 0 to Self.FHeight - 1 do
704 <  begin
705 <    for x := 0 to Self.FWidth - 1 do
706 <    begin
707 <      Target[((Self.FWidth * y + x) * 3) + 0 + 54] := Self.FData[(Self.FWidth * y + x) * 4 + 0];
708 <      Target[((Self.FWidth * y + x) * 3) + 1 + 54] := Self.FData[(Self.FWidth * y + x) * 4 + 1];
709 <      Target[((Self.FWidth * y + x) * 3) + 2 + 54] := Self.FData[(Self.FWidth * y + x) * 4 + 2];
710 <    end;
711 <  end;
712 <
713 <  for i := 0 to High(BMPheader) do
714 <    Target[i] := BMPheader[i];
715 <  Target[2] := ((Self.FWidth * Self.FHeight * 3 + 54) and $000000FF) div $1;
716 <  Target[3]  := ((Self.FWidth * Self.FHeight * 3 + 54) and $0000FF00) div $100;
717 <  Target[4]  := ((Self.FWidth * Self.FHeight * 3 + 54) and $00FF0000) div $10000;
718 <  Target[5]  := ((Self.FWidth * Self.FHeight * 3 + 54) and $FF000000) div $1000000;
719 <  Target[18] := (Self.FWidth and $000000FF) div $1;
720 <  Target[19] := (Self.FWidth and $0000FF00) div $100;
721 <  Target[20] := (Self.FWidth and $00FF0000) div $10000;
722 <  Target[21] := (Self.FWidth and $FF000000) div $1000000;
723 <  Target[22] := (Self.FHeight and $000000FF) div $1;
724 <  Target[23] := (Self.FHeight and $0000FF00) div $100;
725 <  Target[24] := (Self.FHeight and $00FF0000) div $10000;
726 <  Target[25] := (Self.FHeight and $FF000000) div $1000000;
727 <  Target[34] := ((Self.FWidth * Self.FHeight * 3) and $000000FF) div $1;
728 <  Target[35] := ((Self.FWidth * Self.FHeight * 3) and $0000FF00) div $100;
729 <  Target[36] := ((Self.FWidth * Self.FHeight * 3) and $00FF0000) div $10000;
730 <  Target[37] := ((Self.FWidth * Self.FHeight * 3) and $FF000000) div $1000000;
731 < end;
732 <
733 <
734 < procedure TOniImage.GetAsBMP(var Target: TStream);
735 < var
736 <  data: TByteData;
737 <  streampos: Integer;
738 < begin
739 <  GetAsBMP(data);
740 <  streampos := Target.Position;
741 <  Target.Write(data[0], Length(data));
742 <  Target.Seek(streampos, soFromBeginning);
743 < end;
744 <
745 <
746 < function TOniImage.LoadFromBMP(filename: String): Boolean;
747 < var
748 <  filestream: TFileStream;
749 <  tempd:      TByteData;
750 <
751 <  x, y: Integer;
752 < begin
753 <  filestream := TFileStream.Create(filename, fmOpenRead);
754 <  SetLength(tempd, filestream.Size);
755 <  filestream.Read(tempd[0], filestream.Size);
756 <  filestream.Free;
757 <
758 <  if not ((tempd[00] = $42) and (tempd[01] = $4D)) then
759 <  begin
760 <    Result := False;
761 <    ShowMessage('Not a standard 24bit bitmap');
762 <    Exit;
763 <  end;
764 <  if not (tempd[10] = 54) then
765 <  begin
766 <    Result := False;
767 <    ShowMessage('Imagedata has to start at 0x54');
768 <    Exit;
769 <  end;
770 <  if not (tempd[14] = 40) then
771 <  begin
772 <    Result := False;
773 <    ShowMessage('Second bitmap header has to have 40 bytes');
774 <    Exit;
775 <  end;
776 <  if not (tempd[28] = 24) then
777 <  begin
778 <    Result := False;
779 <    ShowMessage('Bitmap has to have 24bits');
780 <    Exit;
781 <  end;
782 <  if not (tempd[30] = 0) then
783 <  begin
784 <    Result := False;
785 <    ShowMessage('Bitmap has to be uncompressed');
786 <    Exit;
787 <  end;
788 <
789 <  Self.FWidth     := tempd[18] + tempd[19] * 256 + tempd[20] * 256 * 256 + tempd[21] * 256 * 256 * 256;
790 <  Self.FHeight    := tempd[22] + tempd[23] * 256 + tempd[24] * 256 * 256 + tempd[25] * 256 * 256 * 256;
791 <  Self.FDepth     := 32;
792 <  Self.FStoreType := 8;
793 <
794 <  SetLength(Self.FData, Self.FWidth * Self.FHeight * Self.FDepth div 8);
795 <  for y := 0 to Self.FHeight - 1 do
796 <  begin
797 <    for x := 0 to Self.FWidth - 1 do
798 <    begin
799 <      Self.FData[((Self.FWidth * y + x) * 4) + 0] := tempd[54 + (Self.FWidth * y + x) * 3 + 0];
800 <      Self.FData[((Self.FWidth * y + x) * 4) + 1] := tempd[54 + (Self.FWidth * y + x) * 3 + 1];
801 <      Self.FData[((Self.FWidth * y + x) * 4) + 2] := tempd[54 + (Self.FWidth * y + x) * 3 + 2];
802 <      Self.FData[((Self.FWidth * y + x) * 4) + 3] := 0;
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 <
810 <
811 <
812 < function TOniImage.WriteToBMP(filename: String): Boolean;
813 < var
814 <  filestream: TFileStream;
815 < begin
816 <  filestream := TFileStream.Create(filename, fmCreate);
817 <  GetAsBMP(TStream(filestream));
818 <  filestream.Free;
819 < end;
820 <
821 <
822 <
823 < function TOniImage.GetMipMappedImage(var Target: TByteData): Boolean;
824 < var
825 <  i:      Integer;
826 <  x, y:   Word;
827 <  fadelvldata: TByteData;
828 <  revert: Boolean;
829 < begin
830 <  Result := False;
831 <
832 <  //    if not (DT_Decoded32 in Self.FDataType) then
833 <  //      Self.DecodeImage;
834 <  if Self.FStoreType = 9 then
835 <    Self.DecompressImage;
836 <  if not (DT_OniReverted in Self.FDataType) then
837 <  begin
838 <    revert := True;
839 <    Self.RevertImage;
840 <  end
841 <  else
842 <    revert := False;
593 >  FreeImage(pspcimage);
594 >  for i := 0 to 8 do
595 >    if parts[i].used then
596 >      FreeImage(parts[i].imgdata);
597  
844  x := Self.FWidth;
845  y := Self.FHeight;
846  SetLength(Target, x * y * Self.FDepth div 8);
847  SetLength(fadelvldata, x * y * Self.FDepth div 8);
848  for i := 0 to Length(Target) - 1 do
849  begin
850    Target[i] := Self.FData[i];
851    fadelvldata[i] := Self.FData[i];
852  end;
853  repeat
854    fadelvldata := Self.ResizeImage(x, y, fadelvldata);
855    x := x div 2;
856    y := y div 2;
857    SetLength(Target, Length(Target) + x * y * Self.FDepth div 8);
858    for i := 0 to Length(fadelvldata) - 1 do
859      Target[Length(Target) - x * y * Self.FDepth div 8 + i] := fadelvldata[i];
860  until (x = 1) or (y = 1) or ((x mod 2) = 1) or ((y mod 2) = 1);
861  if (x > 1) and (y > 1) then
862    Exit;
598    Result := True;
864
865  if revert then
866    Self.RevertImage;
867 end;
868
869
870 function TOniImage.GetMipMappedImage(var Target: TStream): Boolean;
871 var
872  data: TByteData;
873  streampos: Integer;
874 begin
875  Result := GetMipMappedImage(data);
876  if not Assigned(Target) then
877    Target := TMemoryStream.Create;
878  streampos := Target.Position;
879  Target.Write(data[0], Length(data));
880  Target.Seek(streampos, soFromBeginning);
599   end;
600  
883
601   end.

Diff Legend

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