unit Unit6_imgfuncs; interface uses Math, Dialogs, SysUtils, Classes, Unit3_data, Unit15_Classes; { type TImgPackage=record imgx,imgy:Word; imgdepth:Byte; storetype:Byte; datasize:LongWord; raw_addr:LongWord; imgdata:Tdata; end; } type TImgDataType=Set of (DT_OniReverted,DT_Oni,DT_MipMapped,DT_Decoded32); type TOniImage = class private FLoaded:Boolean; FDataType:TImgDataType; FData:Tdata; FWidth,FHeight:Word; FDepth:Byte; FStoreType:Byte; function ResizeImage(oldx,oldy:LongWord; img:Tdata):Tdata; procedure RevertImage; procedure DecodeImage; procedure DecompressImage; protected public property Loaded:Boolean read FLoaded; property DataType:TImgDataType read FDataType; property Width:Word read FWidth; property Height:Word read FHeight; property Depth:Byte read FDepth; property StoreType:Byte read FStoreType; property Data:Tdata read FData; constructor Create; function LoadFromTXMP(fileid:LongWord):Boolean; function LoadFromTXMB(fileid:LongWord):Boolean; function GetImageDataSize(fading:Boolean):LongWord; function GetAsData:Tdata; function GetAs32bit:Tdata; function GetAsBMP:Tdata; function LoadFromBMP(filename:String):Boolean; function WriteToBMP(filename:String):Boolean; function GetMipMappedImage(var faded:Tdata):Boolean; published end; implementation uses Unit2_functions; constructor TOniImage.Create; begin Self.FLoaded:=False; Self.FDataType:=[]; SetLength(Self.FData,0); Self.FWidth:=0; Self.FHeight:=0; Self.FDepth:=0; Self.FStoreType:=0; end; function TOniImage.ResizeImage(oldx,oldy:LongWord; img:Tdata):Tdata; var i,j:LongWord; col,row,row_orig:LongWord; begin SetLength(Result,(oldx div 2)*(oldy div 2)*(Self.FDepth div 8)); row_orig:=0; row:=0; col:=0; for i:=0 to (oldx*oldy)-1 do begin if ((i mod oldx)=0) and (i>0) then begin Inc(row_orig); if (row_orig mod 2)=0 then begin Inc(row); col:=0; end; end; if (row_orig mod 2)=0 then begin if (i mod 2)=0 then begin for j:=0 to (Self.FDepth div 8)-1 do Result[((row*(oldx div 2))+col)*(Self.FDepth div 8)+j]:=img[(i*(Self.FDepth div 8))+j]; Inc(col); end; end; end; end; procedure TOniImage.RevertImage; var x,y,i:LongWord; tempd:Tdata; begin SetLength(tempd, Self.FWidth * Self.FHeight *(Self.FDepth div 8)); for y:=0 to Self.FHeight-1 do for x:=0 to Self.FWidth-1 do for i:=0 to (Self.FDepth div 8)-1 do tempd[((Self.FWidth*(Self.FHeight-1-y)+x)*(Self.FDepth div 8))+i]:= Self.FData[(Self.FWidth*y+x)*(Self.FDepth div 8)+i]; for x:=0 to High(tempd) do Self.FData[x]:=tempd[x]; if DT_OniReverted in Self.FDataType then Self.FDataType:=Self.FDataType-[DT_OniReverted] else Self.FDataType:=Self.FDataType+[DT_OniReverted]; if DT_MipMapped in Self.FDataType then Self.FDataType:=Self.FDataType-[DT_MipMapped]; end; procedure TOniImage.DecodeImage; var x,y:LongWord; tempd:Tdata; begin if not (DT_Decoded32 in Self.FDataType) then begin SetLength(tempd, Self.FWidth * Self.FHeight * 4); case Self.FStoreType of 0: begin for y:=0 to Self.FHeight-1 do begin for x:=0 to Self.FWidth-1 do begin 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); 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); 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); tempd[((Self.FWidth*y+x)*4)+3]:=0; end; end; end; 1,2: begin for y:=0 to Self.FHeight-1 do begin for x:=0 to Self.FWidth-1 do begin 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); 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); 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); tempd[((Self.FWidth*y+x)*4)+3]:=0; end; end; end; 9: begin DecompressImage; end; end; Self.FDepth:=32; if (Self.FStoreType<>9) AND (Self.FStoreType<>8) then begin SetLength(Self.FData, Length(tempd)); for x:=0 to High(tempd) do Self.FData[x]:=tempd[x]; end; Self.FStoreType:=8; if DT_Oni in Self.FDataType then Self.FDataType:=Self.FDataType-[DT_Oni]; Self.FDataType:=Self.FDataType+[DT_Decoded32]; end; if DT_MipMapped in Self.FDataType then Self.FDataType:=Self.FDataType-[DT_MipMapped]; if DT_OniReverted in Self.FDataType then Self.RevertImage; end; procedure TOniImage.DecompressImage; type Tcolor=record RGBb:Byte; RGBg:Byte; RGBr:Byte; RGBa:Byte; end; var i,j,x,y:LongWord; color:Array[1..4] of Tcolor; pixel:Array[1..16] of Byte; tempd:Tdata; begin x:=0; y:=0; SetLength(tempd, Self.FWidth * Self.FHeight * 4); for i:=0 to ((Self.FWidth * Self.FHeight) div 16)-1 do begin Color[1].RGBb:=Floor(((Self.FData[(i*8)+0]+Self.FData[(i*8)+1]*256) and $001F) / $001F * 255); Color[1].RGBg:=Floor(((Self.FData[(i*8)+0]+Self.FData[(i*8)+1]*256) and $07E0) / $07E0 * 255); Color[1].RGBr:=Floor(((Self.FData[(i*8)+0]+Self.FData[(i*8)+1]*256) and $F800) / $F800 * 255); Color[1].RGBa:=255; Color[2].RGBb:=Floor(((Self.FData[(i*8)+2]+Self.FData[(i*8)+3]*256) and $001F) / $001F * 255); Color[2].RGBg:=Floor(((Self.FData[(i*8)+2]+Self.FData[(i*8)+3]*256) and $07E0) / $07E0 * 255); Color[2].RGBr:=Floor(((Self.FData[(i*8)+2]+Self.FData[(i*8)+3]*256) and $F800) / $F800 * 255); Color[2].RGBa:=255; Color[3].RGBb:=Floor( Color[1].RGBb/3*2 + Color[2].RGBb/3 ); Color[3].RGBg:=Floor( Color[1].RGBg/3*2 + Color[2].RGBg/3 ); Color[3].RGBr:=Floor( Color[1].RGBr/3*2 + Color[2].RGBr/3 ); Color[3].RGBa:=255; Color[4].RGBb:=Floor( Color[1].RGBb/3 + Color[2].RGBb/3*2 ); Color[4].RGBg:=Floor( Color[1].RGBg/3 + Color[2].RGBg/3*2 ); Color[4].RGBr:=Floor( Color[1].RGBr/3 + Color[2].RGBr/3*2 ); Color[4].RGBa:=255; Pixel[1]:=Floor( (Self.FData[(i*8)+4] and $C0) / $40 + 1 ); Pixel[2]:=Floor( (Self.FData[(i*8)+4] and $30) / $10 + 1 ); Pixel[3]:=Floor( (Self.FData[(i*8)+4] and $0C) / $04 + 1 ); Pixel[4]:=Floor( (Self.FData[(i*8)+4] and $03) + 1 ); Pixel[5]:=Floor( (Self.FData[(i*8)+5] and $C0) / $40 + 1 ); Pixel[6]:=Floor( (Self.FData[(i*8)+5] and $30) / $10 + 1 ); Pixel[7]:=Floor( (Self.FData[(i*8)+5] and $0C) / $04 + 1 ); Pixel[8]:=Floor( (Self.FData[(i*8)+5] and $03) + 1 ); Pixel[9]:=Floor( (Self.FData[(i*8)+6] and $C0) / $40 + 1 ); Pixel[10]:=Floor( (Self.FData[(i*8)+6] and $30) / $10 + 1 ); Pixel[11]:=Floor( (Self.FData[(i*8)+6] and $0C) / $04 + 1 ); Pixel[12]:=Floor( (Self.FData[(i*8)+6] and $03) + 1 ); Pixel[13]:=Floor( (Self.FData[(i*8)+7] and $C0) / $40 + 1 ); Pixel[14]:=Floor( (Self.FData[(i*8)+7] and $30) / $10 + 1 ); Pixel[15]:=Floor( (Self.FData[(i*8)+7] and $0C) / $04 + 1 ); Pixel[16]:=Floor( (Self.FData[(i*8)+7] and $03) + 1 ); for j:=0 to 3 do begin tempd[((y+3)*Self.FWidth+x+j)*4+0]:=Color[Pixel[16-j]].RGBb; tempd[((y+3)*Self.FWidth+x+j)*4+1]:=Color[Pixel[16-j]].RGBg; tempd[((y+3)*Self.FWidth+x+j)*4+2]:=Color[Pixel[16-j]].RGBr; tempd[((y+3)*Self.FWidth+x+j)*4+3]:=0; end; for j:=0 to 3 do begin tempd[((y+2)*Self.FWidth+x+j)*4+0]:=Color[Pixel[12-j]].RGBb; tempd[((y+2)*Self.FWidth+x+j)*4+1]:=Color[Pixel[12-j]].RGBg; tempd[((y+2)*Self.FWidth+x+j)*4+2]:=Color[Pixel[12-j]].RGBr; tempd[((y+2)*Self.FWidth+x+j)*4+3]:=0; end; for j:=0 to 3 do begin tempd[((y+1)*Self.FWidth+x+j)*4+0]:=Color[Pixel[8-j]].RGBb; tempd[((y+1)*Self.FWidth+x+j)*4+1]:=Color[Pixel[8-j]].RGBg; tempd[((y+1)*Self.FWidth+x+j)*4+2]:=Color[Pixel[8-j]].RGBr; tempd[((y+1)*Self.FWidth+x+j)*4+3]:=0; end; for j:=0 to 3 do begin tempd[((y+0)*Self.FWidth+x+j)*4+0]:=Color[Pixel[4-j]].RGBb; tempd[((y+0)*Self.FWidth+x+j)*4+1]:=Color[Pixel[4-j]].RGBg; tempd[((y+0)*Self.FWidth+x+j)*4+2]:=Color[Pixel[4-j]].RGBr; tempd[((y+0)*Self.FWidth+x+j)*4+3]:=0; end; x:=x+4; if x=Self.FWidth THEN begin y:=y+4; x:=0; end; end; SetLength(Self.FData, Length(tempd)); for i:=0 to High(tempd) do Self.FData[i]:=tempd[i]; if DT_MipMapped in Self.FDataType then Self.FDataType:=Self.FDataType-[DT_MipMapped]; end; function TOniImage.LoadFromTXMP(fileid:LongWord):Boolean; var img_addr:LongWord; begin Result:=True; OniDataConnection.LoadDatFilePart(fileid,$8C,SizeOf(Self.FWidth),@Self.FWidth); OniDataConnection.LoadDatFilePart(fileid,$8E,SizeOf(Self.FHeight),@Self.FHeight); OniDataConnection.LoadDatFilePart(fileid,$90,SizeOf(Self.FStoreType),@Self.FStoreType); if not OniDataConnection.OSisMac then OniDataConnection.LoadDatFilePart(fileid,$9C,SizeOf(img_addr),@img_addr) else OniDataConnection.LoadDatFilePart(fileid,$A0,SizeOf(img_addr),@img_addr); case Self.FStoreType of 0,1,2: begin SetLength(Self.FData, Self.FWidth * Self.FHeight * 2); Self.FDepth:=16; end; 8: begin SetLength(Self.FData, Self.FWidth * Self.FHeight * 4); Self.FDepth:=32; end; 9: begin SetLength(Self.FData, Self.FWidth * Self.FHeight div 2); Self.FDepth:=16; end; else Result:=False; Exit; end; if not OniDataConnection.OSisMac then OniDataConnection.LoadRawFile(fileid,$9C,@Self.FData[0]) else OniDataConnection.LoadRawFile(fileid,$A0,@Self.FData[0]); Self.FDataType:=[DT_OniReverted,DT_Oni]; end; function TOniImage.LoadFromTXMB(fileid:LongWord):Boolean; type TImg=record imgx,imgy:Word; imgdepth:Byte; storetype:Byte; datasize:LongWord; raw_addr:LongWord; imgdata:Tdata; end; var i,x,y,x2,y2,pixelid,imgid:LongWord; rows,cols:Word; linkcount:LongWord; link:LongWord; images_decoded:Array of TOniImage; x_start,y_start:LongWord; begin OniDataConnection.LoadDatFilePart(fileid,$10,SizeOf(Self.FWidth),@Self.FWidth); OniDataConnection.LoadDatFilePart(fileid,$12,SizeOf(Self.FHeight),@Self.FHeight); OniDataConnection.LoadDatFilePart(fileid,$18,SizeOf(cols),@cols); OniDataConnection.LoadDatFilePart(fileid,$1A,SizeOf(rows),@rows); OniDataConnection.LoadDatFilePart(fileid,$1C,SizeOf(linkcount),@linkcount); SetLength(images_decoded,linkcount); for i:=0 to linkcount-1 do begin OniDataConnection.LoadDatFilePart(fileid,$20+i*4,SizeOf(link),@link); link:=link div 256; images_decoded[i]:=TOniImage.Create; images_decoded[i].LoadFromTXMP(link); images_decoded[i].DecodeImage; images_decoded[i].RevertImage; end; SetLength(Self.FData, Self.FWidth * Self.FHeight * 4); for y:=0 to rows-1 do begin for x:=0 to cols-1 do begin imgid:=y*cols+x; x_start:=0; y_start:=0; for i:=0 to x do if i1) and (y>1) then Exit; Result:=True; if revert then Self.RevertImage; end; end.