{
    This file is part of Chentrah,
    Copyright (C) 2004-2008 Anton Rzheshevski (chebmaster@mail.ru).

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see http://www.gnu.org/licenses/

 **********************************************************************

   This file contains the wrapper functions performing calls to the
   Vampyre Imaging library

 **********************************************************************}
 
 
procedure VyCheckFileNameLoad(n: widestring);
var
  e: widestring;
begin
  e:=UpperCase(ExtractFileExt(n));

  if (e='.XCF') or (e='.CGTX') or (e='.PSD') or (e='.MNG')
    then Die(
      'Неверная функция вызвана для открытия "%0".'#13#10'Многослойные текстуры в форматах .PSD, .XCF, .MNG и .CGTX не могут быть загружены как обычные изображения.',
      'A wrong function called to open "%0".'#13#10'The multi-layered textures in the .PSD, .XCF, .MNG and .CGTX formats cannot be opened as a simple images.'
      ,[n]);

  if not ((e='.JPG') or (e='.JPEG') or (e='.JP2')
    or (e='.GIF') or (e='.PNG')
    or (e='.TGA') or (e='.BMP') or (e='.JNG')
    or (e='.PCX') or (e='.PBM') or (e='.PGM') or (e='.PPM') or (e='.PAM') or (e='.PFM'))
    then Die(
      'Нельзя открыть "%0".'#13#10'CGE %1.%2 не поддерживает чтение изображений в этом формате.',
      'Unable to open "%0".'#13#10'CGE %1.%2 doesn''t support reading from this image format.'
      ,[n, VersionMajor, VersionMinor]);
end;

procedure VyCheckFileNameSave(n: widestring);
var
  e: widestring;
begin
  e:=UpperCase(ExtractFileExt(n));
  if not ((e='.JPG') or (e='.JPEG') or (e='.JP2') or (e='.PNG') or (e='.TGA') or (e='.BMP') or (e='.JNG')
    or (e='.PCX') or (e='.PBM') or (e='.PGM') or (e='.PPM') or (e='.PAM') or (e='.PFM'))
    then Die(
      'Нельзя записать "%0".'#13#10'CGE %1.%2 не поддерживает сохранение изображений в этом формате.',
      'Unable write "%0".'#13#10'CGE %1.%2 doesn''t support saving images in this format.'
      ,[n, VersionMajor, VersionMinor]);
end;


procedure VyCheckFileType(n: string; i: PImageData);
begin
  if not ((i^.Format = ifGray8) or (i^.Format = ifA8Gray8) or (i^.Format = ifR8G8B8) or (i^.Format = ifA8R8G8B8))
    then begin
      if MotherState.DebugMode then AddLog('Image "%0" has format "%1" supported by Vampyre Imaging but not supported by Chentrah. Converted to "ifA8R8G8B8".',
         [n, 'ord='+IntToStr(ord(i^.Format))//GetEnumName(typeinfo(TImageFormat), ord(i^.Format)) fpc2.4.0: Error: No type info available for this type
         ]);
      ConvertImage(i^, ifA8R8G8B8);
    end;

    {Die(
      'CGE %1.%2 не поддерживает формат пикселя "%3".'#13#10'Изображение "%0" не может быть прочитано.',
      'CGE %1.%2 does not support pixel format "%3".'#13#10'Image "%0" is none of the above.'
      ,[n, VersionMajor, VersionMinor, GetFormatName(i^.Format)]);}
end;

function GlFmtToVyFmt(i: GLenum): TImageFormat;
begin
  case i of
    GL_LUMINANCE : Result:=ifGray8;
    GL_LUMINANCE_ALPHA : Result:=ifA8Gray8;
    GL_RGB, GL_BGR : Result:=ifR8G8B8;
    GL_RGBA, GL_BGRA : Result:=ifA8R8G8B8;
  end;
end;

function GlFmtBytesPP(i: glUint): integer;
begin
  case i of
    GL_LUMINANCE : Result:=1;
    GL_LUMINANCE_ALPHA : Result:=2;
    GL_RGB, GL_BGR : Result:=3;
    GL_RGBA, GL_BGRA : Result:=4;
  else
    Result:=4;
  end;
end;

// ****************************************************


{function _LoadNewPic (FileName: PAnsiChar; phash: pResourceHash): pointer; cdecl;
begin
  try
  Result:=GetMem(SizeOf(TImageData));
  _GenHash(phash);
  ec;
  _LoadPic(FileName, Result);
  ec;
  LeaveGuardedSection
end;
}
function CreatePic (width, height: integer; format: glUint): pointer; cdecl;
begin
 try
  Result:=GetMem(SizeOf(TImageData));
  NewImage(width, height,GlFmtToVyFmt(format),TImageData(Result^));
 except
  ProcessGuardedException();
 end;
end;

function GetPicPixels (name: pointer): pointer; cdecl;
begin
 try
  Result:=TImageData(name^).Bits;
 except
  ProcessGuardedException();
 end;
end;

function GetPicWidth (name: pointer): integer; cdecl;
begin
 try
  Result:=TImageData(name^).Width;
 except
  ProcessGuardedException();
 end;
end;

function GetPicBytes (name: pointer): integer; cdecl;
begin
 try
  Result:=GetPicWidth(name)*GetPicHeight(name)*GlFmtBytesPP(GetPicFmt(name));
  CheckForGuardedException;
 except
  ProcessGuardedException();
 end;
end;


function GetPicHeight (name: pointer): integer; cdecl;
begin
 try
  Result:=TImageData(name^).Height;
 except
  ProcessGuardedException();
 end;
end;

procedure BgrToRgb(pixels: pbyte; numpixels: integer);
var
  b: byte;
  i: integer;
begin
  for i:=0 to numpixels - 1 do begin
    b:= (pixels + i*3)^;
    (pixels + i*3)^:= (pixels + i*3 + 2)^;
    (pixels + i*3 + 2)^:= b;
  end;
end;

procedure BgrAToRgbA(pixels: pbyte;  numpixels: integer);
var
  b: byte;
  i: integer;
begin
  for i:=0 to numpixels - 1 do begin
    b:= (pixels + i*4)^;
    (pixels + i*4)^:= (pixels + i*4 + 2)^;
    (pixels + i*4 + 2)^:= b;
  end;
end;


function LoadPic (FileName: PAnsiChar): pointer; cdecl;
//converts *everything* except RGBA to RGB
var
  n: WideString;
  i: PImageData;
begin
 try
  if FileName^ = '$' then Die(MI_ERROR_PROGRAMMER_NO_BAKA, ['LoadPic() for containers not implemented yet!']);
  n:=_UnmangleFileName(FileName);
  CheckForGuardedException;
  i:=GetMem(SizeOf(TImageData));
  VyCheckFileNameLoad(n);
  if not FileExists(n)
    then Die(MI_ERROR_FILE_NOT_FOUND, [n]);
  if not LoadImageFromFile(n, i^) //Vampyre call
    then Die(
     'Не удалось прочитать "%0".'#10#13'  Скорее всего, файл повреждён.',
     'Cannot  read file "%0".'#10#13'  It''s probaly corrupt.', [n]);
  VyCheckFileType(n, i);
  Result:=i;
 except
  ProcessGuardedException();
 end;
end;


function LoadPicFromMem (p: pointer; size: integer): pointer; cdecl;
//converts *everything* except RGBA to RGB
var
  n: WideString;
  i: PImageData;
begin
 try
  n:=IntToHex(cardinal(p), 8) + 'h';
  i:=GetMem(SizeOf(TImageData));
  if not Assigned(p)
    then Die(MI_ERROR_FILE_NOT_FOUND, [n]);
  if not LoadImageFromMemory(p, size, i^) //Vampyre call
    then Die(
     'Не удалось прочитать изображение из файла в памяти по адресу %0. (%1 байт)',
     'Failed to read image from the memory-mapped file at %0. (%1 bytes)', [p, size]);
  VyCheckFileType(n, i);
  Result:=i;
 except
  ProcessGuardedException();
 end;
end;


function LoadPicAs (FileName: PAnsiChar; format: GLenum): pointer; cdecl;
var
  n: WideString;
  i: PImageData;
begin
 try
  if FileName^ = '$' then Die(MI_ERROR_PROGRAMMER_NO_BAKA, ['LoadPicAs() for containers not implemented yet!']);
  n:=_UnmangleFileName(FileName);
  CheckForGuardedException;
  i:=GetMem(SizeOf(TImageData));
  VyCheckFileNameLoad(n);
  if not FileExists(n)
    then Die(MI_ERROR_FILE_NOT_FOUND, [n]);
  if not LoadImageFromFile(n, i^) //Vampyre call
    then Die(
     'Не удалось прочитать "%0".'#10#13'  Скорее всего, файл повреждён.',
     'Cannot  read file "%0".'#10#13'  It''s probaly corrupt.', [n]);
  if GetPicFmt(i) <> format
    then ConvertImage(i^, GlFmtToVyFmt(format));
  case format of
    GL_RGB: BgrToRgb(i^.Bits, i^.Width*i^.Height);
    GL_RGBA: BgraToRgba(i^.Bits, i^.Width*i^.Height);
  end;
  Result:=i;
 except
  ProcessGuardedException();
 end;
end;

function LoadPicFromMemAs (p: pointer; size: integer; format: GLenum): pointer; cdecl;
var
  n: WideString;
  i: PImageData;
begin
 try
  n:=IntToHex(cardinal(p), 8) + 'h';
  i:=GetMem(SizeOf(TImageData));
  if not Assigned(p)
    then Die(MI_ERROR_FILE_NOT_FOUND, [n]);
  if not LoadImageFromMemory(p, size, i^) //Vampyre call
    then Die(
     'Не удалось прочитать изображение из файла в памяти по адресу %0. (%1 байт)',
     'Failed to read image from the memory-mapped file at %0. (%1 bytes)', [p, size]);
  if GetPicFmt(i) <> format
    then ConvertImage(i^, GlFmtToVyFmt(format));
  case format of
    GL_RGB: BgrToRgb(i^.Bits, i^.Width*i^.Height);
    GL_RGBA: BgraToRgba(i^.Bits, i^.Width*i^.Height);
  end;
  Result:=i;
 except
  ProcessGuardedException();
 end;
end;



procedure SavePic (FileName: PAnsiChar; name: pointer); cdecl;
var
  n: AnsiString;
  i: PImageData;
begin
 try
  if FileName^ = '$' then Die(MI_ERROR_PROGRAMMER_NO_BAKA, ['SavePic() for containers not implemented yet!']);
  n:=CgePath(PCharToString(FileName));
  i:=name;
  VyCheckFileNamesave(n);
  SaveImageToFile(n, i^) //Vampyre call
 except
  ProcessGuardedException();
 end;
end;

procedure DeletePic (name: pointer); cdecl;
begin
 try
  FreeImage(PImageData(name)^);
  FreeMem(name);
 except
  ProcessGuardedException();
 end;
end;

procedure ResizePic (name: pointer; newwidth, newheight: integer); cdecl;
begin
 try
  ResizeImage //Vampyre call
    (PImageData(name)^, newwidth, newheight, CGE_RESIZE_FILTER);
 except
  ProcessGuardedException();
 end;
end;

function ClonePic (name1: pointer): pointer; cdecl;
begin
 try
  Result:=GetMem(SizeOf(TImageData));
  CloneImage(PImageData(name1)^, PImageData(Result)^);
 except
  ProcessGuardedException();
 end;
end;

procedure ResamplePic (name: pointer; newwidth, newheight: integer; wrap: boolean); cdecl;
var
  i: PImageData;
  i2: TImageData;
begin
 try
  i:=PImageData(name);
  NewImage(newwidth, newheight, i^.Format, i2);
  StretchResample(i^, 0, 0, i^.Width, i^.Height, i2, 0, 0, i2.Width, i2.Height,
    CGE_RESAMPLE_FILTER, wrap);
  FreeImage(i^);
  i^:=i2;
 except
  ProcessGuardedException();
 end;
end;

function CloneResamplePic (name1: pointer; newwidth, newheight: integer; wrap: boolean): pointer; cdecl;
var
  i1, i2: PImageData;
begin
 try
  i1:=PImageData(name1);
  Result:=GetMem(SizeOf(TImageData));
  i2:=PImageData(Result);
  NewImage(newwidth, newheight, i1^.Format, i2^);
  StretchResample(i1^, 0, 0, i1^.Width, i1^.Height,
                  i2^, 0, 0, i2^.Width, i2^.Height,
                  CGE_RESAMPLE_FILTER, wrap);
 except
  ProcessGuardedException();
 end;
end;


function GetPicFmt (name: pointer): glUint; cdecl;
begin
 try
  Case TImageData(name^).Format of
    ifGray8    : Result:=GL_LUMINANCE;
    ifA8Gray8  : Result:=GL_LUMINANCE_ALPHA;
    ifR8G8B8   : Result:=GL_BGR;//GL_RGB;
    ifA8R8G8B8 : Result:=GL_BGRA;//GL_RGBA;
  end;
 except
  ProcessGuardedException();
 end;
end;


