{
  $Id: ImagingExport.pas,v 1.7 2005/06/22 13:53:21 galfar Exp $
  Vampyre Imaging Library
  by Marek Mauder (pentar@seznam.cz)
  http://imaginglib.sourceforge.net

  The contents of this file are used with permission, subject to the Mozilla
  Public License Version 1.1 (the "License"); you may not use this file except
  in compliance with the License. You may obtain a copy of the License at
  http://www.mozilla.org/MPL/MPL-1.1.html

  Software distributed under the License is distributed on an "AS IS" basis,
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
  the specific language governing rights and limitations under the License.

  Alternatively, the contents of this file may be used under the terms of the
  GNU Lesser General Public License (the  "LGPL License"), in which case the
  provisions of the LGPL License are applicable instead of those above.
  If you wish to allow use of your version of this file only under the terms
  of the LGPL License and not to allow others to use your version of this file
  under the MPL, indicate your decision by deleting  the provisions above and
  replace  them with the notice and other provisions required by the LGPL
  License.  If you do not delete the provisions above, a recipient may use
  your version of this file under either the MPL or the LGPL License.

  For more information about the LGPL: http://www.gnu.org/copyleft/lesser.html
}

{ This function contains functions exported from Imaging dynamic link library.
  All string are exported as PChars and all var parameters are exported
  as pointers. All posible exceptions getting out of dll are catched.}
unit ImagingExport;

{$I ImagingOptions.inc}

interface

uses
  ImagingTypes, Imaging;

{ Returns version of Imaging library. }
procedure ImGetVersion(Major: PLongInt; Minor: PLongInt); cdecl;
{ Look at InitImage for details.}
function ImInitImage(Image: PImageData): Boolean; cdecl;
{ Look at NewImage for details.}
function ImNewImage(Width, Height: LongInt; Format: TImageFormat;
  Image: PImageData): Boolean; cdecl;
{ Look at TestImage for details.}
function ImTestImage(Image: PImageData): Boolean; cdecl;
{ Look at FreeImage for details.}
function ImFreeImage(Image: PImageData): Boolean; cdecl;
{ Look at DetermineFileFormat for details.}
function ImDetermineFileFormat(FileName, Ext: PChar): Boolean; cdecl;
{ Look at DetermineMemoryFormat for details.}
function ImDetermineMemoryFormat(Data: Pointer; Size: LongInt; Ext: PChar): Boolean; cdecl;

{ Inits image list. }
function ImInitImageList(Size: LongInt; ImageList: PImageDataList): Boolean; cdecl;
{ Returns size of image list. }
function ImGetImageListSize(ImageList: PImageDataList): LongInt; cdecl;
{ Returns image list's element at given index. Output image is not cloned. }
function ImGetImageListElement(ImageList: PImageDataList; Index: LongInt;
  OutImage: PImageData): Boolean; cdecl;
{ Sets size of image list. }
function ImSetImageListSize(ImageList: PImageDataList; NewSize: LongInt): Boolean; cdecl;
{ Sets image list element at given index. Input image is not cloned.}
function ImSetImageListElement(ImageList: PImageDataList; Index: LongInt;
  InImage: PImageData): Boolean; cdecl;
{ Returns True if all images in list pass ImTestImage test. }
function ImTestImagesInList(ImageList: PImageDataList): Boolean; cdecl;
{ Frees image list and all images in it.}
function ImFreeImageList(ImageList: PImageDataList): Boolean; cdecl;
{ Frees image list and without freeing images in it.}
function ImFreeImageListKeepImages(ImageList: PImageDataList): Boolean; cdecl;

{ Look at LoadImageFromFile for details.}
function ImLoadImageFromFile(FileName: PChar; Image: PImageData): Boolean; cdecl;
{ Look at LoadImageFromMemory for details.}
function ImLoadImageFromMemory(Ext: PChar; Data: Pointer; Size: LongInt;
  Image: PImageData): Boolean; cdecl;
{ Look at LoadMultiImageFromFile for details.}
function ImLoadMultiImageFromFile(FileName: PChar; ImageList: PImageDataList): Boolean; cdecl;
{ Look at LoadMultiImageFromMemory for details.}
function ImLoadMultiImageFromMemory(Ext: PChar; Data: Pointer; Size: LongInt;
  ImageList: PImageDataList): Boolean; cdecl;

{ Look at SaveImageToFile for details.}
function ImSaveImageToFile(FileName: PChar; Image: PImageData): Boolean; cdecl;
{ Look at SaveImageToMemory for details.}
function ImSaveImageToMemory(Ext: PChar; Data: Pointer; Size: PLongInt;
  Image: PImageData): Boolean; cdecl;
{ Look at SaveMultiImageToFile for details.}
function ImSaveMultiImageToFile(FileName: PChar; ImageList: PImageDataList): Boolean; cdecl;
{ Look at SaveMultiImageToMemory for details.}
function ImSaveMultiImageToMemory(Ext: PChar; Data: Pointer; Size: PLongInt;
  ImageList: PImageDataList): Boolean; cdecl;

{ Look at CloneImage for details.}
function ImCloneImage(Image: PImageData; Clone: PImageData): Boolean; cdecl;
{ Look at ConvertImage for details.}
function ImConvertImage(Image: PImageData; DestFormat: TImageFormat): Boolean; cdecl;
{ Look at FlipImage for details.}
function ImFlipImage(Image: PImageData): Boolean; cdecl;
{ Look at MirrorImage for details.}
function ImMirrorImage(Image: PImageData): Boolean; cdecl;
{ Look at ResizeImage for details.}
function ImResizeImage(Image: PImageData; NewWidth, NewHeight: LongInt): Boolean; cdecl;
{ Look at SwapChannels for details.}
function ImSwapChannels(Image: PImageData; SrcChannel, DstChannel: LongInt): Boolean; cdecl;
{ Look at ReduceColors for details.}
function ImReduceColors(Image: PImageData; MaxColors: LongInt): Boolean; cdecl;
{ Look at GenerateMipMaps for details.}
function ImGenerateMipMaps(Image: PImageData; Levels: LongInt;
  MipMaps: PImageDataList): Boolean; cdecl;
{ Look at CopyRect for details.}
function ImCopyRect(SrcImage: PImageData; DstImage: PImageData;
  SrcX, SrcY, Width, Height, DstX, DstY: LongInt): Boolean; cdecl;
{ Look at MapImageToPalette for details.}
function ImMapImageToPalette(Image: PImageData; Pal: PPalette32;
  Entries: LongInt): Boolean; cdecl;
{ Look at FillRect for details.}
function ImFillRect(Image: PImageData; X, Y, Width, Height: LongInt;
  Fill: Pointer): Boolean; cdecl;
{ Look at SplitImage for details.}
function ImSplitImage(Image: PImageData; Chunks: PImageDataList;
  ChunkWidth, ChunkHeight: LongInt; XChunks, YChunks: PLongInt;
  PreserveSize: Boolean; Fill: Pointer): Boolean; cdecl;
{ Look at MakePaletteForImages for details.}
function ImMakePaletteForImages(Images: PImageDataList; Pal: PPalette32;
  MaxColors: LongInt; ConvertImages: Boolean): Boolean; cdecl;

{ Look at NewPalette for details.}
function ImNewPalette(Entries: LongInt; Pal: PPPalette32): Boolean; cdecl;
{ Look at FreePalette for details.}
function ImFreePalette(Pal: PPPalette32): Boolean; cdecl;
{ Look at CopyPalette for details.}
function ImCopyPalette(SrcPal, DstPal: PPalette32; SrcIdx, DstIdx, Count: LongInt): Boolean; cdecl;
{ Look at FindColor for details.}
function ImFindColor(Pal: PPalette32; Entries: LongInt; Color: TColor32): LongInt; cdecl;
{ Look at FillGrayscalePalette for details.}
function ImFillGrayscalePalette(Pal: PPalette32; Entries: LongInt): Boolean; cdecl;
{ Look at FillCustomPalette for details.}
function ImFillCustomPalette(Pal: PPalette32; Entries: LongInt; RBits, GBits,
  BBits: Byte; Alpha: Byte): Boolean; cdecl;
{ Look at SwapChannelsOfPalette for details.}
function ImSwapChannelsOfPalette(Pal: PPalette32; Entries, SrcChannel,
  DstChannel: LongInt): Boolean; cdecl;

{ Look at SetOption for details.}
function ImSetOption(OptionId, Value: LongInt): Boolean; cdecl;
{ Look at GetOption for details.}
function ImGetOption(OptionId: LongInt): LongInt; cdecl;
{ Look at PushOptions for details.}
function ImPushOptions: Boolean; cdecl;
{ Look at PopOptions for details.}
function ImPopOptions: Boolean; cdecl;

{ Look at GetPixelBytes for details.}
function ImGetPixelBytes(Format: TImageFormat): LongInt; cdecl;
{ Look at GetImageFormatInfo for details.}
function ImGetImageFormatInfo(Format: TImageFormat; Info: PImageFormatShortInfo): Boolean; cdecl;
{ Look at GetPixelsSize for details.}
function ImGetPixelsSize(Format: TImageFormat; Width, Height: LongInt): LongInt; cdecl;

{ Look at SetUserFileIO for details.}
procedure ImSetUserFileIO(OpenReadProc: TOpenReadProc; OpenWriteProc:
  TOpenWriteProc; CloseProc: TCloseProc; EofProc: TEofProc; SeekProc: TSeekProc;
  TellProc: TTellProc; ReadProc: TReadProc; WriteProc: TWriteProc); cdecl;
{ Look at ResetFileIO for details.}
procedure ImResetFileIO; cdecl;


{ These are only for documentation generation reasons.}
{ Loads Imaging functions from dll/so library.}
function ImLoadLibrary: Boolean;
{ Frees Imaging functions loaded from dll/so and releases library.}
function ImFreeLibrary: Boolean;

implementation

uses
  SysUtils, ImagingUtility;

function ImLoadLibrary: Boolean; begin Result := True; end;
function ImFreeLibrary: Boolean; begin Result := True; end;

type
  TInternalList = record
    List: TDynImageDataArray;
  end;
  PInternalList = ^TInternalList;

procedure ImGetVersion(Major: PLongInt; Minor: PLongInt);
begin
  try
    Major^ := ImagingVersionMajor;
    Minor^ := ImagingVersionMinor;
  except
  end;
end;

function ImInitImage(Image: PImageData): Boolean;
begin
  try
    Result := Imaging.InitImage(Image^);
  except
    Result := False;
  end;
end;

function ImNewImage(Width, Height: LongInt; Format: TImageFormat; Image:
  PImageData): Boolean;
begin
  try
    Result := Imaging.NewImage(Width, Height, Format, Image^);
  except
    Result := False;
  end;
end;

function ImTestImage(Image: PImageData): Boolean;
begin
  try
    Result := Imaging.TestImage(Image^);
  except
    Result := False;
  end;
end;

function ImFreeImage(Image: PImageData): Boolean;
begin
  try
    Result := Imaging.FreeImage(Image^);
  except
    Result := False;
  end;
end;

function ImDetermineFileFormat(FileName, Ext: PChar): Boolean;
var
  S: string;
begin
  try
    S := Imaging.DetermineFileFormat(FileName);
    Result := S <> '';
    StrCopy(Ext, PChar(S));
  except
    Result := False;
  end;
end;

function ImDetermineMemoryFormat(Data: Pointer; Size: LongInt; Ext: PChar): Boolean;
var
  S: string;
begin
  try
    S := Imaging.DetermineMemoryFormat(Data, Size);
    Result := S <> '';
    StrCopy(Ext, PChar(S));
  except
    Result := False;
  end;
end;

function ImInitImageList(Size: LongInt; ImageList: PImageDataList): Boolean;
var
  Int: PInternalList;
begin
  try
    try
      ImFreeImageList(ImageList);
    except
    end;
    New(Int);
    SetLength(Int.List, Size);
    ImageList^ := TImageDataList(Int);
    Result := True;
  except
    Result := False;
    ImageList^ := nil;
  end;
end;

function ImGetImageListSize(ImageList: PImageDataList): LongInt;
begin
  try
    Result := Length(PInternalList(ImageList^).List);
  except
    Result := -1;
  end;
end;

function ImGetImageListElement(ImageList: PImageDataList; Index: LongInt;
  OutImage: PImageData): Boolean;
begin
  try
    Index := ClampInt(Index, 0, Length(PInternalList(ImageList^).List) - 1);
    OutImage^ := PInternalList(ImageList^).List[Index];
    Result := True;
  except
    Result := False;
  end;
end;

function ImSetImageListSize(ImageList: PImageDataList; NewSize: LongInt):
  Boolean;
var
  I, OldSize: LongInt;
begin
  try
    OldSize := Length(PInternalList(ImageList^).List);
    if NewSize < OldSize then
      for I := NewSize to OldSize - 1 do
        Imaging.FreeImage(PInternalList(ImageList^).List[I]);
    SetLength(PInternalList(ImageList^).List, NewSize);
    Result := True;
  except
    Result := False;
  end;
end;

function ImSetImageListElement(ImageList: PImageDataList; Index: LongInt;
  InImage: PImageData): Boolean;
begin
  try
    Index := ClampInt(Index, 0, Length(PInternalList(ImageList^).List) - 1);
    PInternalList(ImageList^).List[Index] := InImage^;
    Result := True;
  except
    Result := False;
  end;
end;

function ImTestImagesInList(ImageList: PImageDataList): Boolean;
var
  I: LongInt;
  Arr: TDynImageDataArray;
begin
  Arr := nil;
  try
    Arr := PInternalList(ImageList).List;
    Result := True;
    for I := 0 to Length(Arr) - 1 do
    begin
      Result := Result and Imaging.TestImage(Arr[I]);
      if not Result then Break;
    end;
  except
    Result := False;
  end;
end;

function ImFreeImageList(ImageList: PImageDataList): Boolean;
var
  Int: PInternalList;
  I: LongInt;
begin
  try
    Int := PInternalList(ImageList^);
    for I := 0 to Length(Int.List) - 1 do
      Imaging.FreeImage(Int.List[I]);
    SetLength(Int.List, 0);
    Dispose(Int);
    Result := True;
  except
    Result := False;
  end;
end;

function ImFreeImageListKeepImages(ImageList: PImageDataList): Boolean;
var
  Int: PInternalList;
begin
  try
    Int := PInternalList(ImageList^);
    SetLength(Int.List, 0);
    Dispose(Int);
    Result := True;
  except
    Result := False;
  end;
end;

function ImLoadImageFromFile(FileName: PChar; Image: PImageData): Boolean;
begin
  try
    Result := Imaging.LoadImageFromFile(FileName, Image^);
  except
    Result := False;
  end;
end;

function ImLoadImageFromMemory(Ext: PChar; Data: Pointer; Size: LongInt; Image:
  PImageData): Boolean;
begin
  try
    Result := Imaging.LoadImageFromMemory(Ext, Data, Size, Image^);
  except
    Result := False;
  end;
end;

function ImLoadMultiImageFromFile(FileName: PChar; ImageList: PImageDataList):
  Boolean;
begin
  try
    ImInitImageList(0, ImageList);
    Result := Imaging.LoadMultiImageFromFile(FileName,
      PInternalList(ImageList^).List);
  except
    Result := False;
  end;
end;

function ImLoadMultiImageFromMemory(Ext: PChar; Data: Pointer; Size: LongInt;
  ImageList: PImageDataList): Boolean;
begin
  try
    ImInitImageList(0, ImageList);
    Result := Imaging.LoadMultiImageFromMemory(Ext, Data, Size,
      PInternalList(ImageList^).List);
  except
    Result := False;
  end;
end;

function ImSaveImageToFile(FileName: PChar; Image: PImageData): Boolean;
begin
  try
    Result := Imaging.SaveImageToFile(FileName, Image^);
  except
    Result := False;
  end;
end;

function ImSaveImageToMemory(Ext: PChar; Data: Pointer; Size: PLongInt;
  Image: PImageData): Boolean;
begin
  try
    Result := Imaging.SaveImageToMemory(Ext, Data, Size^, Image^);
  except
    Result := False;
  end;
end;

function ImSaveMultiImageToFile(FileName: PChar;
  ImageList: PImageDataList): Boolean;
begin
  try
    Result := Imaging.SaveMultiImageToFile(FileName,
      PInternalList(ImageList^).List);
  except
    Result := False;
  end;
end;

function ImSaveMultiImageToMemory(Ext: PChar; Data: Pointer; Size: PLongInt;
  ImageList: PImageDataList): Boolean;
begin
  try
    Result := Imaging.SaveMultiImageToMemory(Ext, Data, Size^,
      PInternalList(ImageList^).List);
  except
    Result := False;
  end;
end;

function ImCloneImage(Image: PImageData; Clone: PImageData): Boolean;
begin
  try
    Result := Imaging.CloneImage(Image^, Clone^);
  except
    Result := False;
  end;
end;

function ImConvertImage(Image: PImageData; DestFormat: TImageFormat): Boolean;
begin
  try
    Result := Imaging.ConvertImage(Image^, DestFormat);
  except
    Result := False;
  end;
end;

function ImFlipImage(Image: PImageData): Boolean;
begin
  try
    Result := Imaging.FlipImage(Image^);
  except
    Result := False;
  end;
end;

function ImMirrorImage(Image: PImageData): Boolean;
begin
  try
    Result := Imaging.MirrorImage(Image^);
  except
    Result := False;
  end;
end;

function ImResizeImage(Image: PImageData; NewWidth, NewHeight: LongInt):
  Boolean;
begin
  try
    Result := Imaging.ResizeImage(Image^, NewWidth, NewHeight);
  except
    Result := False;
  end;
end;

function ImSwapChannels(Image: PImageData; SrcChannel, DstChannel: LongInt):
  Boolean;
begin
  try
    Result := Imaging.SwapChannels(Image^, SrcChannel, DstChannel);
  except
    Result := False;
  end;
end;

function ImReduceColors(Image: PImageData; MaxColors: LongInt): Boolean;
begin
  try
    Result := Imaging.ReduceColors(Image^, MaxColors);
  except
    Result := False;
  end;
end;

function ImGenerateMipMaps(Image: PImageData; Levels: LongInt;
  MipMaps: PImageDataList): Boolean;
begin
  try
    ImInitImageList(0, MipMaps);
    Result := Imaging.GenerateMipMaps(Image^, Levels,
      PInternalList(MipMaps^).List);
  except
    Result := False;
  end;
end;

function ImCopyRect(SrcImage: PImageData; DstImage: PImageData;
  SrcX, SrcY, Width, Height, DstX, DstY: LongInt): Boolean;
begin
  try
    Result := Imaging.CopyRect(SrcImage^, DstImage^, SrcX, SrcY, Width,
      Height, DstX, DstY);
  except
    Result := False;
  end;
end;

function ImMapImageToPalette(Image: PImageData; Pal: PPalette32;
  Entries: LongInt): Boolean;
begin
  try
    Result := Imaging.MapImageToPalette(Image^, Pal, Entries);
  except
    Result := False;
  end;
end;

function ImFillRect(Image: PImageData; X, Y, Width, Height: LongInt;
  Fill: Pointer): Boolean;
begin
  try
    Result := Imaging.FillRect(Image^, X, Y, Width, Height, Fill);
  except
    Result := False;
  end;
end;

function ImSplitImage(Image: PImageData; Chunks: PImageDataList;
  ChunkWidth, ChunkHeight: LongInt; XChunks, YChunks: PLongInt;
  PreserveSize: Boolean; Fill: Pointer): Boolean;
begin
  try
    ImInitImageList(0, Chunks);
    Result := Imaging.SplitImage(Image^, PInternalList(Chunks^).List,
      ChunkWidth, ChunkHeight, XChunks^, YChunks^, PreserveSize, Fill);
  except
    Result := False;
  end;
end;

function ImMakePaletteForImages(Images: PImageDataList; Pal: PPalette32;
  MaxColors: LongInt; ConvertImages: Boolean): Boolean;
begin
  try
    Result := Imaging.MakePaletteForImages(PInternalList(Images^).List,
      Pal, MaxColors, ConvertImages);
  except
    Result := False;
  end;
end;

function ImNewPalette(Entries: LongInt; Pal: PPPalette32): Boolean;
begin
  try
    Result := Imaging.NewPalette(Entries, Pal^);
  except
    Result := False;
  end;
end;

function ImFreePalette(Pal: PPPalette32): Boolean;
begin
  try
    Result := Imaging.FreePalette(Pal^);
  except
    Result := False;
  end;
end;

function ImCopyPalette(SrcPal, DstPal: PPalette32; SrcIdx, DstIdx, Count: LongInt): Boolean;
begin
  try
    Result := Imaging.CopyPalette(SrcPal, DstPal, SrcIdx, DstIdx, Count);
  except
    Result := False;
  end;
end;

function ImFindColor(Pal: PPalette32; Entries: LongInt; Color: TColor32): LongInt;
begin
  try
    Result := Imaging.FindColor(Pal, Entries, Color);
  except
    Result := 0;
  end;
end;

function ImFillGrayscalePalette(Pal: PPalette32; Entries: LongInt): Boolean;
begin
  try
    Result := Imaging.FillGrayscalePalette(Pal, Entries);
  except
    Result := False;
  end;
end;

function ImFillCustomPalette(Pal: PPalette32; Entries: LongInt; RBits, GBits,
  BBits: Byte; Alpha: Byte): Boolean;
begin
  try
    Result := Imaging.FillCustomPalette(Pal, Entries, RBits, GBits, BBits,
      Alpha);
  except
    Result := False;
  end;
end;

function ImSwapChannelsOfPalette(Pal: PPalette32; Entries, SrcChannel,
  DstChannel: LongInt): Boolean;
begin
  try
    Result := Imaging.SwapChannelsOfPalette(Pal, Entries, SrcChannel, DstChannel);
  except
    Result := False;
  end;
end;

function ImSetOption(OptionId, Value: LongInt): Boolean;
begin
  try
    Result := Imaging.SetOption(OptionId, Value);
  except
    Result := False;
  end;
end;

function ImGetOption(OptionId: LongInt): LongInt;
begin
  try
    Result := GetOption(OptionId);
  except
    Result := InvalidOption;
  end;
end;

function ImPushOptions: Boolean;
begin
  try
    Result := Imaging.PushOptions;
  except
    Result := False;
  end;
end;

function ImPopOptions: Boolean;
begin
  try
    Result := Imaging.PopOptions;
  except
    Result := False;
  end;
end;

function ImGetPixelBytes(Format: TImageFormat): LongInt;
begin
  try
    Result := Imaging.GetPixelBytes(Format);
  except
    Result := 0;
  end;
end;

function ImGetImageFormatInfo(Format: TImageFormat; Info: PImageFormatShortInfo): Boolean;
begin
  try
    Result := Imaging.GetImageFormatInfo(Format, Info^);
  except
    Result := False;
  end;
end;

function ImGetPixelsSize(Format: TImageFormat; Width, Height: LongInt): LongInt;
begin
  try
    Result := Imaging.GetPixelsSize(Format, Width, Height);
  except
    Result := 0;
  end;
end;

procedure ImSetUserFileIO(OpenReadProc: TOpenReadProc; OpenWriteProc:
  TOpenWriteProc; CloseProc: TCloseProc; EofProc: TEofProc; SeekProc: TSeekProc;
  TellProc: TTellProc; ReadProc: TReadProc; WriteProc: TWriteProc);
begin
  try
    Imaging.SetUserFileIO(OpenReadProc, OpenWriteProc, CloseProc, EofProc,
      SeekProc, TellProc, ReadProc, WriteProc);
  except
  end;
end;

procedure ImResetFileIO;
begin
  try
    Imaging.ResetFileIO;
  except
  end;
end;

{
  Changes/Bug Fixes:
  
  -- TODOS ----------------------------------------------------
    - inspect lejks - possible list stuff, change list params

  -- 0.13 -----------------------------------------------------
    - added TestImagesInList function and new 0.13 functions
    - images were not freed when image list was resized in ImSetImageListSize
    - ImSaveMultiImageTo* recreated the input image list with size = 0

}
end.

