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 i<x then x_start:=x_start+images_decoded[i].Width;
        for i:=0 to y do   if i<y then y_start:=y_start+images_decoded[i].Height;
        for y2:=0 to images_decoded[imgid].Height-1 do begin
          for x2:=0 to images_decoded[imgid].Width-1 do begin
            if ( (x_start+x2)<Self.FWidth ) and ( (y_start+y2)<Self.FHeight ) then begin
              pixelid:=y_start*Self.FWidth+x_start+y2*Self.FWidth+x2;
              Self.FData[pixelid*4+0]:=images_decoded[imgid].Data[(y2*images_decoded[imgid].Width+x2)*4+0];
              Self.FData[pixelid*4+1]:=images_decoded[imgid].Data[(y2*images_decoded[imgid].Width+x2)*4+1];
              Self.FData[pixelid*4+2]:=images_decoded[imgid].Data[(y2*images_decoded[imgid].Width+x2)*4+2];
              Self.FData[pixelid*4+3]:=images_decoded[imgid].Data[(y2*images_decoded[imgid].Width+x2)*4+3];
            end;
          end;
        end;
      end;
    end;
    for i:=0 to linkcount-1 do
      images_decoded[i].Free;
    Self.FDepth:=32;
    Self.FStoreType:=1;
    Self.FDataType:=[DT_Decoded32];
    Self.RevertImage;
  end;



function TOniImage.GetImageDataSize(fading:Boolean):LongWord;
  var
    size:LongWord;
    x,y:Word;
    bpp:Byte;
  begin
    case Self.FStoreType of
        9: bpp:=8;
        0,1,2: bpp:=16;
        8: bpp:=32;
    else
      Result:=0;
      Exit;
    end;

    x:=Self.FWidth;
    y:=Self.FHeight;
    size:=x*y*bpp div 8;
    if fading then begin
      repeat
        x:=x div 2;
        y:=y div 2;
        size:=size+x*y*bpp div 8;
      until (x=1) or (y=1);
    end;
    Result:=size;
  end;



function TOniImage.GetAsData:Tdata;
  var
    i: Integer;
    revert:Boolean;
  begin
//    if not (DT_Decoded32 in Self.FDataType) then
//      Self.DecodeImage;
    if not (DT_OniReverted in Self.FDataType) then begin
      revert:=True;
      Self.RevertImage;
    end else revert:=False;
    SetLength(Result, Length(Self.FData));
    for i:=0 to High(Result) do
      Result[i]:=Self.FData[i];
    if revert then
      Self.RevertImage;
  end;



function TOniImage.GetAs32bit:Tdata;
  var
    i:Integer;
  begin
    if not (DT_Decoded32 in Self.FDataType) then
      Self.DecodeImage;
    SetLength(Result,Length(Self.FData));
    for i:=0 to High(Result) do
      Result[i]:=Self.FData[i];
  end;



function TOniImage.GetAsBMP:Tdata;
  const BMPheader:Array[0..53] of Byte=
          ($42,$4D,0,0,0,0,0,0,0,0,54,0,0,0,
           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);
  var
    i,x,y:LongWord;
  begin
    if not (DT_Decoded32 in Self.FDataType) then
      Self.DecodeImage;

    SetLength(Result, Self.FWidth * Self.FHeight * 3);
    for y:=0 to Self.FHeight-1 do begin
      for x:=0 to Self.FWidth-1 do begin
        Result[((Self.FWidth*y+x)*3)+0]:=Self.FData[(Self.FWidth*y+x)*4+0];
        Result[((Self.FWidth*y+x)*3)+1]:=Self.FData[(Self.FWidth*y+x)*4+1];
        Result[((Self.FWidth*y+x)*3)+2]:=Self.FData[(Self.FWidth*y+x)*4+2];
      end;
    end;

    SetLength(Result, Self.FWidth * Self.FHeight * 3 + 54);
    for i:=High(Result)-54 downto 0 do
      Result[i+54]:=Result[i];

    for i:=0 to High(BMPheader) do
      Result[i]:=BMPheader[i];
    Result[2]:=((Self.FWidth*Self.FHeight*3+54) and $000000FF) div $1;
    Result[3]:=((Self.FWidth*Self.FHeight*3+54) and $0000FF00) div $100;
    Result[4]:=((Self.FWidth*Self.FHeight*3+54) and $00FF0000) div $10000;
    Result[5]:=((Self.FWidth*Self.FHeight*3+54) and $FF000000) div $1000000;
    Result[18]:=(Self.FWidth and $000000FF) div $1;
    Result[19]:=(Self.FWidth and $0000FF00) div $100;
    Result[20]:=(Self.FWidth and $00FF0000) div $10000;
    Result[21]:=(Self.FWidth and $FF000000) div $1000000;
    Result[22]:=(Self.FHeight and $000000FF) div $1;
    Result[23]:=(Self.FHeight and $0000FF00) div $100;
    Result[24]:=(Self.FHeight and $00FF0000) div $10000;
    Result[25]:=(Self.FHeight and $FF000000) div $1000000;
    Result[34]:=((Self.FWidth*Self.FHeight*3) and $000000FF) div $1;
    Result[35]:=((Self.FWidth*Self.FHeight*3) and $0000FF00) div $100;
    Result[36]:=((Self.FWidth*Self.FHeight*3) and $00FF0000) div $10000;
    Result[37]:=((Self.FWidth*Self.FHeight*3) and $FF000000) div $1000000;
  end;



function TOniImage.LoadFromBMP(filename:String):Boolean;
  var
    filestream:TFileStream;
    tempd:Tdata;

    x,y:LongWord;
  begin
    filestream:=TFileStream.Create(filename, fmOpenRead);
    SetLength(tempd,filestream.Size);
    filestream.Read(tempd[0],filestream.Size);
    filestream.Free;

    if not((tempd[00]=$42) and (tempd[01]=$4D)) then begin
      Result:=False;
      ShowMessage('Not a standard 24bit bitmap');
      Exit;
    end;
    if not(tempd[10]=54) then begin
      Result:=False;
      ShowMessage('Imagedata has to start at 0x54');
      Exit;
    end;
    if not(tempd[14]=40) then begin
      Result:=False;
      ShowMessage('Second bitmap header has to have 40 bytes');
      Exit;
    end;
    if not(tempd[28]=24) then begin
      Result:=False;
      ShowMessage('Bitmap has to have 24bits');
      Exit;
    end;
    if not(tempd[30]=0) then begin
      Result:=False;
      ShowMessage('Bitmap has to be uncompressed');
      Exit;
    end;

    Self.FWidth :=tempd[18]+tempd[19]*256+tempd[20]*256*256+tempd[21]*256*256*256;
    Self.FHeight:=tempd[22]+tempd[23]*256+tempd[24]*256*256+tempd[25]*256*256*256;
    Self.FDepth:=32;
    Self.FStoreType:=8;

    SetLength(Self.FData, Self.FWidth * Self.FHeight * Self.FDepth div 8);
    for y:=0 to Self.FHeight-1 do begin
      for x:=0 to Self.FWidth-1 do begin
        Self.FData[((Self.FWidth*y+x)*4)+0]:=tempd[54+(Self.FWidth*y+x)*3+0];
        Self.FData[((Self.FWidth*y+x)*4)+1]:=tempd[54+(Self.FWidth*y+x)*3+1];
        Self.FData[((Self.FWidth*y+x)*4)+2]:=tempd[54+(Self.FWidth*y+x)*3+2];
        Self.FData[((Self.FWidth*y+x)*4)+3]:=0;
      end;
    end;

    Self.FDataType:=[DT_Decoded32];
  end;



function TOniImage.WriteToBMP(filename:String):Boolean;
  var
    filestream:TFileStream;
    tempd:Tdata;
  begin
    tempd:=Self.GetAsBMP;
    filestream:=TFileStream.Create(filename,fmCreate);
    filestream.Write(tempd[0],Length(tempd));
    filestream.Free;
  end;



function TOniImage.GetMipMappedImage(var faded:Tdata):Boolean;
  var
    i:LongWord;
    x,y:Word;
    fadelvldata:Tdata;
    revert:Boolean;
  begin
    Result:=False;

//    if not (DT_Decoded32 in Self.FDataType) then
//      Self.DecodeImage;
    if not (DT_OniReverted in Self.FDataType) then begin
      revert:=True;
      Self.RevertImage;
    end else revert:=False;

    x:=Self.FWidth;
    y:=Self.FHeight;
    SetLength(faded,x*y*Self.FDepth div 8);
    SetLength(fadelvldata,x*y*Self.FDepth div 8);
    for i:=0 to Length(faded)-1 do begin
      faded[i]:=Self.FData[i];
      fadelvldata[i]:=Self.FData[i];
    end;
    repeat
      fadelvldata:=Self.ResizeImage(x,y,fadelvldata);
      x:=x div 2;
      y:=y div 2;
      SetLength(faded,Length(faded)+x*y*Self.FDepth div 8);
      for i:=0 to Length(fadelvldata)-1 do
        faded[Length(faded)-x*y*Self.FDepth div 8+i]:=fadelvldata[i];
    until (x=1) or (y=1) or ((x mod 2)=1) or ((y mod 2)=1);
    if (x>1) and (y>1) then Exit;
    Result:=True;

    if revert then
      Self.RevertImage;
  end;


end.
