| 1 | unit OniImgClass;
 | 
|---|
| 2 | 
 | 
|---|
| 3 | interface
 | 
|---|
| 4 | 
 | 
|---|
| 5 | uses Math, Dialogs, Types, SysUtils, Classes, Data, ConnectionManager, TypeDefs;
 | 
|---|
| 6 | 
 | 
|---|
| 7 | type
 | 
|---|
| 8 |   TImgDataType = set of (DT_OniReverted, DT_Oni, DT_Decoded32);
 | 
|---|
| 9 | 
 | 
|---|
| 10 | type
 | 
|---|
| 11 |   TOniImage = class
 | 
|---|
| 12 |   private
 | 
|---|
| 13 |     FLoaded:    Boolean;
 | 
|---|
| 14 |     FDataType:  TImgDataType;
 | 
|---|
| 15 |     FData:      TByteData;
 | 
|---|
| 16 |     FWidth, FHeight: Word;
 | 
|---|
| 17 |     FDepth:     Byte;
 | 
|---|
| 18 |     FStoreType: Byte;
 | 
|---|
| 19 | 
 | 
|---|
| 20 |     function ResizeImage(oldx, oldy: Integer; img: TByteData): TByteData;
 | 
|---|
| 21 |     procedure RevertImage;
 | 
|---|
| 22 |     procedure DecodeImage;
 | 
|---|
| 23 |     procedure DecompressImage;
 | 
|---|
| 24 |   protected
 | 
|---|
| 25 |   public
 | 
|---|
| 26 |     property Loaded:    Boolean      Read FLoaded    Write FLoaded;
 | 
|---|
| 27 |     property DataType:  TImgDataType Read FDataType  Write FDataType;
 | 
|---|
| 28 |     property Width:     Word         Read FWidth     Write FWidth;
 | 
|---|
| 29 |     property Height:    Word         Read FHeight    Write FHeight;
 | 
|---|
| 30 |     property Depth:     Byte         Read FDepth     Write FDepth;
 | 
|---|
| 31 |     property StoreType: Byte         Read FStoreType Write FStoreType;
 | 
|---|
| 32 |     property Data:      TByteData    Read FData      Write FData;
 | 
|---|
| 33 | 
 | 
|---|
| 34 |     constructor Create;
 | 
|---|
| 35 |     function Load(ConnectionID, FileID: Integer): Boolean;
 | 
|---|
| 36 |     function LoadFromPSpc(ConnectionID, FileID: Integer): Boolean;
 | 
|---|
| 37 |     function LoadFromTXMP(ConnectionID, FileID: Integer): Boolean;
 | 
|---|
| 38 |     function LoadFromTXMB(ConnectionID, FileID: Integer): Boolean;
 | 
|---|
| 39 |     function GetImageDataSize(fading: Boolean): Integer;
 | 
|---|
| 40 | 
 | 
|---|
| 41 |     procedure GetAsData(var Target: TStream); overload;
 | 
|---|
| 42 |     procedure GetAsData(var Target: TByteData); overload;
 | 
|---|
| 43 |     procedure GetAs32bit(var Target: TStream); overload;
 | 
|---|
| 44 |     procedure GetAs32bit(var Target: TByteData); overload;
 | 
|---|
| 45 |     procedure GetAsBMP(var Target: TStream); overload;
 | 
|---|
| 46 |     procedure GetAsBMP(var Target: TByteData); overload;
 | 
|---|
| 47 |     function LoadFromBMP(filename: String): Boolean;
 | 
|---|
| 48 |     function WriteToBMP(filename: String): Boolean;
 | 
|---|
| 49 |     function GetMipMappedImage(var Target: TStream): Boolean; overload;
 | 
|---|
| 50 |     function GetMipMappedImage(var Target: TByteData): Boolean; overload;
 | 
|---|
| 51 |   published
 | 
|---|
| 52 |   end;
 | 
|---|
| 53 | 
 | 
|---|
| 54 | 
 | 
|---|
| 55 | implementation
 | 
|---|
| 56 | 
 | 
|---|
| 57 | //uses Functions;
 | 
|---|
| 58 | 
 | 
|---|
| 59 | 
 | 
|---|
| 60 | 
 | 
|---|
| 61 | 
 | 
|---|
| 62 | constructor TOniImage.Create;
 | 
|---|
| 63 | begin
 | 
|---|
| 64 |   Self.FLoaded   := False;
 | 
|---|
| 65 |   Self.FDataType := [];
 | 
|---|
| 66 |   SetLength(Self.FData, 0);
 | 
|---|
| 67 |   Self.FWidth     := 0;
 | 
|---|
| 68 |   Self.FHeight    := 0;
 | 
|---|
| 69 |   Self.FDepth     := 0;
 | 
|---|
| 70 |   Self.FStoreType := 0;
 | 
|---|
| 71 | end;
 | 
|---|
| 72 | 
 | 
|---|
| 73 | 
 | 
|---|
| 74 | 
 | 
|---|
| 75 | 
 | 
|---|
| 76 | function TOniImage.ResizeImage(oldx, oldy: Integer; img: TByteData): TByteData;
 | 
|---|
| 77 | var
 | 
|---|
| 78 |   i, j: Integer;
 | 
|---|
| 79 |   col, row, row_orig: Integer;
 | 
|---|
| 80 | begin
 | 
|---|
| 81 |   SetLength(Result, (oldx div 2) * (oldy div 2) * (Self.FDepth div 8));
 | 
|---|
| 82 |   row_orig := 0;
 | 
|---|
| 83 |   row      := 0;
 | 
|---|
| 84 |   col      := 0;
 | 
|---|
| 85 |   for i := 0 to (oldx * oldy) - 1 do
 | 
|---|
| 86 |   begin
 | 
|---|
| 87 |     if ((i mod oldx) = 0) and (i > 0) then
 | 
|---|
| 88 |     begin
 | 
|---|
| 89 |       Inc(row_orig);
 | 
|---|
| 90 |       if (row_orig mod 2) = 0 then
 | 
|---|
| 91 |       begin
 | 
|---|
| 92 |         Inc(row);
 | 
|---|
| 93 |         col := 0;
 | 
|---|
| 94 |       end;
 | 
|---|
| 95 |     end;
 | 
|---|
| 96 |     if (row_orig mod 2) = 0 then
 | 
|---|
| 97 |     begin
 | 
|---|
| 98 |       if (i mod 2) = 0 then
 | 
|---|
| 99 |       begin
 | 
|---|
| 100 |         for j := 0 to (Self.FDepth div 8) - 1 do
 | 
|---|
| 101 |           Result[((row * (oldx div 2)) + col) * (Self.FDepth div 8) + j] :=
 | 
|---|
| 102 |             img[(i * (Self.FDepth div 8)) + j];
 | 
|---|
| 103 |         Inc(col);
 | 
|---|
| 104 |       end;
 | 
|---|
| 105 |     end;
 | 
|---|
| 106 |   end;
 | 
|---|
| 107 | end;
 | 
|---|
| 108 | 
 | 
|---|
| 109 | 
 | 
|---|
| 110 | 
 | 
|---|
| 111 | 
 | 
|---|
| 112 | procedure TOniImage.RevertImage;
 | 
|---|
| 113 | var
 | 
|---|
| 114 |   x, y, i: Integer;
 | 
|---|
| 115 |   tempd:   TByteData;
 | 
|---|
| 116 | begin
 | 
|---|
| 117 |   SetLength(tempd, Self.FWidth * Self.FHeight * (Self.FDepth div 8));
 | 
|---|
| 118 |   for y := 0 to Self.FHeight - 1 do
 | 
|---|
| 119 |     for x := 0 to Self.FWidth - 1 do
 | 
|---|
| 120 |       for i := 0 to (Self.FDepth div 8) - 1 do
 | 
|---|
| 121 |         tempd[((Self.FWidth * (Self.FHeight - 1 - y) + x) * (Self.FDepth div 8)) + i] :=
 | 
|---|
| 122 |           Self.FData[(Self.FWidth * y + x) * (Self.FDepth div 8) + i];
 | 
|---|
| 123 |   for x := 0 to High(tempd) do
 | 
|---|
| 124 |     Self.FData[x] := tempd[x];
 | 
|---|
| 125 |   if DT_OniReverted in Self.FDataType then
 | 
|---|
| 126 |     Self.FDataType := Self.FDataType - [DT_OniReverted]
 | 
|---|
| 127 |   else
 | 
|---|
| 128 |     Self.FDataType := Self.FDataType + [DT_OniReverted];
 | 
|---|
| 129 | end;
 | 
|---|
| 130 | 
 | 
|---|
| 131 | 
 | 
|---|
| 132 | 
 | 
|---|
| 133 | 
 | 
|---|
| 134 | procedure TOniImage.DecodeImage;
 | 
|---|
| 135 | var
 | 
|---|
| 136 |   x, y:  Integer;
 | 
|---|
| 137 |   tempd: TByteData;
 | 
|---|
| 138 | begin
 | 
|---|
| 139 |   if not (DT_Decoded32 in Self.FDataType) then
 | 
|---|
| 140 |   begin
 | 
|---|
| 141 |     SetLength(tempd, Self.FWidth * Self.FHeight * 4);
 | 
|---|
| 142 |     case Self.FStoreType of
 | 
|---|
| 143 |       0: // 16bit, RGB444, A4?
 | 
|---|
| 144 |       begin
 | 
|---|
| 145 |         for y := 0 to Self.FHeight - 1 do
 | 
|---|
| 146 |         begin
 | 
|---|
| 147 |           for x := 0 to Self.FWidth - 1 do
 | 
|---|
| 148 |           begin
 | 
|---|
| 149 |             tempd[((Self.FWidth * y + x) * 4) + 0] :=
 | 
|---|
| 150 |               Round(((Self.FData[(Self.FWidth * y + x) * 2] + Self.FData[(Self.FWidth * y + x) * 2 + 1] * 256) and
 | 
|---|
| 151 |               $000F) / $000F * 255);
 | 
|---|
| 152 |             tempd[((Self.FWidth * y + x) * 4) + 1] :=
 | 
|---|
| 153 |               Round(((Self.FData[(Self.FWidth * y + x) * 2] + Self.FData[(Self.FWidth * y + x) * 2 + 1] * 256) and
 | 
|---|
| 154 |               $00F0) / $00F0 * 255);
 | 
|---|
| 155 |             tempd[((Self.FWidth * y + x) * 4) + 2] :=
 | 
|---|
| 156 |               Round(((Self.FData[(Self.FWidth * y + x) * 2] + Self.FData[(Self.FWidth * y + x) * 2 + 1] * 256) and
 | 
|---|
| 157 |               $0F00) / $0F00 * 255);
 | 
|---|
| 158 |             tempd[((Self.FWidth * y + x) * 4) + 3] := 0;
 | 
|---|
| 159 |           end;
 | 
|---|
| 160 |         end;
 | 
|---|
| 161 |       end;
 | 
|---|
| 162 |       1, 2: // 16bit, RGB555, A1?
 | 
|---|
| 163 |       begin
 | 
|---|
| 164 |         for y := 0 to Self.FHeight - 1 do
 | 
|---|
| 165 |         begin
 | 
|---|
| 166 |           for x := 0 to Self.FWidth - 1 do
 | 
|---|
| 167 |           begin
 | 
|---|
| 168 |             tempd[((Self.FWidth * y + x) * 4) + 0] :=
 | 
|---|
| 169 |               Round(((Self.FData[(Self.FWidth * y + x) * 2] + Self.FData[(Self.FWidth * y + x) * 2 + 1] * 256) and
 | 
|---|
| 170 |               $001F) / $001F * 255);
 | 
|---|
| 171 |             tempd[((Self.FWidth * y + x) * 4) + 1] :=
 | 
|---|
| 172 |               Round(((Self.FData[(Self.FWidth * y + x) * 2] + Self.FData[(Self.FWidth * y + x) * 2 + 1] * 256) and
 | 
|---|
| 173 |               $03E0) / $03E0 * 255);
 | 
|---|
| 174 |             tempd[((Self.FWidth * y + x) * 4) + 2] :=
 | 
|---|
| 175 |               Round(((Self.FData[(Self.FWidth * y + x) * 2] + Self.FData[(Self.FWidth * y + x) * 2 + 1] * 256) and
 | 
|---|
| 176 |               $7C00) / $7C00 * 255);
 | 
|---|
| 177 |             tempd[((Self.FWidth * y + x) * 4) + 3] := 0;
 | 
|---|
| 178 |           end;
 | 
|---|
| 179 |         end;
 | 
|---|
| 180 |       end;
 | 
|---|
| 181 |       8: // 32bit, RGB888, A8?
 | 
|---|
| 182 |       begin end;
 | 
|---|
| 183 |       9: // Compressed, RGB565
 | 
|---|
| 184 |       begin
 | 
|---|
| 185 |         DecompressImage;
 | 
|---|
| 186 |       end;
 | 
|---|
| 187 |     end;
 | 
|---|
| 188 |     Self.FDepth := 32;
 | 
|---|
| 189 |     if (Self.FStoreType <> 9) and (Self.FStoreType <> 8) then
 | 
|---|
| 190 |     begin
 | 
|---|
| 191 |       SetLength(Self.FData, Length(tempd));
 | 
|---|
| 192 |       for x := 0 to High(tempd) do
 | 
|---|
| 193 |         Self.FData[x] := tempd[x];
 | 
|---|
| 194 |     end;
 | 
|---|
| 195 |     Self.FStoreType := 8;
 | 
|---|
| 196 |     if DT_Oni in Self.FDataType then
 | 
|---|
| 197 |       Self.FDataType := Self.FDataType - [DT_Oni];
 | 
|---|
| 198 |     Self.FDataType := Self.FDataType + [DT_Decoded32];
 | 
|---|
| 199 |   end;
 | 
|---|
| 200 |   if DT_OniReverted in Self.FDataType then
 | 
|---|
| 201 |     Self.RevertImage;
 | 
|---|
| 202 | end;
 | 
|---|
| 203 | 
 | 
|---|
| 204 | 
 | 
|---|
| 205 | 
 | 
|---|
| 206 | 
 | 
|---|
| 207 | procedure TOniImage.DecompressImage;
 | 
|---|
| 208 | type
 | 
|---|
| 209 |   Tcolor = record
 | 
|---|
| 210 |     RGBb: Byte;
 | 
|---|
| 211 |     RGBg: Byte;
 | 
|---|
| 212 |     RGBr: Byte;
 | 
|---|
| 213 |     RGBa: Byte;
 | 
|---|
| 214 |   end;
 | 
|---|
| 215 | var
 | 
|---|
| 216 |   i, j, x, y: Integer;
 | 
|---|
| 217 |   color:      array[1..4] of Tcolor;
 | 
|---|
| 218 |   pixel:      array[1..16] of Byte;
 | 
|---|
| 219 |   tempd:      TByteData;
 | 
|---|
| 220 | begin
 | 
|---|
| 221 |   x := 0;
 | 
|---|
| 222 |   y := 0;
 | 
|---|
| 223 |   SetLength(tempd, Self.FWidth * Self.FHeight * 4);
 | 
|---|
| 224 |   for i := 0 to ((Self.FWidth * Self.FHeight) div 16) - 1 do
 | 
|---|
| 225 |   begin
 | 
|---|
| 226 |     Color[1].RGBb := Round(((Self.FData[(i * 8) + 0] + Self.FData[(i * 8) + 1] * 256) and $001F) /
 | 
|---|
| 227 |       $001F * 255);
 | 
|---|
| 228 |     Color[1].RGBg := Round(((Self.FData[(i * 8) + 0] + Self.FData[(i * 8) + 1] * 256) and $07E0) /
 | 
|---|
| 229 |       $07E0 * 255);
 | 
|---|
| 230 |     Color[1].RGBr := Round(((Self.FData[(i * 8) + 0] + Self.FData[(i * 8) + 1] * 256) and $F800) /
 | 
|---|
| 231 |       $F800 * 255);
 | 
|---|
| 232 |     Color[1].RGBa := 255;
 | 
|---|
| 233 |     Color[2].RGBb := Round(((Self.FData[(i * 8) + 2] + Self.FData[(i * 8) + 3] * 256) and $001F) /
 | 
|---|
| 234 |       $001F * 255);
 | 
|---|
| 235 |     Color[2].RGBg := Round(((Self.FData[(i * 8) + 2] + Self.FData[(i * 8) + 3] * 256) and $07E0) /
 | 
|---|
| 236 |       $07E0 * 255);
 | 
|---|
| 237 |     Color[2].RGBr := Round(((Self.FData[(i * 8) + 2] + Self.FData[(i * 8) + 3] * 256) and $F800) /
 | 
|---|
| 238 |       $F800 * 255);
 | 
|---|
| 239 |     Color[2].RGBa := 255;
 | 
|---|
| 240 |     Color[3].RGBb := Round(Color[1].RGBb / 3 * 2 + Color[2].RGBb / 3);
 | 
|---|
| 241 |     Color[3].RGBg := Round(Color[1].RGBg / 3 * 2 + Color[2].RGBg / 3);
 | 
|---|
| 242 |     Color[3].RGBr := Round(Color[1].RGBr / 3 * 2 + Color[2].RGBr / 3);
 | 
|---|
| 243 |     Color[3].RGBa := 255;
 | 
|---|
| 244 |     Color[4].RGBb := Round(Color[1].RGBb / 3 + Color[2].RGBb / 3 * 2);
 | 
|---|
| 245 |     Color[4].RGBg := Round(Color[1].RGBg / 3 + Color[2].RGBg / 3 * 2);
 | 
|---|
| 246 |     Color[4].RGBr := Round(Color[1].RGBr / 3 + Color[2].RGBr / 3 * 2);
 | 
|---|
| 247 |     Color[4].RGBa := 255;
 | 
|---|
| 248 |     Pixel[1]      := Round((Self.FData[(i * 8) + 4] and $C0) / $40 + 1);
 | 
|---|
| 249 |     Pixel[2]      := Round((Self.FData[(i * 8) + 4] and $30) / $10 + 1);
 | 
|---|
| 250 |     Pixel[3]      := Round((Self.FData[(i * 8) + 4] and $0C) / $04 + 1);
 | 
|---|
| 251 |     Pixel[4]      := Round((Self.FData[(i * 8) + 4] and $03) + 1);
 | 
|---|
| 252 |     Pixel[5]      := Round((Self.FData[(i * 8) + 5] and $C0) / $40 + 1);
 | 
|---|
| 253 |     Pixel[6]      := Round((Self.FData[(i * 8) + 5] and $30) / $10 + 1);
 | 
|---|
| 254 |     Pixel[7]      := Round((Self.FData[(i * 8) + 5] and $0C) / $04 + 1);
 | 
|---|
| 255 |     Pixel[8]      := Round((Self.FData[(i * 8) + 5] and $03) + 1);
 | 
|---|
| 256 |     Pixel[9]      := Round((Self.FData[(i * 8) + 6] and $C0) / $40 + 1);
 | 
|---|
| 257 |     Pixel[10]     := Round((Self.FData[(i * 8) + 6] and $30) / $10 + 1);
 | 
|---|
| 258 |     Pixel[11]     := Round((Self.FData[(i * 8) + 6] and $0C) / $04 + 1);
 | 
|---|
| 259 |     Pixel[12]     := Round((Self.FData[(i * 8) + 6] and $03) + 1);
 | 
|---|
| 260 |     Pixel[13]     := Round((Self.FData[(i * 8) + 7] and $C0) / $40 + 1);
 | 
|---|
| 261 |     Pixel[14]     := Round((Self.FData[(i * 8) + 7] and $30) / $10 + 1);
 | 
|---|
| 262 |     Pixel[15]     := Round((Self.FData[(i * 8) + 7] and $0C) / $04 + 1);
 | 
|---|
| 263 |     Pixel[16]     := Round((Self.FData[(i * 8) + 7] and $03) + 1);
 | 
|---|
| 264 |     for j := 0 to 3 do
 | 
|---|
| 265 |     begin
 | 
|---|
| 266 |       tempd[((y + 3) * Self.FWidth + x + j) * 4 + 0] := Color[Pixel[16 - j]].RGBb;
 | 
|---|
| 267 |       tempd[((y + 3) * Self.FWidth + x + j) * 4 + 1] := Color[Pixel[16 - j]].RGBg;
 | 
|---|
| 268 |       tempd[((y + 3) * Self.FWidth + x + j) * 4 + 2] := Color[Pixel[16 - j]].RGBr;
 | 
|---|
| 269 |       tempd[((y + 3) * Self.FWidth + x + j) * 4 + 3] := 0;
 | 
|---|
| 270 |     end;
 | 
|---|
| 271 |     for j := 0 to 3 do
 | 
|---|
| 272 |     begin
 | 
|---|
| 273 |       tempd[((y + 2) * Self.FWidth + x + j) * 4 + 0] := Color[Pixel[12 - j]].RGBb;
 | 
|---|
| 274 |       tempd[((y + 2) * Self.FWidth + x + j) * 4 + 1] := Color[Pixel[12 - j]].RGBg;
 | 
|---|
| 275 |       tempd[((y + 2) * Self.FWidth + x + j) * 4 + 2] := Color[Pixel[12 - j]].RGBr;
 | 
|---|
| 276 |       tempd[((y + 2) * Self.FWidth + x + j) * 4 + 3] := 0;
 | 
|---|
| 277 |     end;
 | 
|---|
| 278 |     for j := 0 to 3 do
 | 
|---|
| 279 |     begin
 | 
|---|
| 280 |       tempd[((y + 1) * Self.FWidth + x + j) * 4 + 0] := Color[Pixel[8 - j]].RGBb;
 | 
|---|
| 281 |       tempd[((y + 1) * Self.FWidth + x + j) * 4 + 1] := Color[Pixel[8 - j]].RGBg;
 | 
|---|
| 282 |       tempd[((y + 1) * Self.FWidth + x + j) * 4 + 2] := Color[Pixel[8 - j]].RGBr;
 | 
|---|
| 283 |       tempd[((y + 1) * Self.FWidth + x + j) * 4 + 3] := 0;
 | 
|---|
| 284 |     end;
 | 
|---|
| 285 |     for j := 0 to 3 do
 | 
|---|
| 286 |     begin
 | 
|---|
| 287 |       tempd[((y + 0) * Self.FWidth + x + j) * 4 + 0] := Color[Pixel[4 - j]].RGBb;
 | 
|---|
| 288 |       tempd[((y + 0) * Self.FWidth + x + j) * 4 + 1] := Color[Pixel[4 - j]].RGBg;
 | 
|---|
| 289 |       tempd[((y + 0) * Self.FWidth + x + j) * 4 + 2] := Color[Pixel[4 - j]].RGBr;
 | 
|---|
| 290 |       tempd[((y + 0) * Self.FWidth + x + j) * 4 + 3] := 0;
 | 
|---|
| 291 |     end;
 | 
|---|
| 292 |     x := x + 4;
 | 
|---|
| 293 |     if x = Self.FWidth then
 | 
|---|
| 294 |     begin
 | 
|---|
| 295 |       y := y + 4;
 | 
|---|
| 296 |       x := 0;
 | 
|---|
| 297 |     end;
 | 
|---|
| 298 |   end;
 | 
|---|
| 299 |   SetLength(Self.FData, Length(tempd));
 | 
|---|
| 300 |   for i := 0 to High(tempd) do
 | 
|---|
| 301 |     Self.FData[i] := tempd[i];
 | 
|---|
| 302 |   Self.FStoreType := 8;
 | 
|---|
| 303 |   Self.FDepth    := 32;
 | 
|---|
| 304 |   Self.FDataType := Self.FDataType - [DT_Oni] + [DT_Decoded32];
 | 
|---|
| 305 | end;
 | 
|---|
| 306 | 
 | 
|---|
| 307 | 
 | 
|---|
| 308 | 
 | 
|---|
| 309 | 
 | 
|---|
| 310 | 
 | 
|---|
| 311 | function TOniImage.Load(ConnectionID, FileID: Integer): Boolean;
 | 
|---|
| 312 | var
 | 
|---|
| 313 |   FileInfo: TFileInfo;
 | 
|---|
| 314 | begin
 | 
|---|
| 315 |   FileInfo := ConManager.Connection[ConnectionID].GetFileInfo(fileid);
 | 
|---|
| 316 |   if FileInfo.Extension = 'PSpc' then
 | 
|---|
| 317 |     Result := LoadFromPSpc(ConnectionID, fileid)
 | 
|---|
| 318 |   else if FileInfo.Extension = 'TXMB' then
 | 
|---|
| 319 |     Result := LoadFromTXMB(ConnectionID, fileid)
 | 
|---|
| 320 |   else if FileInfo.Extension = 'TXMP' then
 | 
|---|
| 321 |     Result := LoadFromTXMP(ConnectionID, fileid)
 | 
|---|
| 322 |   else
 | 
|---|
| 323 |     Result := False;
 | 
|---|
| 324 | end;
 | 
|---|
| 325 | 
 | 
|---|
| 326 | 
 | 
|---|
| 327 | 
 | 
|---|
| 328 | 
 | 
|---|
| 329 | function TOniImage.LoadFromPSpc(ConnectionID, FileID: Integer): Boolean;
 | 
|---|
| 330 | type
 | 
|---|
| 331 |   TPoint = packed record
 | 
|---|
| 332 |     X, Y: Word;
 | 
|---|
| 333 |   end;
 | 
|---|
| 334 | 
 | 
|---|
| 335 |   TPSpc = packed record
 | 
|---|
| 336 |     p1:   array[0..8] of TPoint;
 | 
|---|
| 337 |     p2:   array[0..8] of TPoint;
 | 
|---|
| 338 |     TXMP: Integer;
 | 
|---|
| 339 |   end;
 | 
|---|
| 340 | 
 | 
|---|
| 341 |   TPart = packed record
 | 
|---|
| 342 |     x_txmp, y_txmp: Word;
 | 
|---|
| 343 |     x_pspc, y_pspc: Word;
 | 
|---|
| 344 |     w, h:    Word;
 | 
|---|
| 345 |     imgdata: TByteData;
 | 
|---|
| 346 |     used:    Boolean;
 | 
|---|
| 347 |   end;
 | 
|---|
| 348 | const
 | 
|---|
| 349 |   PartMatch: array[0..8] of Byte = (0, 3, 6, 1, 4, 7, 2, 5, 8);
 | 
|---|
| 350 | var
 | 
|---|
| 351 |   x, y, pixel: Word;
 | 
|---|
| 352 |   i: Integer;
 | 
|---|
| 353 | 
 | 
|---|
| 354 |   PSpc:     TPSpc;
 | 
|---|
| 355 |   txmpimg:  TOniImage;
 | 
|---|
| 356 |   txmpdata: TByteData;
 | 
|---|
| 357 | 
 | 
|---|
| 358 |   parts:    array[0..8] of TPart;
 | 
|---|
| 359 |   part:     Byte;
 | 
|---|
| 360 |   cols:     array[0..2] of Word;
 | 
|---|
| 361 |   rows:     array[0..2] of Word;
 | 
|---|
| 362 |   col, row: Byte;
 | 
|---|
| 363 | begin
 | 
|---|
| 364 |   ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $08, SizeOf(PSpc), @PSpc);
 | 
|---|
| 365 |   PSpc.TXMP := PSpc.TXMP div 256;
 | 
|---|
| 366 |   if PSpc.TXMP = 0 then
 | 
|---|
| 367 |   begin
 | 
|---|
| 368 |     Result := False;
 | 
|---|
| 369 |     Exit;
 | 
|---|
| 370 |   end;
 | 
|---|
| 371 |   txmpimg := TOniImage.Create;
 | 
|---|
| 372 |   txmpimg.LoadFromTXMP(ConnectionID, PSpc.TXMP);
 | 
|---|
| 373 |   txmpimg.DecodeImage;
 | 
|---|
| 374 | //  txmpimg.WriteToBMP('C:\file.bmp');
 | 
|---|
| 375 |   txmpimg.GetAs32bit(txmpdata);
 | 
|---|
| 376 | {    ShowMessage(IntToStr(txmpimg.Width)+'x'+IntToStr(txmpimg.Height));
 | 
|---|
| 377 |     for i:=0 to High(txmpdata) do
 | 
|---|
| 378 |       txmpimg.Data[i]:=txmpdata[i];
 | 
|---|
| 379 |     txmpimg.WriteToBMP('D:\file2.bmp');
 | 
|---|
| 380 | }
 | 
|---|
| 381 |   with PSpc do
 | 
|---|
| 382 |   begin
 | 
|---|
| 383 |     for i := 0 to 2 do
 | 
|---|
| 384 |     begin
 | 
|---|
| 385 |       cols[i] := 0;
 | 
|---|
| 386 |       rows[i] := 0;
 | 
|---|
| 387 |     end;
 | 
|---|
| 388 |     for i := 0 to 8 do
 | 
|---|
| 389 |     begin
 | 
|---|
| 390 |       part := PartMatch[i];
 | 
|---|
| 391 |       col  := i div 3;
 | 
|---|
| 392 |       row  := i mod 3;
 | 
|---|
| 393 |       if (p2[i].X > 0) or (p2[i].Y > 0) then
 | 
|---|
| 394 |       begin
 | 
|---|
| 395 |         parts[part].x_txmp := p1[i].X - 1;
 | 
|---|
| 396 |         parts[part].y_txmp := p1[i].Y - 1;
 | 
|---|
| 397 |         parts[part].x_pspc := 0;
 | 
|---|
| 398 |         if col > 0 then
 | 
|---|
| 399 |           for x := 0 to col - 1 do
 | 
|---|
| 400 |             Inc(parts[part].x_pspc, cols[x]);
 | 
|---|
| 401 |         parts[part].y_pspc := 0;
 | 
|---|
| 402 |         if row > 0 then
 | 
|---|
| 403 |           for y := 0 to row - 1 do
 | 
|---|
| 404 |             Inc(parts[part].y_pspc, rows[y]);
 | 
|---|
| 405 |         parts[part].w := p2[i].X - p1[i].X + 1;
 | 
|---|
| 406 |         parts[part].h := p2[i].Y - p1[i].Y + 1;
 | 
|---|
| 407 |         parts[part].used := True;
 | 
|---|
| 408 |         cols[col] := parts[part].w;
 | 
|---|
| 409 |         rows[row] := parts[part].h;
 | 
|---|
| 410 |         SetLength(parts[part].imgdata, parts[part].w * parts[part].h * 4);
 | 
|---|
| 411 |         for y := 0 to parts[part].h - 1 do
 | 
|---|
| 412 |         begin
 | 
|---|
| 413 |           for x := 0 to parts[part].w - 1 do
 | 
|---|
| 414 |           begin
 | 
|---|
| 415 |             for pixel := 0 to 3 do
 | 
|---|
| 416 |             begin
 | 
|---|
| 417 |               parts[part].imgdata[(y * parts[part].w + x) * 4 + pixel] :=
 | 
|---|
| 418 |                 txmpdata[((parts[part].y_txmp + y) * txmpimg.Width +
 | 
|---|
| 419 |                 parts[part].x_txmp + x) * 4 + pixel];
 | 
|---|
| 420 |             end;
 | 
|---|
| 421 |           end;
 | 
|---|
| 422 |         end;
 | 
|---|
| 423 |       end
 | 
|---|
| 424 |       else
 | 
|---|
| 425 |       begin
 | 
|---|
| 426 |         parts[part].used := False;
 | 
|---|
| 427 |       end;
 | 
|---|
| 428 |     end;
 | 
|---|
| 429 | 
 | 
|---|
| 430 |   end;
 | 
|---|
| 431 | 
 | 
|---|
| 432 |   txmpimg.Free;
 | 
|---|
| 433 |   txmpimg := TOniImage.Create;
 | 
|---|
| 434 |   for i := 0 to 8 do
 | 
|---|
| 435 |   begin
 | 
|---|
| 436 |     if parts[i].used then
 | 
|---|
| 437 |     begin
 | 
|---|
| 438 |       SetLength(txmpimg.FData, Length(parts[i].imgdata));
 | 
|---|
| 439 |       for pixel := 0 to High(parts[i].imgdata) do
 | 
|---|
| 440 |         txmpimg.Data[pixel] := parts[i].imgdata[pixel];
 | 
|---|
| 441 |       txmpimg.Width := parts[i].w;
 | 
|---|
| 442 |       txmpimg.Height    := parts[i].h;
 | 
|---|
| 443 |       txmpimg.StoreType := 8;
 | 
|---|
| 444 |       txmpimg.DataType  := [DT_Decoded32];
 | 
|---|
| 445 |       txmpimg.Depth     := 32;
 | 
|---|
| 446 |       txmpimg.WriteToBMP('M:\' + IntToStr(i) + '.bmp');
 | 
|---|
| 447 |     end;
 | 
|---|
| 448 |   end;
 | 
|---|
| 449 |   txmpimg.Free;
 | 
|---|
| 450 | 
 | 
|---|
| 451 |   Self.FWidth  := 0;
 | 
|---|
| 452 |   Self.FHeight := 0;
 | 
|---|
| 453 |   for i := 0 to 2 do
 | 
|---|
| 454 |   begin
 | 
|---|
| 455 |     Inc(Self.FWidth, cols[i]);
 | 
|---|
| 456 |     Inc(Self.FHeight, rows[i]);
 | 
|---|
| 457 |   end;
 | 
|---|
| 458 |   SetLength(Self.FData, Self.FWidth * Self.FHeight * 4);
 | 
|---|
| 459 | 
 | 
|---|
| 460 |   //Combine data parts
 | 
|---|
| 461 | 
 | 
|---|
| 462 |   Self.FDepth     := 32;
 | 
|---|
| 463 |   Self.FStoreType := 8;
 | 
|---|
| 464 |   Self.FDataType  := [DT_Decoded32];
 | 
|---|
| 465 |   //    Self.RevertImage;
 | 
|---|
| 466 | end;
 | 
|---|
| 467 | 
 | 
|---|
| 468 | 
 | 
|---|
| 469 | 
 | 
|---|
| 470 | 
 | 
|---|
| 471 | function TOniImage.LoadFromTXMP(ConnectionID, FileID: Integer): Boolean;
 | 
|---|
| 472 | var
 | 
|---|
| 473 |   img_addr: Integer;
 | 
|---|
| 474 | begin
 | 
|---|
| 475 |   Result := True;
 | 
|---|
| 476 |   ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $8C, SizeOf(Self.FWidth), @Self.FWidth);
 | 
|---|
| 477 |   ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $8E, SizeOf(Self.FHeight), @Self.FHeight);
 | 
|---|
| 478 |   ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $90, SizeOf(Self.FStoreType),
 | 
|---|
| 479 |     @Self.FStoreType);
 | 
|---|
| 480 |   if ConManager.Connection[ConnectionID].DataOS = DOS_WIN then
 | 
|---|
| 481 |     ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $9C, SizeOf(img_addr), @img_addr)
 | 
|---|
| 482 |   else
 | 
|---|
| 483 |     ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $A0, SizeOf(img_addr), @img_addr);
 | 
|---|
| 484 | 
 | 
|---|
| 485 |   case Self.FStoreType of
 | 
|---|
| 486 |     0, 1, 2:
 | 
|---|
| 487 |     begin
 | 
|---|
| 488 |       SetLength(Self.FData, Self.FWidth * Self.FHeight * 2);
 | 
|---|
| 489 |       Self.FDepth := 16;
 | 
|---|
| 490 |     end;
 | 
|---|
| 491 |     8:
 | 
|---|
| 492 |     begin
 | 
|---|
| 493 |       SetLength(Self.FData, Self.FWidth * Self.FHeight * 4);
 | 
|---|
| 494 |       Self.FDepth := 32;
 | 
|---|
| 495 |     end;
 | 
|---|
| 496 |     9:
 | 
|---|
| 497 |     begin
 | 
|---|
| 498 |       SetLength(Self.FData, Self.FWidth * Self.FHeight div 2);
 | 
|---|
| 499 |       Self.FDepth := 16;
 | 
|---|
| 500 |     end;
 | 
|---|
| 501 |     else
 | 
|---|
| 502 |       Result := False;
 | 
|---|
| 503 |       Exit;
 | 
|---|
| 504 |   end;
 | 
|---|
| 505 | 
 | 
|---|
| 506 |   if ConManager.Connection[ConnectionID].DataOS = DOS_WIN then
 | 
|---|
| 507 |     ConManager.Connection[ConnectionID].LoadRawFile(fileid, $9C, FData)
 | 
|---|
| 508 |   else
 | 
|---|
| 509 |     ConManager.Connection[ConnectionID].LoadRawFile(fileid, $A0, FData);
 | 
|---|
| 510 | 
 | 
|---|
| 511 |   Self.FDataType := [DT_OniReverted, DT_Oni];
 | 
|---|
| 512 | end;
 | 
|---|
| 513 | 
 | 
|---|
| 514 | 
 | 
|---|
| 515 | 
 | 
|---|
| 516 | 
 | 
|---|
| 517 | function TOniImage.LoadFromTXMB(ConnectionID, FileID: Integer): Boolean;
 | 
|---|
| 518 | var
 | 
|---|
| 519 |   i, x, y, x2, y2, pixelid, imgid: Integer;
 | 
|---|
| 520 |   rows, cols: Word;
 | 
|---|
| 521 |   linkcount: Integer;
 | 
|---|
| 522 |   link: Integer;
 | 
|---|
| 523 |   images_decoded: array of TOniImage;
 | 
|---|
| 524 |   x_start, y_start: Integer;
 | 
|---|
| 525 | begin
 | 
|---|
| 526 |   ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $10, SizeOf(Self.FWidth), @Self.FWidth);
 | 
|---|
| 527 |   ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $12, SizeOf(Self.FHeight), @Self.FHeight);
 | 
|---|
| 528 |   ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $18, SizeOf(cols), @cols);
 | 
|---|
| 529 |   ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $1A, SizeOf(rows), @rows);
 | 
|---|
| 530 |   ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $1C, SizeOf(linkcount), @linkcount);
 | 
|---|
| 531 |   SetLength(images_decoded, linkcount);
 | 
|---|
| 532 |   for i := 0 to linkcount - 1 do
 | 
|---|
| 533 |   begin
 | 
|---|
| 534 |     ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $20 + i * 4, SizeOf(link), @link);
 | 
|---|
| 535 |     link := link div 256;
 | 
|---|
| 536 |     images_decoded[i] := TOniImage.Create;
 | 
|---|
| 537 |     images_decoded[i].LoadFromTXMP(ConnectionID, link);
 | 
|---|
| 538 |     images_decoded[i].DecodeImage;
 | 
|---|
| 539 |     images_decoded[i].RevertImage;
 | 
|---|
| 540 |   end;
 | 
|---|
| 541 |   SetLength(Self.FData, Self.FWidth * Self.FHeight * 4);
 | 
|---|
| 542 |   for y := 0 to rows - 1 do
 | 
|---|
| 543 |   begin
 | 
|---|
| 544 |     for x := 0 to cols - 1 do
 | 
|---|
| 545 |     begin
 | 
|---|
| 546 |       imgid   := y * cols + x;
 | 
|---|
| 547 |       x_start := 0;
 | 
|---|
| 548 |       y_start := 0;
 | 
|---|
| 549 |       for i := 0 to x do
 | 
|---|
| 550 |         if i < x then
 | 
|---|
| 551 |           x_start := x_start + images_decoded[i].Width;
 | 
|---|
| 552 |       for i := 0 to y do
 | 
|---|
| 553 |         if i < y then
 | 
|---|
| 554 |           y_start := y_start + images_decoded[i].Height;
 | 
|---|
| 555 |       for y2 := 0 to images_decoded[imgid].Height - 1 do
 | 
|---|
| 556 |       begin
 | 
|---|
| 557 |         for x2 := 0 to images_decoded[imgid].Width - 1 do
 | 
|---|
| 558 |         begin
 | 
|---|
| 559 |           if ((x_start + x2) < Self.FWidth) and ((y_start + y2) < Self.FHeight) then
 | 
|---|
| 560 |           begin
 | 
|---|
| 561 |             pixelid := y_start * Self.FWidth + x_start + y2 * Self.FWidth + x2;
 | 
|---|
| 562 |             Self.FData[pixelid * 4 + 0] :=
 | 
|---|
| 563 |               images_decoded[imgid].Data[(y2 * images_decoded[imgid].Width + x2) * 4 + 0];
 | 
|---|
| 564 |             Self.FData[pixelid * 4 + 1] :=
 | 
|---|
| 565 |               images_decoded[imgid].Data[(y2 * images_decoded[imgid].Width + x2) * 4 + 1];
 | 
|---|
| 566 |             Self.FData[pixelid * 4 + 2] :=
 | 
|---|
| 567 |               images_decoded[imgid].Data[(y2 * images_decoded[imgid].Width + x2) * 4 + 2];
 | 
|---|
| 568 |             Self.FData[pixelid * 4 + 3] :=
 | 
|---|
| 569 |               images_decoded[imgid].Data[(y2 * images_decoded[imgid].Width + x2) * 4 + 3];
 | 
|---|
| 570 |           end;
 | 
|---|
| 571 |         end;
 | 
|---|
| 572 |       end;
 | 
|---|
| 573 |     end;
 | 
|---|
| 574 |   end;
 | 
|---|
| 575 |   for i := 0 to linkcount - 1 do
 | 
|---|
| 576 |     images_decoded[i].Free;
 | 
|---|
| 577 |   Self.FDepth     := 32;
 | 
|---|
| 578 |   Self.FStoreType := 8;
 | 
|---|
| 579 |   Self.FDataType  := [DT_Decoded32];
 | 
|---|
| 580 |   Self.RevertImage;
 | 
|---|
| 581 | end;
 | 
|---|
| 582 | 
 | 
|---|
| 583 | 
 | 
|---|
| 584 | 
 | 
|---|
| 585 | 
 | 
|---|
| 586 | function TOniImage.GetImageDataSize(fading: Boolean): Integer;
 | 
|---|
| 587 | var
 | 
|---|
| 588 |   size: Integer;
 | 
|---|
| 589 |   x, y: Word;
 | 
|---|
| 590 |   bpp:  Byte;
 | 
|---|
| 591 | begin
 | 
|---|
| 592 |   case Self.FStoreType of
 | 
|---|
| 593 |     9:
 | 
|---|
| 594 |       bpp := 8;
 | 
|---|
| 595 |     0, 1, 2:
 | 
|---|
| 596 |       bpp := 16;
 | 
|---|
| 597 |     8:
 | 
|---|
| 598 |       bpp := 32;
 | 
|---|
| 599 |     else
 | 
|---|
| 600 |       Result := 0;
 | 
|---|
| 601 |       Exit;
 | 
|---|
| 602 |   end;
 | 
|---|
| 603 | 
 | 
|---|
| 604 |   x    := Self.FWidth;
 | 
|---|
| 605 |   y    := Self.FHeight;
 | 
|---|
| 606 |   size := x * y * bpp div 8;
 | 
|---|
| 607 |   if fading then
 | 
|---|
| 608 |   begin
 | 
|---|
| 609 |     repeat
 | 
|---|
| 610 |       x    := x div 2;
 | 
|---|
| 611 |       y    := y div 2;
 | 
|---|
| 612 |       size := size + x * y * bpp div 8;
 | 
|---|
| 613 |     until (x = 1) or (y = 1);
 | 
|---|
| 614 |   end;
 | 
|---|
| 615 |   Result := size;
 | 
|---|
| 616 | end;
 | 
|---|
| 617 | 
 | 
|---|
| 618 | 
 | 
|---|
| 619 | 
 | 
|---|
| 620 | 
 | 
|---|
| 621 | procedure TOniImage.GetAsData(var Target: TStream);
 | 
|---|
| 622 | var
 | 
|---|
| 623 |   revert: Boolean;
 | 
|---|
| 624 | begin
 | 
|---|
| 625 |   //    if not (DT_Decoded32 in Self.FDataType) then
 | 
|---|
| 626 |   //      Self.DecodeImage;
 | 
|---|
| 627 |   if not (DT_OniReverted in Self.FDataType) then
 | 
|---|
| 628 |   begin
 | 
|---|
| 629 |     revert := True;
 | 
|---|
| 630 |     Self.RevertImage;
 | 
|---|
| 631 |   end
 | 
|---|
| 632 |   else
 | 
|---|
| 633 |     revert := False;
 | 
|---|
| 634 |   if not Assigned(Target) then
 | 
|---|
| 635 |     Target := TMemoryStream.Create;
 | 
|---|
| 636 |   Target.Write(FData[0], Length(FData));
 | 
|---|
| 637 |   Target.Seek(0, soFromBeginning);
 | 
|---|
| 638 |   if revert then
 | 
|---|
| 639 |     Self.RevertImage;
 | 
|---|
| 640 | end;
 | 
|---|
| 641 | 
 | 
|---|
| 642 | procedure TOniImage.GetAsData(var Target: TByteData);
 | 
|---|
| 643 | var
 | 
|---|
| 644 |   mem: TStream;
 | 
|---|
| 645 | begin
 | 
|---|
| 646 |   mem := TMemoryStream.Create;
 | 
|---|
| 647 |   GetAsData(mem);
 | 
|---|
| 648 |   SetLength(Target, mem.Size);
 | 
|---|
| 649 |   mem.Read(Target[0], mem.Size);
 | 
|---|
| 650 |   mem.Free;
 | 
|---|
| 651 | end;
 | 
|---|
| 652 | 
 | 
|---|
| 653 | 
 | 
|---|
| 654 | procedure TOniImage.GetAs32bit(var Target: TStream);
 | 
|---|
| 655 | begin
 | 
|---|
| 656 |   if not (DT_Decoded32 in Self.FDataType) then
 | 
|---|
| 657 |     Self.DecodeImage;
 | 
|---|
| 658 |   if not Assigned(Target) then
 | 
|---|
| 659 |     Target := TMemoryStream.Create;
 | 
|---|
| 660 |   Target.Write(FData[0], Length(FData));
 | 
|---|
| 661 |   Target.Seek(0, soFromBeginning);
 | 
|---|
| 662 | end;
 | 
|---|
| 663 | 
 | 
|---|
| 664 | procedure TOniImage.GetAs32bit(var Target: TByteData);
 | 
|---|
| 665 | var
 | 
|---|
| 666 |   mem: TStream;
 | 
|---|
| 667 | begin
 | 
|---|
| 668 |   mem := TMemoryStream.Create;
 | 
|---|
| 669 |   GetAs32bit(mem);
 | 
|---|
| 670 |   SetLength(Target, mem.Size);
 | 
|---|
| 671 |   mem.Read(Target[0], mem.Size);
 | 
|---|
| 672 |   mem.Free;
 | 
|---|
| 673 | end;
 | 
|---|
| 674 | 
 | 
|---|
| 675 | 
 | 
|---|
| 676 | procedure TOniImage.GetAsBMP(var Target: TByteData);
 | 
|---|
| 677 | const
 | 
|---|
| 678 |   BMPheader: array[0..53] of Byte =
 | 
|---|
| 679 |     ($42, $4D, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0,
 | 
|---|
| 680 |     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,
 | 
|---|
| 681 |     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 | 
|---|
| 682 | var
 | 
|---|
| 683 |   i, x, y: Integer;
 | 
|---|
| 684 | begin
 | 
|---|
| 685 |   if not (DT_Decoded32 in Self.FDataType) then
 | 
|---|
| 686 |     Self.DecodeImage;
 | 
|---|
| 687 | 
 | 
|---|
| 688 |   SetLength(Target, Self.FWidth * Self.FHeight * 3 + 54);
 | 
|---|
| 689 |   for y := 0 to Self.FHeight - 1 do
 | 
|---|
| 690 |   begin
 | 
|---|
| 691 |     for x := 0 to Self.FWidth - 1 do
 | 
|---|
| 692 |     begin
 | 
|---|
| 693 |       Target[((Self.FWidth * y + x) * 3) + 0 + 54] := Self.FData[(Self.FWidth * y + x) * 4 + 0];
 | 
|---|
| 694 |       Target[((Self.FWidth * y + x) * 3) + 1 + 54] := Self.FData[(Self.FWidth * y + x) * 4 + 1];
 | 
|---|
| 695 |       Target[((Self.FWidth * y + x) * 3) + 2 + 54] := Self.FData[(Self.FWidth * y + x) * 4 + 2];
 | 
|---|
| 696 |     end;
 | 
|---|
| 697 |   end;
 | 
|---|
| 698 | 
 | 
|---|
| 699 |   for i := 0 to High(BMPheader) do
 | 
|---|
| 700 |     Target[i] := BMPheader[i];
 | 
|---|
| 701 |   Target[2] := ((Self.FWidth * Self.FHeight * 3 + 54) and $000000FF) div $1;
 | 
|---|
| 702 |   Target[3]  := ((Self.FWidth * Self.FHeight * 3 + 54) and $0000FF00) div $100;
 | 
|---|
| 703 |   Target[4]  := ((Self.FWidth * Self.FHeight * 3 + 54) and $00FF0000) div $10000;
 | 
|---|
| 704 |   Target[5]  := ((Self.FWidth * Self.FHeight * 3 + 54) and $FF000000) div $1000000;
 | 
|---|
| 705 |   Target[18] := (Self.FWidth and $000000FF) div $1;
 | 
|---|
| 706 |   Target[19] := (Self.FWidth and $0000FF00) div $100;
 | 
|---|
| 707 |   Target[20] := (Self.FWidth and $00FF0000) div $10000;
 | 
|---|
| 708 |   Target[21] := (Self.FWidth and $FF000000) div $1000000;
 | 
|---|
| 709 |   Target[22] := (Self.FHeight and $000000FF) div $1;
 | 
|---|
| 710 |   Target[23] := (Self.FHeight and $0000FF00) div $100;
 | 
|---|
| 711 |   Target[24] := (Self.FHeight and $00FF0000) div $10000;
 | 
|---|
| 712 |   Target[25] := (Self.FHeight and $FF000000) div $1000000;
 | 
|---|
| 713 |   Target[34] := ((Self.FWidth * Self.FHeight * 3) and $000000FF) div $1;
 | 
|---|
| 714 |   Target[35] := ((Self.FWidth * Self.FHeight * 3) and $0000FF00) div $100;
 | 
|---|
| 715 |   Target[36] := ((Self.FWidth * Self.FHeight * 3) and $00FF0000) div $10000;
 | 
|---|
| 716 |   Target[37] := ((Self.FWidth * Self.FHeight * 3) and $FF000000) div $1000000;
 | 
|---|
| 717 | end;
 | 
|---|
| 718 | 
 | 
|---|
| 719 | 
 | 
|---|
| 720 | procedure TOniImage.GetAsBMP(var Target: TStream);
 | 
|---|
| 721 | var
 | 
|---|
| 722 |   data: TByteData;
 | 
|---|
| 723 |   streampos: Integer;
 | 
|---|
| 724 | begin
 | 
|---|
| 725 |   GetAsBMP(data);
 | 
|---|
| 726 |   streampos := Target.Position;
 | 
|---|
| 727 |   Target.Write(data[0], Length(data));
 | 
|---|
| 728 |   Target.Seek(streampos, soFromBeginning);
 | 
|---|
| 729 | end;
 | 
|---|
| 730 | 
 | 
|---|
| 731 | 
 | 
|---|
| 732 | function TOniImage.LoadFromBMP(filename: String): Boolean;
 | 
|---|
| 733 | var
 | 
|---|
| 734 |   filestream: TFileStream;
 | 
|---|
| 735 |   tempd:      TByteData;
 | 
|---|
| 736 | 
 | 
|---|
| 737 |   x, y: Integer;
 | 
|---|
| 738 | begin
 | 
|---|
| 739 |   filestream := TFileStream.Create(filename, fmOpenRead);
 | 
|---|
| 740 |   SetLength(tempd, filestream.Size);
 | 
|---|
| 741 |   filestream.Read(tempd[0], filestream.Size);
 | 
|---|
| 742 |   filestream.Free;
 | 
|---|
| 743 | 
 | 
|---|
| 744 |   if not ((tempd[00] = $42) and (tempd[01] = $4D)) then
 | 
|---|
| 745 |   begin
 | 
|---|
| 746 |     Result := False;
 | 
|---|
| 747 |     ShowMessage('Not a standard 24bit bitmap');
 | 
|---|
| 748 |     Exit;
 | 
|---|
| 749 |   end;
 | 
|---|
| 750 |   if not (tempd[10] = 54) then
 | 
|---|
| 751 |   begin
 | 
|---|
| 752 |     Result := False;
 | 
|---|
| 753 |     ShowMessage('Imagedata has to start at 0x54');
 | 
|---|
| 754 |     Exit;
 | 
|---|
| 755 |   end;
 | 
|---|
| 756 |   if not (tempd[14] = 40) then
 | 
|---|
| 757 |   begin
 | 
|---|
| 758 |     Result := False;
 | 
|---|
| 759 |     ShowMessage('Second bitmap header has to have 40 bytes');
 | 
|---|
| 760 |     Exit;
 | 
|---|
| 761 |   end;
 | 
|---|
| 762 |   if not (tempd[28] = 24) then
 | 
|---|
| 763 |   begin
 | 
|---|
| 764 |     Result := False;
 | 
|---|
| 765 |     ShowMessage('Bitmap has to have 24bits');
 | 
|---|
| 766 |     Exit;
 | 
|---|
| 767 |   end;
 | 
|---|
| 768 |   if not (tempd[30] = 0) then
 | 
|---|
| 769 |   begin
 | 
|---|
| 770 |     Result := False;
 | 
|---|
| 771 |     ShowMessage('Bitmap has to be uncompressed');
 | 
|---|
| 772 |     Exit;
 | 
|---|
| 773 |   end;
 | 
|---|
| 774 | 
 | 
|---|
| 775 |   Self.FWidth     := tempd[18] + tempd[19] * 256 + tempd[20] * 256 * 256 + tempd[21] * 256 * 256 * 256;
 | 
|---|
| 776 |   Self.FHeight    := tempd[22] + tempd[23] * 256 + tempd[24] * 256 * 256 + tempd[25] * 256 * 256 * 256;
 | 
|---|
| 777 |   Self.FDepth     := 32;
 | 
|---|
| 778 |   Self.FStoreType := 8;
 | 
|---|
| 779 | 
 | 
|---|
| 780 |   SetLength(Self.FData, Self.FWidth * Self.FHeight * Self.FDepth div 8);
 | 
|---|
| 781 |   for y := 0 to Self.FHeight - 1 do
 | 
|---|
| 782 |   begin
 | 
|---|
| 783 |     for x := 0 to Self.FWidth - 1 do
 | 
|---|
| 784 |     begin
 | 
|---|
| 785 |       Self.FData[((Self.FWidth * y + x) * 4) + 0] := tempd[54 + (Self.FWidth * y + x) * 3 + 0];
 | 
|---|
| 786 |       Self.FData[((Self.FWidth * y + x) * 4) + 1] := tempd[54 + (Self.FWidth * y + x) * 3 + 1];
 | 
|---|
| 787 |       Self.FData[((Self.FWidth * y + x) * 4) + 2] := tempd[54 + (Self.FWidth * y + x) * 3 + 2];
 | 
|---|
| 788 |       Self.FData[((Self.FWidth * y + x) * 4) + 3] := 0;
 | 
|---|
| 789 |     end;
 | 
|---|
| 790 |   end;
 | 
|---|
| 791 | 
 | 
|---|
| 792 |   Self.FDataType := [DT_Decoded32];
 | 
|---|
| 793 | end;
 | 
|---|
| 794 | 
 | 
|---|
| 795 | 
 | 
|---|
| 796 | 
 | 
|---|
| 797 | 
 | 
|---|
| 798 | function TOniImage.WriteToBMP(filename: String): Boolean;
 | 
|---|
| 799 | var
 | 
|---|
| 800 |   filestream: TFileStream;
 | 
|---|
| 801 | begin
 | 
|---|
| 802 |   filestream := TFileStream.Create(filename, fmCreate);
 | 
|---|
| 803 |   GetAsBMP(TStream(filestream));
 | 
|---|
| 804 |   filestream.Free;
 | 
|---|
| 805 | end;
 | 
|---|
| 806 | 
 | 
|---|
| 807 | 
 | 
|---|
| 808 | 
 | 
|---|
| 809 | function TOniImage.GetMipMappedImage(var Target: TByteData): Boolean;
 | 
|---|
| 810 | var
 | 
|---|
| 811 |   i:      Integer;
 | 
|---|
| 812 |   x, y:   Word;
 | 
|---|
| 813 |   fadelvldata: TByteData;
 | 
|---|
| 814 |   revert: Boolean;
 | 
|---|
| 815 | begin
 | 
|---|
| 816 |   Result := False;
 | 
|---|
| 817 | 
 | 
|---|
| 818 |   //    if not (DT_Decoded32 in Self.FDataType) then
 | 
|---|
| 819 |   //      Self.DecodeImage;
 | 
|---|
| 820 |   if Self.FStoreType = 9 then
 | 
|---|
| 821 |     Self.DecompressImage;
 | 
|---|
| 822 |   if not (DT_OniReverted in Self.FDataType) then
 | 
|---|
| 823 |   begin
 | 
|---|
| 824 |     revert := True;
 | 
|---|
| 825 |     Self.RevertImage;
 | 
|---|
| 826 |   end
 | 
|---|
| 827 |   else
 | 
|---|
| 828 |     revert := False;
 | 
|---|
| 829 | 
 | 
|---|
| 830 |   x := Self.FWidth;
 | 
|---|
| 831 |   y := Self.FHeight;
 | 
|---|
| 832 |   SetLength(Target, x * y * Self.FDepth div 8);
 | 
|---|
| 833 |   SetLength(fadelvldata, x * y * Self.FDepth div 8);
 | 
|---|
| 834 |   for i := 0 to Length(Target) - 1 do
 | 
|---|
| 835 |   begin
 | 
|---|
| 836 |     Target[i] := Self.FData[i];
 | 
|---|
| 837 |     fadelvldata[i] := Self.FData[i];
 | 
|---|
| 838 |   end;
 | 
|---|
| 839 |   repeat
 | 
|---|
| 840 |     fadelvldata := Self.ResizeImage(x, y, fadelvldata);
 | 
|---|
| 841 |     x := x div 2;
 | 
|---|
| 842 |     y := y div 2;
 | 
|---|
| 843 |     SetLength(Target, Length(Target) + x * y * Self.FDepth div 8);
 | 
|---|
| 844 |     for i := 0 to Length(fadelvldata) - 1 do
 | 
|---|
| 845 |       Target[Length(Target) - x * y * Self.FDepth div 8 + i] := fadelvldata[i];
 | 
|---|
| 846 |   until (x = 1) or (y = 1) or ((x mod 2) = 1) or ((y mod 2) = 1);
 | 
|---|
| 847 |   if (x > 1) and (y > 1) then
 | 
|---|
| 848 |     Exit;
 | 
|---|
| 849 |   Result := True;
 | 
|---|
| 850 | 
 | 
|---|
| 851 |   if revert then
 | 
|---|
| 852 |     Self.RevertImage;
 | 
|---|
| 853 | end;
 | 
|---|
| 854 | 
 | 
|---|
| 855 | 
 | 
|---|
| 856 | function TOniImage.GetMipMappedImage(var Target: TStream): Boolean;
 | 
|---|
| 857 | var
 | 
|---|
| 858 |   data: TByteData;
 | 
|---|
| 859 |   streampos: Integer;
 | 
|---|
| 860 | begin
 | 
|---|
| 861 |   Result := GetMipMappedImage(data);
 | 
|---|
| 862 |   if not Assigned(Target) then
 | 
|---|
| 863 |     Target := TMemoryStream.Create;
 | 
|---|
| 864 |   streampos := Target.Position;
 | 
|---|
| 865 |   Target.Write(data[0], Length(data));
 | 
|---|
| 866 |   Target.Seek(streampos, soFromBeginning);
 | 
|---|
| 867 | end;
 | 
|---|
| 868 | 
 | 
|---|
| 869 | 
 | 
|---|
| 870 | end.
 | 
|---|