1 |
unit Unit6_imgfuncs; |
2 |
interface |
3 |
uses Math, Dialogs, SysUtils, Classes, Unit3_data, Unit15_Classes; |
4 |
|
5 |
{ |
6 |
type |
7 |
TImgPackage=record |
8 |
imgx,imgy:Word; |
9 |
imgdepth:Byte; |
10 |
storetype:Byte; |
11 |
datasize:LongWord; |
12 |
raw_addr:LongWord; |
13 |
imgdata:Tdata; |
14 |
end; |
15 |
} |
16 |
type |
17 |
TImgDataType=Set of (DT_OniReverted,DT_Oni,DT_MipMapped,DT_Decoded32); |
18 |
|
19 |
type |
20 |
TOniImage = class |
21 |
private |
22 |
FLoaded:Boolean; |
23 |
FDataType:TImgDataType; |
24 |
FData:Tdata; |
25 |
FWidth,FHeight:Word; |
26 |
FDepth:Byte; |
27 |
FStoreType:Byte; |
28 |
|
29 |
function ResizeImage(oldx,oldy:LongWord; img:Tdata):Tdata; |
30 |
procedure RevertImage; |
31 |
procedure DecodeImage; |
32 |
procedure DecompressImage; |
33 |
protected |
34 |
public |
35 |
property Loaded:Boolean read FLoaded; |
36 |
property DataType:TImgDataType read FDataType; |
37 |
property Width:Word read FWidth; |
38 |
property Height:Word read FHeight; |
39 |
property Depth:Byte read FDepth; |
40 |
property StoreType:Byte read FStoreType; |
41 |
property Data:Tdata read FData; |
42 |
|
43 |
constructor Create; |
44 |
function LoadFromTXMP(fileid:LongWord):Boolean; |
45 |
function LoadFromTXMB(fileid:LongWord):Boolean; |
46 |
function GetImageDataSize(fading:Boolean):LongWord; |
47 |
|
48 |
function GetAsData:Tdata; |
49 |
function GetAs32bit:Tdata; |
50 |
function GetAsBMP:Tdata; |
51 |
function LoadFromBMP(filename:String):Boolean; |
52 |
function WriteToBMP(filename:String):Boolean; |
53 |
function GetMipMappedImage(var faded:Tdata):Boolean; |
54 |
published |
55 |
end; |
56 |
|
57 |
|
58 |
implementation |
59 |
uses Unit2_functions; |
60 |
|
61 |
|
62 |
|
63 |
constructor TOniImage.Create; |
64 |
begin |
65 |
Self.FLoaded:=False; |
66 |
Self.FDataType:=[]; |
67 |
SetLength(Self.FData,0); |
68 |
Self.FWidth:=0; |
69 |
Self.FHeight:=0; |
70 |
Self.FDepth:=0; |
71 |
Self.FStoreType:=0; |
72 |
end; |
73 |
|
74 |
|
75 |
|
76 |
function TOniImage.ResizeImage(oldx,oldy:LongWord; img:Tdata):Tdata; |
77 |
var |
78 |
i,j:LongWord; |
79 |
col,row,row_orig:LongWord; |
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 begin |
86 |
if ((i mod oldx)=0) and (i>0) then begin |
87 |
Inc(row_orig); |
88 |
if (row_orig mod 2)=0 then begin |
89 |
Inc(row); |
90 |
col:=0; |
91 |
end; |
92 |
end; |
93 |
if (row_orig mod 2)=0 then begin |
94 |
if (i mod 2)=0 then begin |
95 |
for j:=0 to (Self.FDepth div 8)-1 do |
96 |
Result[((row*(oldx div 2))+col)*(Self.FDepth div 8)+j]:=img[(i*(Self.FDepth div 8))+j]; |
97 |
Inc(col); |
98 |
end; |
99 |
end; |
100 |
end; |
101 |
end; |
102 |
|
103 |
|
104 |
|
105 |
procedure TOniImage.RevertImage; |
106 |
var |
107 |
x,y,i:LongWord; |
108 |
tempd:Tdata; |
109 |
begin |
110 |
SetLength(tempd, Self.FWidth * Self.FHeight *(Self.FDepth div 8)); |
111 |
for y:=0 to Self.FHeight-1 do |
112 |
for x:=0 to Self.FWidth-1 do |
113 |
for i:=0 to (Self.FDepth div 8)-1 do |
114 |
tempd[((Self.FWidth*(Self.FHeight-1-y)+x)*(Self.FDepth div 8))+i]:= |
115 |
Self.FData[(Self.FWidth*y+x)*(Self.FDepth div 8)+i]; |
116 |
for x:=0 to High(tempd) do |
117 |
Self.FData[x]:=tempd[x]; |
118 |
if DT_OniReverted in Self.FDataType then |
119 |
Self.FDataType:=Self.FDataType-[DT_OniReverted] |
120 |
else |
121 |
Self.FDataType:=Self.FDataType+[DT_OniReverted]; |
122 |
if DT_MipMapped in Self.FDataType then |
123 |
Self.FDataType:=Self.FDataType-[DT_MipMapped]; |
124 |
end; |
125 |
|
126 |
|
127 |
|
128 |
procedure TOniImage.DecodeImage; |
129 |
var |
130 |
x,y:LongWord; |
131 |
tempd:Tdata; |
132 |
begin |
133 |
if not (DT_Decoded32 in Self.FDataType) then begin |
134 |
SetLength(tempd, Self.FWidth * Self.FHeight * 4); |
135 |
case Self.FStoreType of |
136 |
0: begin |
137 |
for y:=0 to Self.FHeight-1 do begin |
138 |
for x:=0 to Self.FWidth-1 do begin |
139 |
tempd[((Self.FWidth*y+x)*4)+0]:=Floor( ( (Self.FData[(Self.FWidth*y+x)*2]+Self.FData[(Self.FWidth*y+x)*2+1]*256) AND $000F ) / $000F * 255); |
140 |
tempd[((Self.FWidth*y+x)*4)+1]:=Floor( ( (Self.FData[(Self.FWidth*y+x)*2]+Self.FData[(Self.FWidth*y+x)*2+1]*256) AND $00F0 ) / $00F0 * 255); |
141 |
tempd[((Self.FWidth*y+x)*4)+2]:=Floor( ( (Self.FData[(Self.FWidth*y+x)*2]+Self.FData[(Self.FWidth*y+x)*2+1]*256) AND $0F00 ) / $0F00 * 255); |
142 |
tempd[((Self.FWidth*y+x)*4)+3]:=0; |
143 |
end; |
144 |
end; |
145 |
end; |
146 |
1,2: begin |
147 |
for y:=0 to Self.FHeight-1 do begin |
148 |
for x:=0 to Self.FWidth-1 do begin |
149 |
tempd[((Self.FWidth*y+x)*4)+0]:=Floor( ( (Self.FData[(Self.FWidth*y+x)*2]+Self.FData[(Self.FWidth*y+x)*2+1]*256) AND $001F ) / $001F * 255); |
150 |
tempd[((Self.FWidth*y+x)*4)+1]:=Floor( ( (Self.FData[(Self.FWidth*y+x)*2]+Self.FData[(Self.FWidth*y+x)*2+1]*256) AND $03E0 ) / $03E0 * 255); |
151 |
tempd[((Self.FWidth*y+x)*4)+2]:=Floor( ( (Self.FData[(Self.FWidth*y+x)*2]+Self.FData[(Self.FWidth*y+x)*2+1]*256) AND $7C00 ) / $7C00 * 255); |
152 |
tempd[((Self.FWidth*y+x)*4)+3]:=0; |
153 |
end; |
154 |
end; |
155 |
end; |
156 |
9: begin |
157 |
DecompressImage; |
158 |
end; |
159 |
end; |
160 |
Self.FDepth:=32; |
161 |
if (Self.FStoreType<>9) AND (Self.FStoreType<>8) then begin |
162 |
SetLength(Self.FData, Length(tempd)); |
163 |
for x:=0 to High(tempd) do |
164 |
Self.FData[x]:=tempd[x]; |
165 |
end; |
166 |
Self.FStoreType:=8; |
167 |
if DT_Oni in Self.FDataType then |
168 |
Self.FDataType:=Self.FDataType-[DT_Oni]; |
169 |
Self.FDataType:=Self.FDataType+[DT_Decoded32]; |
170 |
end; |
171 |
if DT_MipMapped in Self.FDataType then |
172 |
Self.FDataType:=Self.FDataType-[DT_MipMapped]; |
173 |
if DT_OniReverted in Self.FDataType then |
174 |
Self.RevertImage; |
175 |
end; |
176 |
|
177 |
|
178 |
|
179 |
procedure TOniImage.DecompressImage; |
180 |
type |
181 |
Tcolor=record |
182 |
RGBb:Byte; |
183 |
RGBg:Byte; |
184 |
RGBr:Byte; |
185 |
RGBa:Byte; |
186 |
end; |
187 |
var |
188 |
i,j,x,y:LongWord; |
189 |
color:Array[1..4] of Tcolor; |
190 |
pixel:Array[1..16] of Byte; |
191 |
tempd:Tdata; |
192 |
begin |
193 |
x:=0; |
194 |
y:=0; |
195 |
SetLength(tempd, Self.FWidth * Self.FHeight * 4); |
196 |
for i:=0 to ((Self.FWidth * Self.FHeight) div 16)-1 do begin |
197 |
Color[1].RGBb:=Floor(((Self.FData[(i*8)+0]+Self.FData[(i*8)+1]*256) and $001F) / $001F * 255); |
198 |
Color[1].RGBg:=Floor(((Self.FData[(i*8)+0]+Self.FData[(i*8)+1]*256) and $07E0) / $07E0 * 255); |
199 |
Color[1].RGBr:=Floor(((Self.FData[(i*8)+0]+Self.FData[(i*8)+1]*256) and $F800) / $F800 * 255); |
200 |
Color[1].RGBa:=255; |
201 |
Color[2].RGBb:=Floor(((Self.FData[(i*8)+2]+Self.FData[(i*8)+3]*256) and $001F) / $001F * 255); |
202 |
Color[2].RGBg:=Floor(((Self.FData[(i*8)+2]+Self.FData[(i*8)+3]*256) and $07E0) / $07E0 * 255); |
203 |
Color[2].RGBr:=Floor(((Self.FData[(i*8)+2]+Self.FData[(i*8)+3]*256) and $F800) / $F800 * 255); |
204 |
Color[2].RGBa:=255; |
205 |
Color[3].RGBb:=Floor( Color[1].RGBb/3*2 + Color[2].RGBb/3 ); |
206 |
Color[3].RGBg:=Floor( Color[1].RGBg/3*2 + Color[2].RGBg/3 ); |
207 |
Color[3].RGBr:=Floor( Color[1].RGBr/3*2 + Color[2].RGBr/3 ); |
208 |
Color[3].RGBa:=255; |
209 |
Color[4].RGBb:=Floor( Color[1].RGBb/3 + Color[2].RGBb/3*2 ); |
210 |
Color[4].RGBg:=Floor( Color[1].RGBg/3 + Color[2].RGBg/3*2 ); |
211 |
Color[4].RGBr:=Floor( Color[1].RGBr/3 + Color[2].RGBr/3*2 ); |
212 |
Color[4].RGBa:=255; |
213 |
Pixel[1]:=Floor( (Self.FData[(i*8)+4] and $C0) / $40 + 1 ); |
214 |
Pixel[2]:=Floor( (Self.FData[(i*8)+4] and $30) / $10 + 1 ); |
215 |
Pixel[3]:=Floor( (Self.FData[(i*8)+4] and $0C) / $04 + 1 ); |
216 |
Pixel[4]:=Floor( (Self.FData[(i*8)+4] and $03) + 1 ); |
217 |
Pixel[5]:=Floor( (Self.FData[(i*8)+5] and $C0) / $40 + 1 ); |
218 |
Pixel[6]:=Floor( (Self.FData[(i*8)+5] and $30) / $10 + 1 ); |
219 |
Pixel[7]:=Floor( (Self.FData[(i*8)+5] and $0C) / $04 + 1 ); |
220 |
Pixel[8]:=Floor( (Self.FData[(i*8)+5] and $03) + 1 ); |
221 |
Pixel[9]:=Floor( (Self.FData[(i*8)+6] and $C0) / $40 + 1 ); |
222 |
Pixel[10]:=Floor( (Self.FData[(i*8)+6] and $30) / $10 + 1 ); |
223 |
Pixel[11]:=Floor( (Self.FData[(i*8)+6] and $0C) / $04 + 1 ); |
224 |
Pixel[12]:=Floor( (Self.FData[(i*8)+6] and $03) + 1 ); |
225 |
Pixel[13]:=Floor( (Self.FData[(i*8)+7] and $C0) / $40 + 1 ); |
226 |
Pixel[14]:=Floor( (Self.FData[(i*8)+7] and $30) / $10 + 1 ); |
227 |
Pixel[15]:=Floor( (Self.FData[(i*8)+7] and $0C) / $04 + 1 ); |
228 |
Pixel[16]:=Floor( (Self.FData[(i*8)+7] and $03) + 1 ); |
229 |
for j:=0 to 3 do begin |
230 |
tempd[((y+3)*Self.FWidth+x+j)*4+0]:=Color[Pixel[16-j]].RGBb; |
231 |
tempd[((y+3)*Self.FWidth+x+j)*4+1]:=Color[Pixel[16-j]].RGBg; |
232 |
tempd[((y+3)*Self.FWidth+x+j)*4+2]:=Color[Pixel[16-j]].RGBr; |
233 |
tempd[((y+3)*Self.FWidth+x+j)*4+3]:=0; |
234 |
end; |
235 |
for j:=0 to 3 do begin |
236 |
tempd[((y+2)*Self.FWidth+x+j)*4+0]:=Color[Pixel[12-j]].RGBb; |
237 |
tempd[((y+2)*Self.FWidth+x+j)*4+1]:=Color[Pixel[12-j]].RGBg; |
238 |
tempd[((y+2)*Self.FWidth+x+j)*4+2]:=Color[Pixel[12-j]].RGBr; |
239 |
tempd[((y+2)*Self.FWidth+x+j)*4+3]:=0; |
240 |
end; |
241 |
for j:=0 to 3 do begin |
242 |
tempd[((y+1)*Self.FWidth+x+j)*4+0]:=Color[Pixel[8-j]].RGBb; |
243 |
tempd[((y+1)*Self.FWidth+x+j)*4+1]:=Color[Pixel[8-j]].RGBg; |
244 |
tempd[((y+1)*Self.FWidth+x+j)*4+2]:=Color[Pixel[8-j]].RGBr; |
245 |
tempd[((y+1)*Self.FWidth+x+j)*4+3]:=0; |
246 |
end; |
247 |
for j:=0 to 3 do begin |
248 |
tempd[((y+0)*Self.FWidth+x+j)*4+0]:=Color[Pixel[4-j]].RGBb; |
249 |
tempd[((y+0)*Self.FWidth+x+j)*4+1]:=Color[Pixel[4-j]].RGBg; |
250 |
tempd[((y+0)*Self.FWidth+x+j)*4+2]:=Color[Pixel[4-j]].RGBr; |
251 |
tempd[((y+0)*Self.FWidth+x+j)*4+3]:=0; |
252 |
end; |
253 |
x:=x+4; |
254 |
if x=Self.FWidth THEN begin |
255 |
y:=y+4; |
256 |
x:=0; |
257 |
end; |
258 |
end; |
259 |
SetLength(Self.FData, Length(tempd)); |
260 |
for i:=0 to High(tempd) do |
261 |
Self.FData[i]:=tempd[i]; |
262 |
if DT_MipMapped in Self.FDataType then |
263 |
Self.FDataType:=Self.FDataType-[DT_MipMapped]; |
264 |
end; |
265 |
|
266 |
|
267 |
|
268 |
|
269 |
|
270 |
function TOniImage.LoadFromTXMP(fileid:LongWord):Boolean; |
271 |
var |
272 |
img_addr:LongWord; |
273 |
begin |
274 |
Result:=True; |
275 |
OniDataConnection.LoadDatFilePart(fileid,$8C,SizeOf(Self.FWidth),@Self.FWidth); |
276 |
OniDataConnection.LoadDatFilePart(fileid,$8E,SizeOf(Self.FHeight),@Self.FHeight); |
277 |
OniDataConnection.LoadDatFilePart(fileid,$90,SizeOf(Self.FStoreType),@Self.FStoreType); |
278 |
if not OniDataConnection.OSisMac then |
279 |
OniDataConnection.LoadDatFilePart(fileid,$9C,SizeOf(img_addr),@img_addr) |
280 |
else |
281 |
OniDataConnection.LoadDatFilePart(fileid,$A0,SizeOf(img_addr),@img_addr); |
282 |
|
283 |
case Self.FStoreType of |
284 |
0,1,2: begin |
285 |
SetLength(Self.FData, Self.FWidth * Self.FHeight * 2); |
286 |
Self.FDepth:=16; |
287 |
end; |
288 |
8: begin |
289 |
SetLength(Self.FData, Self.FWidth * Self.FHeight * 4); |
290 |
Self.FDepth:=32; |
291 |
end; |
292 |
9: begin |
293 |
SetLength(Self.FData, Self.FWidth * Self.FHeight div 2); |
294 |
Self.FDepth:=16; |
295 |
end; |
296 |
else |
297 |
Result:=False; |
298 |
Exit; |
299 |
end; |
300 |
|
301 |
if not OniDataConnection.OSisMac then |
302 |
OniDataConnection.LoadRawFile(fileid,$9C,@Self.FData[0]) |
303 |
else |
304 |
OniDataConnection.LoadRawFile(fileid,$A0,@Self.FData[0]); |
305 |
|
306 |
Self.FDataType:=[DT_OniReverted,DT_Oni]; |
307 |
end; |
308 |
|
309 |
|
310 |
|
311 |
function TOniImage.LoadFromTXMB(fileid:LongWord):Boolean; |
312 |
type |
313 |
TImg=record |
314 |
imgx,imgy:Word; |
315 |
imgdepth:Byte; |
316 |
storetype:Byte; |
317 |
datasize:LongWord; |
318 |
raw_addr:LongWord; |
319 |
imgdata:Tdata; |
320 |
end; |
321 |
var |
322 |
i,x,y,x2,y2,pixelid,imgid:LongWord; |
323 |
rows,cols:Word; |
324 |
linkcount:LongWord; |
325 |
link:LongWord; |
326 |
images_decoded:Array of TOniImage; |
327 |
x_start,y_start:LongWord; |
328 |
begin |
329 |
OniDataConnection.LoadDatFilePart(fileid,$10,SizeOf(Self.FWidth),@Self.FWidth); |
330 |
OniDataConnection.LoadDatFilePart(fileid,$12,SizeOf(Self.FHeight),@Self.FHeight); |
331 |
OniDataConnection.LoadDatFilePart(fileid,$18,SizeOf(cols),@cols); |
332 |
OniDataConnection.LoadDatFilePart(fileid,$1A,SizeOf(rows),@rows); |
333 |
OniDataConnection.LoadDatFilePart(fileid,$1C,SizeOf(linkcount),@linkcount); |
334 |
SetLength(images_decoded,linkcount); |
335 |
for i:=0 to linkcount-1 do begin |
336 |
OniDataConnection.LoadDatFilePart(fileid,$20+i*4,SizeOf(link),@link); |
337 |
link:=link div 256; |
338 |
images_decoded[i]:=TOniImage.Create; |
339 |
images_decoded[i].LoadFromTXMP(link); |
340 |
images_decoded[i].DecodeImage; |
341 |
images_decoded[i].RevertImage; |
342 |
end; |
343 |
SetLength(Self.FData, Self.FWidth * Self.FHeight * 4); |
344 |
for y:=0 to rows-1 do begin |
345 |
for x:=0 to cols-1 do begin |
346 |
imgid:=y*cols+x; |
347 |
x_start:=0; |
348 |
y_start:=0; |
349 |
for i:=0 to x do if i<x then x_start:=x_start+images_decoded[i].Width; |
350 |
for i:=0 to y do if i<y then y_start:=y_start+images_decoded[i].Height; |
351 |
for y2:=0 to images_decoded[imgid].Height-1 do begin |
352 |
for x2:=0 to images_decoded[imgid].Width-1 do begin |
353 |
if ( (x_start+x2)<Self.FWidth ) and ( (y_start+y2)<Self.FHeight ) then begin |
354 |
pixelid:=y_start*Self.FWidth+x_start+y2*Self.FWidth+x2; |
355 |
Self.FData[pixelid*4+0]:=images_decoded[imgid].Data[(y2*images_decoded[imgid].Width+x2)*4+0]; |
356 |
Self.FData[pixelid*4+1]:=images_decoded[imgid].Data[(y2*images_decoded[imgid].Width+x2)*4+1]; |
357 |
Self.FData[pixelid*4+2]:=images_decoded[imgid].Data[(y2*images_decoded[imgid].Width+x2)*4+2]; |
358 |
Self.FData[pixelid*4+3]:=images_decoded[imgid].Data[(y2*images_decoded[imgid].Width+x2)*4+3]; |
359 |
end; |
360 |
end; |
361 |
end; |
362 |
end; |
363 |
end; |
364 |
for i:=0 to linkcount-1 do |
365 |
images_decoded[i].Free; |
366 |
Self.FDepth:=32; |
367 |
Self.FStoreType:=1; |
368 |
Self.FDataType:=[DT_Decoded32]; |
369 |
Self.RevertImage; |
370 |
end; |
371 |
|
372 |
|
373 |
|
374 |
function TOniImage.GetImageDataSize(fading:Boolean):LongWord; |
375 |
var |
376 |
size:LongWord; |
377 |
x,y:Word; |
378 |
bpp:Byte; |
379 |
begin |
380 |
case Self.FStoreType of |
381 |
9: bpp:=8; |
382 |
0,1,2: bpp:=16; |
383 |
8: bpp:=32; |
384 |
else |
385 |
Result:=0; |
386 |
Exit; |
387 |
end; |
388 |
|
389 |
x:=Self.FWidth; |
390 |
y:=Self.FHeight; |
391 |
size:=x*y*bpp div 8; |
392 |
if fading then begin |
393 |
repeat |
394 |
x:=x div 2; |
395 |
y:=y div 2; |
396 |
size:=size+x*y*bpp div 8; |
397 |
until (x=1) or (y=1); |
398 |
end; |
399 |
Result:=size; |
400 |
end; |
401 |
|
402 |
|
403 |
|
404 |
function TOniImage.GetAsData:Tdata; |
405 |
var |
406 |
i: Integer; |
407 |
revert:Boolean; |
408 |
begin |
409 |
// if not (DT_Decoded32 in Self.FDataType) then |
410 |
// Self.DecodeImage; |
411 |
if not (DT_OniReverted in Self.FDataType) then begin |
412 |
revert:=True; |
413 |
Self.RevertImage; |
414 |
end else revert:=False; |
415 |
SetLength(Result, Length(Self.FData)); |
416 |
for i:=0 to High(Result) do |
417 |
Result[i]:=Self.FData[i]; |
418 |
if revert then |
419 |
Self.RevertImage; |
420 |
end; |
421 |
|
422 |
|
423 |
|
424 |
function TOniImage.GetAs32bit:Tdata; |
425 |
var |
426 |
i:Integer; |
427 |
begin |
428 |
if not (DT_Decoded32 in Self.FDataType) then |
429 |
Self.DecodeImage; |
430 |
SetLength(Result,Length(Self.FData)); |
431 |
for i:=0 to High(Result) do |
432 |
Result[i]:=Self.FData[i]; |
433 |
end; |
434 |
|
435 |
|
436 |
|
437 |
function TOniImage.GetAsBMP:Tdata; |
438 |
const BMPheader:Array[0..53] of Byte= |
439 |
($42,$4D,0,0,0,0,0,0,0,0,54,0,0,0, |
440 |
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,0,0,0,0,0,0,0,0,0,0,0,0,0); |
441 |
var |
442 |
i,x,y:LongWord; |
443 |
begin |
444 |
if not (DT_Decoded32 in Self.FDataType) then |
445 |
Self.DecodeImage; |
446 |
|
447 |
SetLength(Result, Self.FWidth * Self.FHeight * 3); |
448 |
for y:=0 to Self.FHeight-1 do begin |
449 |
for x:=0 to Self.FWidth-1 do begin |
450 |
Result[((Self.FWidth*y+x)*3)+0]:=Self.FData[(Self.FWidth*y+x)*4+0]; |
451 |
Result[((Self.FWidth*y+x)*3)+1]:=Self.FData[(Self.FWidth*y+x)*4+1]; |
452 |
Result[((Self.FWidth*y+x)*3)+2]:=Self.FData[(Self.FWidth*y+x)*4+2]; |
453 |
end; |
454 |
end; |
455 |
|
456 |
SetLength(Result, Self.FWidth * Self.FHeight * 3 + 54); |
457 |
for i:=High(Result)-54 downto 0 do |
458 |
Result[i+54]:=Result[i]; |
459 |
|
460 |
for i:=0 to High(BMPheader) do |
461 |
Result[i]:=BMPheader[i]; |
462 |
Result[2]:=((Self.FWidth*Self.FHeight*3+54) and $000000FF) div $1; |
463 |
Result[3]:=((Self.FWidth*Self.FHeight*3+54) and $0000FF00) div $100; |
464 |
Result[4]:=((Self.FWidth*Self.FHeight*3+54) and $00FF0000) div $10000; |
465 |
Result[5]:=((Self.FWidth*Self.FHeight*3+54) and $FF000000) div $1000000; |
466 |
Result[18]:=(Self.FWidth and $000000FF) div $1; |
467 |
Result[19]:=(Self.FWidth and $0000FF00) div $100; |
468 |
Result[20]:=(Self.FWidth and $00FF0000) div $10000; |
469 |
Result[21]:=(Self.FWidth and $FF000000) div $1000000; |
470 |
Result[22]:=(Self.FHeight and $000000FF) div $1; |
471 |
Result[23]:=(Self.FHeight and $0000FF00) div $100; |
472 |
Result[24]:=(Self.FHeight and $00FF0000) div $10000; |
473 |
Result[25]:=(Self.FHeight and $FF000000) div $1000000; |
474 |
Result[34]:=((Self.FWidth*Self.FHeight*3) and $000000FF) div $1; |
475 |
Result[35]:=((Self.FWidth*Self.FHeight*3) and $0000FF00) div $100; |
476 |
Result[36]:=((Self.FWidth*Self.FHeight*3) and $00FF0000) div $10000; |
477 |
Result[37]:=((Self.FWidth*Self.FHeight*3) and $FF000000) div $1000000; |
478 |
end; |
479 |
|
480 |
|
481 |
|
482 |
function TOniImage.LoadFromBMP(filename:String):Boolean; |
483 |
var |
484 |
filestream:TFileStream; |
485 |
tempd:Tdata; |
486 |
|
487 |
x,y:LongWord; |
488 |
begin |
489 |
filestream:=TFileStream.Create(filename, fmOpenRead); |
490 |
SetLength(tempd,filestream.Size); |
491 |
filestream.Read(tempd[0],filestream.Size); |
492 |
filestream.Free; |
493 |
|
494 |
if not((tempd[00]=$42) and (tempd[01]=$4D)) then begin |
495 |
Result:=False; |
496 |
ShowMessage('Not a standard 24bit bitmap'); |
497 |
Exit; |
498 |
end; |
499 |
if not(tempd[10]=54) then begin |
500 |
Result:=False; |
501 |
ShowMessage('Imagedata has to start at 0x54'); |
502 |
Exit; |
503 |
end; |
504 |
if not(tempd[14]=40) then begin |
505 |
Result:=False; |
506 |
ShowMessage('Second bitmap header has to have 40 bytes'); |
507 |
Exit; |
508 |
end; |
509 |
if not(tempd[28]=24) then begin |
510 |
Result:=False; |
511 |
ShowMessage('Bitmap has to have 24bits'); |
512 |
Exit; |
513 |
end; |
514 |
if not(tempd[30]=0) then begin |
515 |
Result:=False; |
516 |
ShowMessage('Bitmap has to be uncompressed'); |
517 |
Exit; |
518 |
end; |
519 |
|
520 |
Self.FWidth :=tempd[18]+tempd[19]*256+tempd[20]*256*256+tempd[21]*256*256*256; |
521 |
Self.FHeight:=tempd[22]+tempd[23]*256+tempd[24]*256*256+tempd[25]*256*256*256; |
522 |
Self.FDepth:=32; |
523 |
Self.FStoreType:=8; |
524 |
|
525 |
SetLength(Self.FData, Self.FWidth * Self.FHeight * Self.FDepth div 8); |
526 |
for y:=0 to Self.FHeight-1 do begin |
527 |
for x:=0 to Self.FWidth-1 do begin |
528 |
Self.FData[((Self.FWidth*y+x)*4)+0]:=tempd[54+(Self.FWidth*y+x)*3+0]; |
529 |
Self.FData[((Self.FWidth*y+x)*4)+1]:=tempd[54+(Self.FWidth*y+x)*3+1]; |
530 |
Self.FData[((Self.FWidth*y+x)*4)+2]:=tempd[54+(Self.FWidth*y+x)*3+2]; |
531 |
Self.FData[((Self.FWidth*y+x)*4)+3]:=0; |
532 |
end; |
533 |
end; |
534 |
|
535 |
Self.FDataType:=[DT_Decoded32]; |
536 |
end; |
537 |
|
538 |
|
539 |
|
540 |
function TOniImage.WriteToBMP(filename:String):Boolean; |
541 |
var |
542 |
filestream:TFileStream; |
543 |
tempd:Tdata; |
544 |
begin |
545 |
tempd:=Self.GetAsBMP; |
546 |
filestream:=TFileStream.Create(filename,fmCreate); |
547 |
filestream.Write(tempd[0],Length(tempd)); |
548 |
filestream.Free; |
549 |
end; |
550 |
|
551 |
|
552 |
|
553 |
function TOniImage.GetMipMappedImage(var faded:Tdata):Boolean; |
554 |
var |
555 |
i:LongWord; |
556 |
x,y:Word; |
557 |
fadelvldata:Tdata; |
558 |
revert:Boolean; |
559 |
begin |
560 |
Result:=False; |
561 |
|
562 |
// if not (DT_Decoded32 in Self.FDataType) then |
563 |
// Self.DecodeImage; |
564 |
if not (DT_OniReverted in Self.FDataType) then begin |
565 |
revert:=True; |
566 |
Self.RevertImage; |
567 |
end else revert:=False; |
568 |
|
569 |
x:=Self.FWidth; |
570 |
y:=Self.FHeight; |
571 |
SetLength(faded,x*y*Self.FDepth div 8); |
572 |
SetLength(fadelvldata,x*y*Self.FDepth div 8); |
573 |
for i:=0 to Length(faded)-1 do begin |
574 |
faded[i]:=Self.FData[i]; |
575 |
fadelvldata[i]:=Self.FData[i]; |
576 |
end; |
577 |
repeat |
578 |
fadelvldata:=Self.ResizeImage(x,y,fadelvldata); |
579 |
x:=x div 2; |
580 |
y:=y div 2; |
581 |
SetLength(faded,Length(faded)+x*y*Self.FDepth div 8); |
582 |
for i:=0 to Length(fadelvldata)-1 do |
583 |
faded[Length(faded)-x*y*Self.FDepth div 8+i]:=fadelvldata[i]; |
584 |
until (x=1) or (y=1) or ((x mod 2)=1) or ((y mod 2)=1); |
585 |
if (x>1) and (y>1) then Exit; |
586 |
Result:=True; |
587 |
|
588 |
if revert then |
589 |
Self.RevertImage; |
590 |
end; |
591 |
|
592 |
|
593 |
end. |