:Class netFreeImage ⍝ ⍝ Utility class for bitmap resizing, cropping, compression and format change using .Net. ⍝ It is using an open source project called FreeImage created by Floris van den Berg originally written in C++. ⍝ The project is maintained today by Hervé Drolon. The .Net wrapper is the work of Jean-Philippe Goerke and Carsten Klein. ⍝ ⍝ FreeImage supports: ⍝  Loading and saving of as many bitmap types as possible ⍝  Easy access to bitmap components, such as palettes, data bits and metadata ⍝  Converting bitmap’s bit depths from one to another ⍝  Accessing pages in a bitmap when there are multiple, such as in TIFF ⍝  Basic manipulation of bitmaps, such as rotation, flipping and resampling or point ⍝ operations such as brightness and contrast adjustment ⍝  Alpha compositing and alpha blending ⍝ ⍝ FreeImage does not support: ⍝  Advanced image processing operations such as convolution and transforms ⍝  Bitmap drawing ⍝  Vector graphics ⍝ ⍝ For this class to work you need to download the original dll in C++ (FreeImage.dll) and the .Net wrapper (FreeImageNET.dll) ⍝ and copy them both in the same directory as the dyalog.exe program. For commodity the version 3.17.04 can be downloaded from the Wiki page. ⍝ ⍝ Usefull links: ⍝ http://freeimage.sourceforge.net/index.html ⍝ Original project location ⍝ http://downloads.sourceforge.net/freeimage/FreeImage3170.pdf ⍝ Original project documentation ⍝ https://sourceforge.net/p/freeimage/discussion/ ⍝ Forum of original project ⍝ ⍝ https://freeimagenet.codeplex.com ⍝ FreeImage.NET wrapper project page ⍝ https://freeimagenet.codeplex.com/releases ⍝ Page to Download .NET wrapper ⍝ ⍝ http://paulbourke.net/dataformats/bitmaps/ ⍝ A Beginners Guide to Bitmaps ⍝ ⍝ ⍝ Original location of the Dyalog APL class: http://www.AplWiki/netFreeImage ⍝ Methods in FreeImage: ⍝ Section LoadAndSave *************************************************************************************************** ⍝ LoadFromFile ⍝ Get a FreeImageBitmap object from a file on disk. ⍝ LoadFromBase64 ⍝ Get a FreeImageBitmap object from a Base64 string. ⍝ LoadFromMemoryStream ⍝ Get a FreeImageBitmap object from a MemoryStream. ⍝ LoadFromBitmap ⍝ Get a FreeImageBitmap object from a System.Drawing.Bitmap (WindowsForms). ⍝ ⍝ SaveToFile ⍝ Save the loaded bitmap to a file on disk with default values (format conversion allowed). ⍝ SaveToBase64 ⍝ Save the loaded bitmap to a Base64 character vector with the current bitmap format. ⍝ SaveToMemoryStream ⍝ Save the loaded bitmap to a MemoryStream object with the specified bitmap format. ⍝ SaveToBitmap ⍝ Save the loaded bitmap to a System.Drawing.Bitmap (WindowsForms). ⍝ SaveToHtml ⍝ Save the loaded bitmap to an HTML inline image with the current bitmap format. ⍝ Dispose ⍝ Release all the resources. ⍝ Section BitmapOperation *********************************************************************************************** ⍝ AdjustBrightness ⍝ Adjusts the brightness of a 8-, 24- or 32-bit image by a certain amount. ⍝ AdjustColors ⍝ Adjusts an image's brightness, contrast, gamma and invert image in a single operation. ⍝ AdjustContrast ⍝ Adjusts the contrast of a 8-, 24- or 32-bit image by a certain amount. ⍝ AdjustGamma ⍝ Performs gamma correction on a 8-, 24- or 32-bit image. ⍝ ConvertFormat ⍝ Convert the format of the loaded bitmap to another bitmap format. ⍝ ConvertTo4Bits ⍝ Converts the loaded bitmap to 4 bits per pixel using the Xiaolin Wu color quantization algorithm ⍝ ConvertTo8Bits ⍝ Converts the loaded bitmap to 8 bits per pixel using the Xiaolin Wu color quantization algorithm ⍝ ConvertTo16Bits ⍝ Converts the loaded bitmap to 16 bits per pixel (RGB565). ⍝ ConvertTo24Bits ⍝ Converts the loaded bitmap to 24 bits per pixel. ⍝ ConvertTo32Bits ⍝ Converts the loaded bitmap to 32 bits per pixel. ⍝ ConvertToGreyscale ⍝ Converts the loaded bitmap to 256, 16 or 1 tone of grey. ⍝ ConvertToThumbnail ⍝ Converts the loaded bitmap to a thumbnail while keeping aspect ratio. ⍝ Crop ⍝ Crop the loaded bitmap. ⍝ FlipHorizontal ⍝ Flip horizontally the loaded bitmap. ⍝ FlipVertical ⍝ Flip vertically the loaded bitmap. ⍝ Invert ⍝ Invert the loaded bitmap. ⍝ Resize ⍝ Resize the loaded bitmap. ⍝ Rotate ⍝ Rotate the loaded bitmap. ⍝ JPEGCrop ⍝ Performs a lossless crop on a JPEG file. ⍝ JPEGTransform ⍝ Performs a lossless rotation or flipping on a JPEG file. ⍝ Section PixelAccess *************************************************************************************************** ⍝ GetPalette ⍝ Get the colors of the palette of loaded bitmap if existing. ⍝ GetPixelsColors ⍝ Get the RGB colors for all pixels of loaded bitmap. ⍝ GetSinglePixelColor ⍝ Get the RGB value of a single pixel of loaded bitmap. ⍝ Section Information *************************************************************************************************** ⍝ GetMetaData ⍝ Get a Key/Value pair for each MetaData of the loaded bitmap. ⍝ Info ⍝ Show information about the loaded bitmap. ⍝ SetComment ⍝ Sets the comment of the loaded bitmap. Supported formats are JPEG, PNG and GIF. ⍝ Show ⍝ Show the loaded bitmap in a WPF window. ⍝ ShowInWebBrowser ⍝ Show the loaded bitmap in WindowForm browser using 'SaveToHtml'. ⍝ Height ⍝ Height of the loaded bitmap in pixel. ⍝ Width ⍝ Width of the loaded bitmap in pixel. ⍝ *********************************************************************************************************************** ⍝ Version 1.0 April 2016 by Pierre Gilbert ⍝ System variables used: (⎕IO ⎕ML ⎕WX)←1 3 3 ⍝ Microsoft .NET Search Path: ⎕USING ← 'FreeImageAPI,FreeImageNET.dll' 'System.IO,mscorlib.dll' 'System,mscorlib.dll' 'System.Drawing,System.Drawing.dll' ⎕USING,← 'System.Windows.Media,WPF/PresentationCore.dll' 'System.Windows.Media.Imaging,WPF/PresentationCore.dll' ⎕USING,←⊂'System.Windows,WPF/PresentationFramework.dll' ⍝ Global variables: :Field Public FIB ← ⎕NULL ⍝ FreeImageBitmap object :Field Public MS ← ⎕NULL ⍝ MemoryStream object :Field Public LastFileName ← ⎕NULL ⍝ Last file name ⍝ Constructor: ∇ Init0 :Access Public :Implements Constructor ∇ :Section LoadAndSave ⍝ ************************************************************************* ∇ r←{options}LoadFromFile fileName;format :Access Public ⍝ Get a FreeImageBitmap object from a file on disk. ⍝ Tries to find the format of the file automatically. ⍝ The image is stored in memory outside the workspace. ⍝ Use the method 'SaveToFile' to save back to a file. ⍝ ⍝ Format supported: ⍝ Windows or OS/2 Bitmap File (*.BMP) ⍝ Windows Icon (*.ICO) ⍝ Independent JPEG Group (*.JPG, *.JIF, *.JPEG, *.JPE) ⍝ JPEG Network Graphics (*.JNG) ⍝ Commodore 64 Koala format (*.KOA) ⍝ Amiga IFF (*.IFF, *.LBM) ⍝ Amiga IFF (*.IFF, *.LBM) ⍝ Multiple Network Graphics (*.MNG) ⍝ Portable Bitmap (ASCII) (*.PBM) ⍝ Portable Bitmap (BINARY) (*.PBM) ⍝ Kodak PhotoCD (*.PCD) ⍝ Zsoft Paintbrush PCX bitmap format (*.PCX) ⍝ Portable Graymap (ASCII) (*.PGM) ⍝ Portable Graymap (BINARY) (*.PGM) ⍝ Portable Network Graphics (*.PNG) ⍝ Portable Pixelmap (ASCII) (*.PPM) ⍝ Portable Pixelmap (BINARY) (*.PPM) ⍝ Sun Rasterfile (*.RAS) ⍝ Truevision Targa files (*.TGA, *.TARGA) ⍝ Tagged Image File Format (*.TIF, *.TIFF) ⍝ Wireless Bitmap (*.WBMP) ⍝ Adobe Photoshop (*.PSD) ⍝ Dr. Halo (*.CUT) ⍝ X11 Bitmap Format (*.XBM) ⍝ X11 Pixmap Format (*.XPM) ⍝ DirectDraw Surface (*.DDS) ⍝ Graphics Interchange Format (*.GIF) ⍝ High Dynamic Range (*.HDR) ⍝ Raw Fax format CCITT G3 (*.G3) ⍝ Silicon Graphics SGI image format (*.SGI) ⍝ OpenEXR format (*.EXR) ⍝ JPEG-2000 format (*.J2K, *.J2C) ⍝ JPEG-2000 format (*.JP2) ⍝ Portable FloatMap (*.PFM) ⍝ Macintosh PICT (*.PICT) ⍝ RAW camera image (*.*) ⍝ Google WebP image format (*.webp) ⍝ JPEG XR image format (*.jxr) ⍝ ⍝ options available when loading Graphics Interchange Format (*.GIF) ⍝ options = 1 load the image as a 256 color image with unused palette entries, if it's 16 or 2 color ⍝ = 2 'Play' the GIF to generate each frame (as 32 bpp) instead of returning raw frame data when loading ⍝ ⍝ options available when loading Windows Icon (*.ICO) ⍝ options = 1 Convert to 32bpp and create an alpha channel from the AND-mask when loading ⍝ ⍝ options available when loading Independent JPEG Group (*.JPG, *.JIF, *.JPEG, *.JPE) ⍝ options = 1 load the file as fast as possible, sacrificing some quality (default) ⍝ = 2 load the file with the best quality, sacrificing some speed ⍝ = +4 load separated CMYK 'as is' (combine with other flags) ⍝ = 8 load and rotate according to Exif 'Orientation' tag if available ⍝ ⍝ options available when loading Kodak PhotoCD (*.PCD) ⍝ options = 1 load the bitmap sized 768 x 512 ⍝ = 2 load the bitmap sized 384 x 256 ⍝ = 3 load the bitmap sized 192 x 128 ⍝ ⍝ options available when loading Portable Network Graphics (*.PNG) ⍝ options = 1 avoid gammaa correction on loading ⍝ ⍝ options available when loading Truevision Targa files (*.TGA, *.TARGA) ⍝ options = 1 converts RGB555 and ARGB8888 to RGB888 ⍝ ⍝ options available when loading Tagged Image File Format (*.TIF, *.TIFF) ⍝ options = 1 load CMYK bitmaps as separated CMYK (default is conversin to RGB) ⍝ ⍝ options available when loading RAW camera image (*.*) ⍝ default is load the file as linear RGB 48-bit ⍝ options = 1 tries to load the JPEG preview image, embedded in Exif Metadata or ⍝ load the image as RGB 24-bit if no preview image is available ⍝ = 2 loads the image as RGB 24-bit ⍝ = 4 load as half-size color image ⍝ = 8 load as FIT_UINT16 raw Bayer image ⍝ ⍝ fileName = fully qualified file name with extension. ⍝ ⍝ r = 1 if successfull ⍝ = 0 'error message' if failure Dispose ⍝ Release any previous resources. LastFileName←fileName format←FREE_IMAGE_FORMAT.FIF_UNKNOWN :If 0=⎕NC'options' options←FREE_IMAGE_LOAD_FLAGS.DEFAULT :EndIf :Trap 0 FIB←⎕NEW FreeImageBitmap(fileName format options) r←1 :Else r←0 ⎕EXCEPTION.Message :EndTrap ∇ ∇ r←{options}SaveToFile fileName;format :Access Public ⍝ Save the loaded bitmap to a file on disk with default values or with options. ⍝ The bitmap can have a different extension then when it was loaded. ⍝ Checks whether the extension is valid for the file type and if the plugin can ⍝ use the colordepth of the bitmap. If not it will automatically convert ⍝ the bitmap into the next best colordepth and save it. ⍝ If the file already exists it is overwritten (except for .jpeg file ?). ⍝ See 'LoadFromFile' for the list of supported file format. ⍝ ⍝ Default values when saving: ⍝ OpenEXR format (*.EXR) = Save data as half with piz-based wavelet compression ⍝ JPEG-2000 format (*.J2K, *.J2C) = Save with a 16:1 rate ⍝ JPEG-2000 format (*.JP2) = Save with a 16:1 rate ⍝ Independent JPEG Group (*.JPG, *.JIF, *.JPEG, *.JPE) = Saves with good quality (75:1) and medium 2x2 chroma subsampling (4:2:0) ⍝ JPEG XR image format (*.jxr) = Save with quality 80 and no chroma subsampling (4:4:4) ⍝ Portable Network Graphics (*.PNG) = Save with ZLib level 6 compression and no interlacing ⍝ Portable Bitmap (ASCII) (*.PBM) = Save the bitmap as a binary file ⍝ Portable Graymap (ASCII) (*.PGM) = Save the bitmap as a binary file ⍝ Portable Pixelmap (ASCII) (*.PPM) = Save the bitmap as a binary file ⍝ Tagged Image File Format (*.TIF, *.TIFF) = Save using CCITT Group 4 fax encoding for 1-bit bitmaps and LZW compression for any other bitmaps ⍝ Truevision Targa files (*.TGA, *.TARGA) = Save without compression ⍝ Google WebP image format (*.webp) = Save with good quality (75:1) ⍝ ⍝ Options available when saving an Independent JPEG Group (*.JPG, *.JIF, *.JPEG, *.JPE) file: ⍝ options = 128 save with compression ratio 100:1 ⍝ = 256 save with compression ratio 75:1 (default) ⍝ = 512 save with compression ratio 50:1 ⍝ = 1024 save with compression ratio 25:1 ⍝ = 2048 save with compression ratio 10:1 ⍝ = or 0 to 100 for specific compression ratio ⍝ = 4096 save with high 4x1 chroma subsampling (4:1:1) ⍝ = 16384 save with medium 2x2 medium chroma (4:2:0) ⍝ = 32768 save with low 2x1 chroma subsampling (4:2:2) ⍝ = 65536 save with no chroma subsampling (4:4:4) ⍝ = + 8192 save as progressive JPEG (to combine with other options) ⍝ = + 131072 compute optimal Huffman coding (to combine with other options) ⍝ = + 262144 remove all metadata (to combine with other options) ⍝ ⍝ Suggested for web: options ← 256+8192+131072+262144 ⍝ ⍝ Options available when saving a Tagged Image File Format (*.TIF, *.TIFF) file: ⍝ options = + 1 Stores tags for separated CMYK (to combine with other options) ⍝ = 256 Save using PACKBITS compression. ⍝ = 512 Save using DEFLATE compression (a.k.a. ZLIB compression). ⍝ = 1024 Save using ADOBE DEFLATE compression. ⍝ = 2048 Save without any compression. ⍝ = 4096 Save using CCITT Group 3 fax encoding. ⍝ = 8192 Save using CCITT Group 4 fax encoding. ⍝ = 16384 Save using LZW compression (default). ⍝ = 32768 Save using JPEG compression. ⍝ ⍝ Options available when saving a Portable Network Graphics (*.PNG) file: ⍝ options = 1 Save using ZLib level 1 compression flag ⍝ = 6 Save using ZLib level 6 compression flag (default) ⍝ = 9 Save using ZLib level 9 compression flag ⍝ = 256 Save without ZLib compression. ⍝ = + 512 Save using Adam7 interlacing (to combine with other options) ⍝ ⍝ fileName = fully qualified file name with extension. ⍝ ⍝ r = 1 if successfull ⍝ = 0 'error message' if failure :If ⎕NULL≡FIB r←0 'SaveToFile: no bitmap loaded in memory !' →0 :EndIf format←FREE_IMAGE_FORMAT.FIF_UNKNOWN :If 0=⎕NC'options' options←FREE_IMAGE_SAVE_FLAGS.DEFAULT :EndIf :Trap 0 FIB.Save(fileName format options) r←1 :Else r←0 ⎕EXCEPTION.Message :EndTrap ∇ ∇ r←LoadFromMemoryStream ms :Access Public ⍝ Get a FreeImageBitmap object from a MemoryStream. ⍝ Finds the format of the MemoryStream automatically. ⍝ Note: You must keep the stream open for the lifetime of the FreeImageBitmap. ⍝ ⍝ ms = MemoryStream ⍝ ⍝ r = 1 if successfull ⍝ = 0 'error message' if failure Dispose ⍝ Release any previous resources. LastFileName←⎕NULL ⍝ To set the position to 0, otherwise it may not load. ms.Position←Convert.ToInt64 0 :Trap 0 FIB←⎕NEW FreeImageBitmap(ms) r←1 :Else r←0 ⎕EXCEPTION.Message :EndTrap ∇ ∇ ms←{options}SaveToMemoryStream format :Access Public ⍝ Save the loaded bitmap to a Base64 character vector with the specified bitmap format. ⍝ ⍝ Format supported: ⍝ ¯1 = Format of loaded bitmap ⍝ 0 = Windows or OS/2 Bitmap File (*.BMP) ⍝ 1 = Windows Icon (*.ICO) ⍝ 2 = Independent JPEG Group (*.JPG, *.JIF, *.JPEG, *.JPE) ⍝ 3 = JPEG Network Graphics (*.JNG) ⍝ 4 = Commodore 64 Koala format (*.KOA) ⍝ 5 = Amiga IFF (*.IFF, *.LBM) ⍝ 5 = Amiga IFF (*.IFF, *.LBM) ⍝ 6 = Multiple Network Graphics (*.MNG) ⍝ 7 = Portable Bitmap (ASCII) (*.PBM) ⍝ 8 = Portable Bitmap (BINARY) (*.PBM) ⍝ 9 = Kodak PhotoCD (*.PCD) ⍝ 10 = Zsoft Paintbrush PCX bitmap format (*.PCX) ⍝ 11 = Portable Graymap (ASCII) (*.PGM) ⍝ 12 = Portable Graymap (BINARY) (*.PGM) ⍝ 13 = Portable Network Graphics (*.PNG) ⍝ 14 = Portable Pixelmap (ASCII) (*.PPM) ⍝ 15 = Portable Pixelmap (BINARY) (*.PPM) ⍝ 16 = Sun Rasterfile (*.RAS) ⍝ 17 = Truevision Targa files (*.TGA, *.TARGA) ⍝ 18 = Tagged Image File Format (*.TIF, *.TIFF) ⍝ 19 = Wireless Bitmap (*.WBMP) ⍝ 20 = Adobe Photoshop (*.PSD) ⍝ 21 = Dr. Halo (*.CUT) ⍝ 22 = X11 Bitmap Format (*.XBM) ⍝ 23 = X11 Pixmap Format (*.XPM) ⍝ 24 = DirectDraw Surface (*.DDS) ⍝ 25 = Graphics Interchange Format (*.GIF) ⍝ 26 = High Dynamic Range (*.HDR) ⍝ 27 = Raw Fax format CCITT G3 (*.G3) ⍝ 28 = Silicon Graphics SGI image format (*.SGI) ⍝ 29 = OpenEXR format (*.EXR) ⍝ 30 = JPEG-2000 format (*.J2K, *.J2C) ⍝ 31 = JPEG-2000 format (*.JP2) ⍝ 32 = Portable FloatMap (*.PFM) ⍝ 33 = Macintosh PICT (*.PICT) ⍝ 34 = RAW camera image (*.*) ⍝ 35 = Google WebP image format (*.webp) ⍝ 36 = JPEG XR image format (*.jxr) ⍝ ⍝ Options available when saving an Independent JPEG Group (*.JPG, *.JIF, *.JPEG, *.JPE) file: ⍝ options = 128 save with compression ratio 100:1 ⍝ = 256 save with compression ratio 75:1 (default) ⍝ = 512 save with compression ratio 50:1 ⍝ = 1024 save with compression ratio 25:1 ⍝ = 2048 save with compression ratio 10:1 ⍝ = or 0 to 100 for specific compression ratio ⍝ = 4096 save with high 4x1 chroma subsampling (4:1:1) ⍝ = 16384 save with medium 2x2 medium chroma (4:2:0) ⍝ = 32768 save with low 2x1 chroma subsampling (4:2:2) ⍝ = 65536 save with no chroma subsampling (4:4:4) ⍝ = + 8192 save as progressive JPEG (to combine with other options) ⍝ = + 131072 compute optimal Huffman coding (to combine with other options) ⍝ = + 262144 remove all metadata (to combine with other options) ⍝ ⍝ Suggested for web: options ← 256+8192+131072+262144 ⍝ ⍝ Options available when saving a Tagged Image File Format (*.TIF, *.TIFF) file: ⍝ options = + 1 Stores tags for separated CMYK (to combine with other options) ⍝ = 256 Save using PACKBITS compression. ⍝ = 512 Save using DEFLATE compression (a.k.a. ZLIB compression). ⍝ = 1024 Save using ADOBE DEFLATE compression. ⍝ = 2048 Save without any compression. ⍝ = 4096 Save using CCITT Group 3 fax encoding. ⍝ = 8192 Save using CCITT Group 4 fax encoding. ⍝ = 16384 Save using LZW compression (default). ⍝ = 32768 Save using JPEG compression. ⍝ ⍝ Options available when saving a Portable Network Graphics (*.PNG) file: ⍝ options = 1 Save using ZLib level 1 compression flag ⍝ = 6 Save using ZLib level 6 compression flag (default) ⍝ = 9 Save using ZLib level 9 compression flag ⍝ = 256 Save without ZLib compression. ⍝ = + 512 Save using Adam7 interlacing (to combine with other options) ⍝ ⍝ You need to do the following to dispose of the MemoryStream after use: ⍝ ms.Close ⋄ ms.Dispose ⋄ ms←⎕NULL ⍝ ⍝ format = Format to use to save the memory stream. ⍝ ms = MemoryStream containing the bitmap if successfull ⍝ = ⎕NULL 'error message' if failure :If ⎕NULL≡FIB ms←⎕NULL'SaveToMemoryStream: no bitmap loaded in memory !' →0 :EndIf :If format=¯1 format←FIB.ImageFormat.value__ :EndIf :If 0=⎕NC'options' options←FREE_IMAGE_SAVE_FLAGS.DEFAULT :EndIf :Trap 0 ⍝ Create a new empty MemoryStream ms←⎕NEW MemoryStream ⍝ Save to the MemoryStream FIB.Save(ms format options) :Else ms←⎕NULL ⎕EXCEPTION.Message :EndTrap ∇ ∇ r←LoadFromBase64 base64String;imageBytes;ms :Access Public ⍝ Get a FreeImageBitmap object from a Base64 string. ⍝ Finds the format of the file automatically. ⍝ The image is stored in memory outside the workspace. ⍝ ⍝ base64String = Base64 character vector ⍝ ⍝ r = 1 if successfull ⍝ = 0 'error message' if failure Dispose ⍝ Release any previous resources. LastFileName←⎕NULL :Trap 0 ⍝ Convert Base64 String to byte[] imageBytes←Convert.FromBase64String(⊂base64String) ⍝ Create a new MemoryStream with the byte[] ms←⎕NEW MemoryStream(⊂imageBytes) ⍝ Create a FreeImageBitmap from the MemoryStream FIB←⎕NEW FreeImageBitmap(ms) r←1 :Else r←0 ⎕EXCEPTION.Message :EndTrap ∇ ∇ base64String←SaveToBase64;ms :Access Public ⍝ Save the loaded bitmap to a Base64 character vector with the current bitmap format. ⍝ ⍝ base64String = Base64 encoded bitmap as a character vector if successfull ⍝ = ⎕NULL 'error message' if failure :If ⎕NULL≡FIB base64String←⎕NULL'SaveToBase64: no bitmap loaded in memory !' →0 :EndIf :If ⎕NULL≠1↑ms←SaveToMemoryStream ¯1 ⍝ ¯1 = same format as loaded bitmap ⍝ Convert the MemoryStream to a Base64String base64String←Convert.ToBase64String(⊂ms.ToArray) ms.Close ⋄ ms.Dispose ⋄ ms←⎕NULL :Else base64String←ms :End ⍝ The following function can be used to create a 'BitmapImage' from a base64 string. ⍝ bmpimg←ImageFromBase64String base64String;imageBytes;MS;⎕USING ⍝ ⍝ Converts a Base64String to a System.Windows.Media.Imaging.BitmapImage. ⍝ ⍝ ⎕USING←'System.IO,mscorlib.dll' 'System,mscorlib.dll' 'System.Windows.Media.Imaging,WPF/PresentationCore.dll' ⍝ ⍝ ⍝ Convert Base64 String to byte[] as numbers. ⍝ imageBytes←Convert.FromBase64String(⊂base64String) ⍝ ⍝ ⍝ Create a new MemoryStream with the byte[] ⍝ MS←⎕NEW MemoryStream(⊂imageBytes) ⍝ ⍝ ⍝ Create a BitmapImage Object from the Memory Stream ⍝ bmpimg←⎕NEW BitmapImage ⍝ bmpimg.BeginInit ⍝ bmpimg.CacheOption←bmpimg.CacheOption.OnLoad ⍝ bmpimg.StreamSource←MS ⍝ bmpimg.EndInit ⍝ ⍝ ⍝ Erase the MemoryStream ⍝ MS.Close ⋄ MS.Dispose ⋄ MS←⎕NULL ∇ ∇ html←SaveToHtml;base64String;formatValue;imageHeight;imageWidth;ms :Access Public ⍝ Save the loaded bitmap to an HTML inline image with the current bitmap format. ⍝ Tries to find the most appropriate permitted format for HTML inline publishing. ⍝ The method .ShowInWebBrowser use this method to show the bitmap in a web browser. ⍝ ⍝ html = HTML inline image as character vector if successfull ⍝ = ⎕NULL 'error message' if failure :If ⎕NULL≡FIB html←⎕NULL'SaveToHtml: no bitmap loaded in memory !' →0 :EndIf (imageHeight imageWidth)←⍕¨FIB.(Height Width) formatValue←FIB.ImageFormat.value__ ⍝ Get the Base64String for a format supported by the html tag :If ~formatValue∊2 3 30 31 36 25 13 ⍝ 'JPEG JNG J2K JP2 JXR' 'GIF' 'PNG' formatValue←0 ⍝ BMP :EndIf :If ⎕NULL≠1↑ms←SaveToMemoryStream formatValue ⍝ Convert the MemoryStream to a Base64String base64String←Convert.ToBase64String(⊂ms.ToArray) ms.Close ⋄ ms.Dispose ⋄ ms←⎕NULL :Else html←ms →0 :End ⍝ Get the tag with the inline base64 encoded image :Select formatValue :CaseList 2 3 30 31 36 ⍝ 'JPEG JNG J2K JP2 JXR' html←'' :Case 25 ⍝'GIF' html←'' :Case 13 ⍝'PNG' html←'' :Else ⍝'BMP' html←'' :EndSelect ⍝ Add the tag html←'',html,'' ∇ ∇ Dispose :Access Public ⍝ Release all the resources. :Trap 0 FIB.Dispose ⋄ FIB←⎕NULL :EndTrap :Trap 0 MS.Close ⋄ MS.Dispose ⋄ MS←⎕NULL :EndTrap ∇ :EndSection :Section Information ⍝ ************************************************************************* ∇ Info;mData :Access Public ⍝ Show information about the loaded bitmap. :If ⎕NULL≢LastFileName 'File name: ',LastFileName :EndIf 'Size in memory (bytes): ',⍕FIB.DataSize 'Width (pixel): ',⍕FIB.Width 'Height (pixel): ',⍕FIB.Height 'Color depth (bits): ',⍕FIB.ColorDepth 'Image Type: ',⍕FIB.ImageType 'Image Format: ',⍕FIB.ImageFormat 'Frame count: ',⍕FIB.FrameCount 'Pixel Format: ',⍕FIB.PixelFormat 'X-axis dpi: ',⍕FIB.HorizontalResolution 'Y-axis dpi: ',⍕FIB.VerticalResolution :Trap 0 'Number of unique colors: ',⍕FIB.UniqueColors :Else 'Number of unique colors: Unknow' :EndTrap 'Has Palette: ',⍕FIB.HasPalette 'Number of palette colors: ',⍕FIB.ColorsUsed 'Color Type: ',⍕FIB.ColorType 'HasBackgroundColor: ',⍕FIB.HasBackgroundColor 'IsTransparent: ',⍕FIB.IsTransparent 'TransparencyCount: ',⍕FIB.TransparencyCount mData←FIB.Metadata mData.HideEmptyModels←1 :If 0=mData.List.Count 'Metadata Count: 0' :Else 'Metadata Count: ',⍕+/(⌷mData.List).Count :EndIf :Trap 0 'Comment: ',⍕FIB.Comment :Else 'Comment: ' :EndTrap ∇ ∇ mData←GetMetaData :Access Public ⍝ Get a Key/Value pair for each MetaData of the loaded bitmap. mData←FIB.Metadata mData.HideEmptyModels←1 :If 0=mData.List.Count mData←⎕NULL :Else mData←⊃,/{(⌷⍵).(Key ToString)}¨(⌷mData.List).List :End ∇ ∇ r←SetComment comment :Access Public ⍝ Sets the comment of the loaded bitmap. Supported formats are JPEG, PNG and GIF. ⍝ ⍝ r = 1 if successfull ⍝ = 0 if failure :Trap 0 FIB.Comment←comment r←1 :Else r←0 :EndTrap ∇ ∇ Show;bmpImg;img;ms;win :Access Public ⍝ Show the current loaded bitmap in a WPF window. :If ⎕NULL≡FIB ⎕←'Show: No bitmap loaded in memory !' →0 :End :If ⎕NULL=↑ms←SaveToMemoryStream 0 ⍝ 0 = BMP 'ShowImage: Not able to Show the Bitmap ',2⊃ms →0 :EndIf ⍝ Create a BitmapImage from the MemoryStream of the Bitmap bmpImg←⎕NEW BitmapImage bmpImg.BeginInit bmpImg.CacheOption←bmpImg.CacheOption.OnLoad bmpImg.StreamSource←ms bmpImg.EndInit ⍝ Dispose Of the BitmapImage's MemoryStream previously created. ms.Close ⋄ ms.Dispose ⋄ ms←⎕NULL ⍝ Create an Image with the BitmapImage img←⎕NEW Controls.Image img.Source←bmpImg img.(Width Height)←FIB.(Width Height) ⍝ Create a WPF window with the Image win←⎕NEW Window win.Content←img win.SizeToContent←win.SizeToContent.WidthAndHeight :If ⎕NULL≢LastFileName win.Title←' File name: ',LastFileName,' Pixel format: ',⍕FIB.PixelFormat :Else win.Title←' Pixel format: ',⍕FIB.PixelFormat :EndIf win.Show ∇ ∇ ShowInWebBrowser;frm;html;wb;⎕USING :Access Public ⍝ Show the current loaded bitmap in WindowForm browser. :If ⎕NULL≡FIB ⎕←'ShowInWebBrowser: No bitmap loaded in memory !' →0 :End :If ⎕NULL=1↑html←SaveToHtml 'ShowInWebBrowser error: ',2⊃html →0 :End ⎕USING←'System.Windows.Forms,System.Windows.Forms.dll' 'System.Drawing,System.Drawing.dll' wb←⎕NEW WebBrowser wb.DocumentText←html wb.Dock←wb.Dock.Fill frm←⎕NEW Form frm.Size←⎕NEW Size(65 70+FIB.Width FIB.Height) frm.Controls.Add(wb) :If ⎕NULL≢LastFileName frm.Text←⊂' File name: ',LastFileName,' Pixel format: ',⍕FIB.PixelFormat :Else frm.Text←⊂' Pixel format: ',⍕FIB.PixelFormat :EndIf {}frm.ShowDialog ⍬ wb.Dispose frm.Dispose ∇ ∇ r←Height :Access Public ⍝ Height of the loaded bitmap in pixel. r←FIB.Height ∇ ∇ r←Width :Access Public ⍝ Width of the loaded bitmap in pixel. r←FIB.Width ∇ :EndSection :Section PixelAccess ⍝ ************************************************************************* ∇ palette←GetPalette :Access Public ⍝ Get the colors of the palette of loaded bitmap if existing. ⍝ Equivalent to CMap in APL. ⍝ ⍝ palette = RGB color of the palette if existing ⍝ = ⎕NULL otherwise :If FIB.HasPalette palette←256⊥¨(⌷FIB.Palette).Color.(R G B) palette←(FIB.ColorsUsed)↑palette ⍝ palette←(⌷FIB.Palette).Color.(R G B) :Else palette←⎕NULL :EndIf ∇ ∇ colors←GetPixelsColors;lines;palette :Access Public ⍝ Get the RGB colors for all pixels of loaded bitmap. ⍝ If the bitmap is palettized it will return the index (origin 0) of the color in the palette. ⍝ In tha case you can do BMP.GetPalette[⎕IO+BMP.GetPixelsColors] to get the equivalent to 'CBits' ⍝ ⍝ colors = RGB color or index of color in palette lines←⌽⌷FIB.GetScanlines ⍝ Because FreeImage bitmaps are bottum up we need to do a ⌽ ⍝ ↓This line covers all the cases but is too slow. ⍝ colors←⊃{256⊥¨(⌷⍵).Color.(R G B)}¨lines ⍝ It is faster to use .ToByteArray and get the colors from the bytes. :Select FIB.ColorDepth :Case 1 ⍝ '[FreeImageAPI.FI1BIT]' ⍝ Number from 0 to 1 ⍝ Each number is made up of 1 bit. colors←⊃{,⍉(8⍴2)⊤⍵.ToByteArray}¨lines colors←(FIB.(Height Width))↑colors :Case 4 ⍝ '[FreeImageAPI.FI4BIT]' ⍝ Numbers from 0 to 15 ⍝ Each number is made up of 4 bits. colors←⊃{{2⊥¨((⍴⍵)⍴2 1 1 1)⊂⍵},⍉(8⍴2)⊤⍵.ToByteArray}¨lines colors←(FIB.(Height Width))↑colors :Case 8 ⍝ '[System.Byte]' ⍝ Numbers from 0 to 255 ⍝ Each number is made up of 8 bits. colors←⊃lines.ToByteArray :Case 16 ⍝ '[FreeImageAPI.FI16RGB555]' '[FreeImageAPI.FI16RGB565]' '[FreeImageAPI.FIRGB16]' :Select ⍕FIB.PixelFormat :Case 'Format16bppRgb565' ⍝ The 'FI16RGB565' structure describes a color consisting of relative ⍝ intensities of red, green, blue. R and B components consumes 31 bits ⍝ and G component consumes 6 bits. ⍝ (R × 31)÷255, (G × 63)÷255, (B × 31)÷255 colors←⊃{{{256⊥⌊31 63 31÷⍨255×2⊥¨((⍴⍵)⍴2 1 1 1 1 2 1 1 1 1 1 2 1 1 1 1)⊂⍵},⍉(8⍴2)⊤⌽⍵}¨{((⍴⍵)⍴2 1)⊂⍵}⍵.ToByteArray}¨lines :Case 'Format16bppRgb555' ⍝ The 'FI16RGB565' structure describes a color consisting of relative ⍝ intensities of red, green, blue. Each single color ⍝ component consumes 5 bits and so, takes values in the range from 0 to 31. ⍝ (R × 31)÷255, (G × 31)÷255, (B × 31)÷255 ⍝ The first bit is drop and the remaining 15 bits are used. colors←⊃{{{256⊥⌊31 31 31÷⍨255×2⊥¨((⍴⍵)⍴0 2 1 1 1 1 2 1 1 1 1 2 1 1 1 1)⊂⍵},⍉(8⍴2)⊤⌽⍵}¨{((⍴⍵)⍴2 1)⊂⍵}⍵.ToByteArray}¨lines :Else ⍝ The 'FIRGB16' structure describes a color consisting of relative ⍝ intensities of red, green, blue. Each single color ⍝ component consumes 16 bits and so, takes values in the range from 0 to 65535. colors←⊃{256⊥¨(⌷⍵).Color.(R G B)}¨lines :EndSelect :Case 24 ⍝ '[FreeImageAPI.RGBTRIPLE]' '[FreeImageAPI.FIRGBF]' ⍝ Each pixels has a 3 bytes (R G B) color structure. colors←⊃{{{256⊥⌽⍵}¨((⍴⍵)⍴2 1 1)⊂⍵}⍵.ToByteArray}¨lines ⍝ Equivalent to 'CBits' in APL :Case 32 ⍝ '[FreeImageAPI.RGBQUAD]' '[FreeImageAPI.FIRGBA16]' '[FreeImageAPI.FIRGBAF]' ⍝ Each pixels has a 4 bytes (R G B A) color structure. colors←⊃{{{256⊥⌽⍵}¨((⍴⍵)⍴2 1 1 0)⊂⍵}⍵.ToByteArray}¨lines ⍝ Equivalent to 'CBits' in APL :Else colors←⊃{256⊥¨(⌷⍵).Color.(R G B)}¨lines :EndSelect ⍝ Get each pixel color by indexing the palette when bitmap is palettized. :If FIB.HasPalette palette←256⊥¨(⌷FIB.Palette).Color.(R G B) colors←palette[⎕IO+colors] :EndIf ∇ ∇ color←GetSinglePixelColor(row col) :Access Public ⍝ Get the color value of a single pixel ⍝ If the bitmap has a palette it will return the color not the index of the color in the palette. ⍝ Note: (0 0) is the upper-left corner of the bitmap ⍝ ⍝ col = The x-coordinate of the pixel to retrieve (origin 0) ⍝ row = The y-coordinate of the pixel to retrieve (origin 0) ⍝ color = 256⊥R G B value if successfull ⍝ = ⎕NULL 'error message' if failure :Trap 0 row←¯1+FIB.Height-row ⍝ The rows are reverse in the FIB bitmap. color←FIB.GetPixel(col row) color←256⊥color.(R G B) :Else color←⎕NULL ⎕EXCEPTION.Message :EndTrap ∇ :EndSection :Section BitmapOperation ⍝ ************************************************************************* ∇ r←AdjustBrightness percentage :Access Public ⍝ Adjusts the brightness of a 8-, 24- or 32-bit image by a certain amount. ⍝ A value 0 means no change, less than 0 will make the image darker and greater than 0 will make the image brighter. ⍝ 'percentage' is a value between -100 and 100. ⍝ ⍝ r = 1 if successfull ⍝ = 0 if failure r←FIB.AdjustBrightness percentage ∇ ∇ r←AdjustColors(brightness contrast gamma invert) :Access Public ⍝ Adjusts an image's brightness, contrast and gamma as well as it may optionally invert the image within a single operation. ⍝ ⍝ brightness = A value 0 means no change, less than 0 will make the image darker and greater than 0 will make the image brighter. ⍝ contrast = A value 0 means no change, less than 0 will decrease the contrast and greater than 0 will increase the contrast of the image. ⍝ gamma = A value of 1.0 leaves the image alone, less than one darkens it, and greater than one lightens it. ⍝ invert = 1 = invert the image, 0 = do not invert the image. ⍝ Permitted range: ¯100 ≤ 'brightness' ≤ 100 , ¯100 ≤ 'contrast' ≤ 100, 'gamma' > 0 ⍝ ⍝ Note: It is faster to use this method than using AdjustBrightness, AdjustContrast, AdjustGamma and Invert separately. r←FIB.AdjustColors(brightness contrast gamma invert) ∇ ∇ r←AdjustContrast percentage :Access Public ⍝ Adjusts the contrast of a 8-, 24- or 32-bit image by a certain amount. ⍝ A value 0 means no change, less than 0 will decrease the contrast and greater than 0 will increase the contrast of the image. ⍝ 'percentage' is a value between -100 and 100. ⍝ ⍝ r = 1 if successfull ⍝ = 0 if failure r←FIB.AdjustContrast percentage ∇ ∇ r←AdjustGamma gamma :Access Public ⍝ Performs gamma correction on a 8-, 24- or 32-bit image. ⍝ The parameter represents the gamma value to use ('gamma' > 0). ⍝ A value of 1.0 leaves the image alone, less than one darkens it, and greater than one lightens it. ⍝ ⍝ r = 1 if successfull ⍝ = 0 if failure r←FIB.AdjustGamma gamma ∇ ∇ r←{options}ConvertFormat format;ms :Access Public ⍝ Convert the loaded bitmap to another bitmap format. ⍝ ⍝ Format supported: ⍝ 0 = Windows or OS/2 Bitmap File (*.BMP) ⍝ 1 = Windows Icon (*.ICO) ⍝ 2 = Independent JPEG Group (*.JPG, *.JIF, *.JPEG, *.JPE) ⍝ 3 = JPEG Network Graphics (*.JNG) ⍝ 4 = Commodore 64 Koala format (*.KOA) ⍝ 5 = Amiga IFF (*.IFF, *.LBM) ⍝ 5 = Amiga IFF (*.IFF, *.LBM) ⍝ 6 = Multiple Network Graphics (*.MNG) ⍝ 7 = Portable Bitmap (ASCII) (*.PBM) ⍝ 8 = Portable Bitmap (BINARY) (*.PBM) ⍝ 9 = Kodak PhotoCD (*.PCD) ⍝ 10 = Zsoft Paintbrush PCX bitmap format (*.PCX) ⍝ 11 = Portable Graymap (ASCII) (*.PGM) ⍝ 12 = Portable Graymap (BINARY) (*.PGM) ⍝ 13 = Portable Network Graphics (*.PNG) ⍝ 14 = Portable Pixelmap (ASCII) (*.PPM) ⍝ 15 = Portable Pixelmap (BINARY) (*.PPM) ⍝ 16 = Sun Rasterfile (*.RAS) ⍝ 17 = Truevision Targa files (*.TGA, *.TARGA) ⍝ 18 = Tagged Image File Format (*.TIF, *.TIFF) ⍝ 19 = Wireless Bitmap (*.WBMP) ⍝ 20 = Adobe Photoshop (*.PSD) ⍝ 21 = Dr. Halo (*.CUT) ⍝ 22 = X11 Bitmap Format (*.XBM) ⍝ 23 = X11 Pixmap Format (*.XPM) ⍝ 24 = DirectDraw Surface (*.DDS) ⍝ 25 = Graphics Interchange Format (*.GIF) ⍝ 26 = High Dynamic Range (*.HDR) ⍝ 27 = Raw Fax format CCITT G3 (*.G3) ⍝ 28 = Silicon Graphics SGI image format (*.SGI) ⍝ 29 = OpenEXR format (*.EXR) ⍝ 30 = JPEG-2000 format (*.J2K, *.J2C) ⍝ 31 = JPEG-2000 format (*.JP2) ⍝ 32 = Portable FloatMap (*.PFM) ⍝ 33 = Macintosh PICT (*.PICT) ⍝ 34 = RAW camera image (*.*) ⍝ 35 = Google WebP image format (*.webp) ⍝ 36 = JPEG XR image format (*.jxr) ⍝ ⍝ Options available when saving an Independent JPEG Group (*.JPG, *.JIF, *.JPEG, *.JPE) file: ⍝ options = 128 save with compression ratio 100:1 ⍝ = 256 save with compression ratio 75:1 (default) ⍝ = 512 save with compression ratio 50:1 ⍝ = 1024 save with compression ratio 25:1 ⍝ = 2048 save with compression ratio 10:1 ⍝ = or 0 to 100 for specific compression ratio ⍝ = 4096 save with high 4x1 chroma subsampling (4:1:1) ⍝ = 16384 save with medium 2x2 medium chroma (4:2:0) ⍝ = 32768 save with low 2x1 chroma subsampling (4:2:2) ⍝ = 65536 save with no chroma subsampling (4:4:4) ⍝ = + 8192 save as progressive JPEG (to combine with other options) ⍝ = + 131072 compute optimal Huffman coding (to combine with other options) ⍝ = + 262144 remove all metadata (to combine with other options) ⍝ ⍝ Suggested for web: options ← 256+8192+131072+262144 ⍝ ⍝ Options available when saving a Tagged Image File Format (*.TIF, *.TIFF) file: ⍝ options = + 1 Stores tags for separated CMYK (to combine with other options) ⍝ = 256 Save using PACKBITS compression. ⍝ = 512 Save using DEFLATE compression (a.k.a. ZLIB compression). ⍝ = 1024 Save using ADOBE DEFLATE compression. ⍝ = 2048 Save without any compression. ⍝ = 4096 Save using CCITT Group 3 fax encoding. ⍝ = 8192 Save using CCITT Group 4 fax encoding. ⍝ = 16384 Save using LZW compression (default). ⍝ = 32768 Save using JPEG compression. ⍝ ⍝ Options available when saving a Portable Network Graphics (*.PNG) file: ⍝ options = 1 Save using ZLib level 1 compression flag ⍝ = 6 Save using ZLib level 6 compression flag (default) ⍝ = 9 Save using ZLib level 9 compression flag ⍝ = 256 Save without ZLib compression. ⍝ = + 512 Save using Adam7 interlacing (to combine with other options) ⍝ ⍝ You need to do the following to dispose of the MemoryStream after use: ⍝ ms.Close ⋄ ms.Dispose ⋄ ms←⎕NULL ⍝ ⍝ format = Format to use to save the memory stream. ⍝ ms = MemoryStream containing the bitmap if successfull ⍝ = ⎕NULL 'error message' if failure :If format=¯1 format←FIB.ImageFormat.value__ :EndIf :If 0=⎕NC'options' options←FREE_IMAGE_SAVE_FLAGS.DEFAULT :EndIf :Trap 0 ⍝ Create a new empty MemoryStream ms←⎕NEW MemoryStream ⍝ Save to the MemoryStream FIB.Save(ms format options) :Else ms←⎕NULL ⎕EXCEPTION.Message :EndTrap ⍝ To set the position to 0, otherwise it may not load. ms.Position←Convert.ToInt64 0 FIB.Dispose ⋄ FIB←⎕NULL :Trap 0 FIB←⎕NEW FreeImageBitmap(ms) r←1 :Else r←0 ⎕EXCEPTION.Message :EndTrap ∇ ∇ r←ConvertTo4Bits :Access Public ⍝ Converts the loaded bitmap to 4 bits per pixel using the Xiaolin Wu color quantization algorithm ⍝ and the Floyd and Steinberg error diffusion. ⍝ r = 1 if successfull ⍝ = 0 if failure r←FIB.ConvertColorDepth(FREE_IMAGE_COLOR_DEPTH.FICD_04_BPP) ∇ ∇ r←ConvertTo8Bits :Access Public ⍝ Converts the loaded bitmap to 8 bits per pixel using the Xiaolin Wu color quantization algorithm ⍝ and the Floyd and Steinberg error diffusion. ⍝ ⍝ r = 1 if successfull ⍝ = 0 if failure r←FIB.ConvertColorDepth(FREE_IMAGE_COLOR_DEPTH.FICD_08_BPP) ∇ ∇ r←ConvertTo16Bits :Access Public ⍝ Converts the loaded bitmap to 16 bits per pixel (RGB565 → R=5 bits, G=6 bits, B=5 bits). ⍝ ⍝ r = 1 if successfull ⍝ = 0 if failure r←FIB.ConvertColorDepth(FREE_IMAGE_COLOR_DEPTH.FICD_16_BPP) ∇ ∇ r←ConvertTo24Bits :Access Public ⍝ Converts the loaded bitmap to 24 bits per pixel (R=8 bits, G=8 bits, B=8 bits). ⍝ ⍝ r = 1 if successfull ⍝ = 0 if failure r←FIB.ConvertColorDepth(FREE_IMAGE_COLOR_DEPTH.FICD_24_BPP) ∇ ∇ r←ConvertTo32Bits :Access Public ⍝ Converts the loaded bitmap to 32 bits per pixel (R=8 bits, G=8 bits, B=8 bits, Alpha=8 bits). ⍝ ⍝ r = 1 if successfull ⍝ = 0 if failure r←FIB.ConvertColorDepth(FREE_IMAGE_COLOR_DEPTH.FICD_32_BPP) ∇ ∇ r←ConvertToGreyscale tones :Access Public ⍝ Converts the loaded bitmap to 256, 16 or 1 tone of grey. ⍝ ⍝ tones = number of tones (256, 16 or 1) ⍝ ⍝ r = 1 if successfull ⍝ = 0 if failure :Select tones :Case 256 r←FIB.ConvertColorDepth(FREE_IMAGE_COLOR_DEPTH.FICD_08_BPP+FREE_IMAGE_COLOR_DEPTH.FICD_FORCE_GREYSCALE) ⍝ 256 tones of grey :Case 16 r←FIB.ConvertColorDepth(FREE_IMAGE_COLOR_DEPTH.FICD_04_BPP+FREE_IMAGE_COLOR_DEPTH.FICD_FORCE_GREYSCALE) ⍝ 16 tones of grey :Case 1 r←FIB.ConvertColorDepth(FREE_IMAGE_COLOR_DEPTH.FICD_01_BPP+FREE_IMAGE_COLOR_DEPTH.FICD_FORCE_GREYSCALE) ⍝ black or white pixel :Else r←0 'ConvertToGreyscale: Number of tones not supported' :EndSelect ∇ ∇ r←ConvertToThumbnail maxPixelSize;newFIB :Access Public ⍝ Converts the loaded bitmap to a thumbnail while keeping aspect ratio. ⍝ ⍝ maxPixelSize = maximum width or height of the thumbnail. ⍝ ⍝ r = 1 if successfull ⍝ = 0 'error message' if failure :Trap 0 newFIB←FIB.MakeThumbnail(maxPixelSize 1) ⍝ 1 = HDR images are transperantly converted to standard images FIB.Dispose ⋄ FIB←⎕NULL FIB←newFIB r←1 :Else r←0 ⎕EXCEPTION.Message :End ∇ ∇ r←Crop(x y width height);newFIB :Access Public ⍝ Crop the loaded bitmap. ⍝ ⍝ x = Specifies the x-coordinate of the upper-left corner of the cropped rectangle. ⍝ y = Specifies the y-coordinate of the upper-left corner of the cropped rectangle. ⍝ width = Specifies the width of the cropped rectangle. ⍝ height = Specifies the height of the cropped rectangle. ⍝ ⍝ r = 1 if successfull ⍝ = 0 if failure :Trap 0 newFIB←FIB.Copy(x y(x+width)(y+height)) FIB.Dispose ⋄ FIB←⎕NULL FIB←newFIB r←1 :Else r←0 ⎕EXCEPTION.Message :End ∇ ∇ r←FlipHorizontal :Access Public ⍝ FlipHorizontal the loaded bitmap. The following Flips/Rotate are also available: ⍝ ⍝ Rotate180FlipNone = Specifies a 180-degree clockwise rotation without flipping. ⍝ Rotate180FlipX = Specifies a 180-degree clockwise rotation followed by a horizontal flip. ⍝ Rotate180FlipXY = Specifies a 180-degree clockwise rotation followed by a horizontal and vertical flip. ⍝ Rotate180FlipY = Specifies a 180-degree clockwise rotation followed by a vertical flip. ⍝ Rotate270FlipNone = Specifies a 270-degree clockwise rotation without flipping. ⍝ Rotate270FlipX = Specifies a 270-degree clockwise rotation followed by a horizontal flip. ⍝ Rotate270FlipXY = Specifies a 270-degree clockwise rotation followed by a horizontal and vertical flip. ⍝ Rotate270FlipY = Specifies a 270-degree clockwise rotation followed by a vertical flip. ⍝ Rotate90FlipNone = Specifies a 90-degree clockwise rotation without flipping. ⍝ Rotate90FlipX = Specifies a 90-degree clockwise rotation followed by a horizontal flip. ⍝ Rotate90FlipXY = Specifies a 90-degree clockwise rotation followed by a horizontal and vertical flip. ⍝ Rotate90FlipY = Specifies a 90-degree clockwise rotation followed by a vertical flip. ⍝ RotateNoneFlipNone = Specifies no clockwise rotation and no flipping. ⍝ RotateNoneFlipX = Specifies no clockwise rotation followed by a horizontal flip. ⍝ RotateNoneFlipXY = Specifies no clockwise rotation followed by a horizontal and vertical flip. ⍝ RotateNoneFlipY = Specifies no clockwise rotation followed by a vertical flip. ⍝ ⍝ r = 1 if successfull ⍝ = 0 'error message' if failure :Trap 0 FIB.RotateFlip(RotateFlipType.RotateNoneFlipX) :Else r←0 ⎕EXCEPTION.Messag :EndTrap ∇ ∇ r←FlipVertical :Access Public ⍝ FlipVertical the loaded bitmap. ⍝ Note: See method FlipHorizontal for the list of alternative Flips/Rotate available. ⍝ ⍝ r = 1 if successfull ⍝ = 0 'error message' if failure :Trap 0 FIB.RotateFlip(RotateFlipType.RotateNoneFlipY) :Else r←0 ⎕EXCEPTION.Messag :EndTrap ∇ ∇ r←Invert :Access Public ⍝ Invert the loaded bitmap (255 - R, G or B value for each pixel). ⍝ ⍝ r = 1 if successfull ⍝ = 0 if failure r←FIB.Invert ∇ ∇ r←Resize(width height);size :Access Public ⍝ Resize the loaded bitmap. ⍝ The Resize will fail when the bitdepth cannot be handled or when ⍝ there’s not enough memory (this may happen with very large images). ⍝ See also the method .ConvertToThumbnail that will resize while keeping the aspect ratio. ⍝ ⍝ Images whose image type is FIT_BITMAP are returned as 8-bit or 24-bit, or as 32-bit if they ⍝ contain transparency. For example, 16-bit RGB bitmap are returned as 24-bit. Non ⍝ transparent palettized and 4-bit bitmap are returned as 24-bit images. The algorithm tries to ⍝ produce destination images with the smallest possible bit depth. ⍝ If you have transparency, you'll get a 32-bit image. If you have real colors, you'll get a 24-bit ⍝ image. For all other cases, you'll get an 8-bit image with a linear color palette. ⍝ ⍝ Resampling refers to changing the pixel dimensions (and therefore display size) of an image. ⍝ When you downsample (or decrease the number of pixels), information is deleted from the ⍝ image. When you upsample (or increase the number of pixels), new pixels are added based ⍝ on color values of existing pixels. You specify an interpolation filter to determine how pixels ⍝ are added or deleted. ⍝ ⍝ The resize image filter available are: ⍝ FILTER_BOX = Box, pulse, Fourier window, 1st order (constant) b-spline ⍝ FILTER_BICUBIC = Mitchell and Netravali's two-param cubic filter ⍝ FILTER_BILINEAR = Bilinear filter ⍝ FILTER_BSPLINE = 4th order (cubic) b-spline ⍝ FILTER_CATMULLROM = Catmull-Rom spline, Overhauser spline ⍝ FILTER_LANCZOS3 = Lanczos3 filter ⍝ ⍝ r = 1 if successfull ⍝ = 0 if failure size←⎕NEW Size(width height) r←FIB.Rescale(size FREE_IMAGE_FILTER.FILTER_CATMULLROM) ∇ ∇ r←Rotate angle :Access Public ⍝ Rotate the loaded bitmap. ⍝ This method rotates a 1-, 4-, 8-bit greyscale or a 24-, 32-bit color image by means of 3 shears. ⍝ For 1- and 4-bit images, rotation is limited to angles whose value is an integer multiple of 90. ⍝ ⍝ r = 1 if successfull ⍝ = 0 if failure r←FIB.Rotate(angle) ∇ ∇ r←JPEGCrop(srcFileName dstFileName x y width height) :Access Public ⍝ Performs a lossless crop on a JPEG file. ⍝ 'JPEGCrop' works by rearranging the compressed data (DCT coefficients), without ⍝ ever fully decoding the image. Therefore, the crop operation is lossless: there is no image ⍝ degradation at all, which would not be true if you used 'LoadFromFile' followed by ⍝ 'SaveToFile' to accomplish the same conversion. ⍝ ⍝ To perform this lossless operation, however, the width and height of the cropped rectangle ⍝ must be adjusted so that the image dimensions are a multiple of the iMCU size (usually 8 or ⍝ 16 pixels), because the function can only transform complete blocks of DCT coefficient data ⍝ in the desired way. That’s why the output width or height can be slightly greater than the ⍝ requested image size. ⍝ ⍝ srcFileName = source filename ⍝ dstFileName = destination filename (could be the same as srcFileName) ⍝ x = Specifies the x-coordinate of the upper-left corner of the cropped rectangle. ⍝ y = Specifies the y-coordinate of the upper-left corner of the cropped rectangle. ⍝ width = Specifies the width of the cropped rectangle. ⍝ height = Specifies the height of the cropped rectangle. ⍝ ⍝ r = 1 if successfull ⍝ = 0 if failure r←FIB.JPEGCrop(srcFileName dstFileName x y(x+width)(y+height)) ∇ ∇ r←JPEGTransform(srcFile dstFile operation) :Access Public ⍝ Performs a lossless rotation or flipping on a JPEG file. ⍝ ⍝ operation = operation to apply ⍝ = 'FLIP_H' is an horizontal flip ⍝ = 'FLIP_V' is a vertical flip ⍝ = 'ROTATE_180' is a 180 degree rotation ⍝ = 'ROTATE_270' is a 270 degree rotation (or 90 CCW) ⍝ = 'ROTATE_90' is a 90 degree clockwise rotation ⍝ = 'TRANSPOSE' is transpose across UL-to-LR axis ⍝ = 'TRANSVERSE' is transpose across UR-to-UL axis ⍝ srcFileName = source filename ⍝ dstFileName = destination filename (could be the same as srcFileName) ⍝ ⍝ r = 1 if successfull ⍝ = 0 if failure operation←⍎'FREE_IMAGE_JPEG_OPERATION.FIJPEG_OP_',operation r←FIB.JPEGTransform(srcFile dstFile operation 0) ∇ :EndSection :EndClass