37 using System.Collections;
38 using System.Collections.Generic;
40 using System.Drawing.Imaging;
42 using System.Reflection;
43 using System.Runtime.InteropServices;
44 using FreeImageAPI.IO;
45 using FreeImageAPI.Metadata;
47 namespace FreeImageAPI
53 public static partial class FreeImage
66 private static Dictionary<FIMULTIBITMAP, fi_handle> streamHandles =
67 new Dictionary<FIMULTIBITMAP, fi_handle>();
72 private static Version WrapperVersion;
74 private const int DIB_RGB_COLORS = 0;
75 private const int DIB_PAL_COLORS = 1;
76 private const int CBM_INIT = 0x4;
81 public const int BI_RGB = 0;
87 public const int BI_RLE8 = 1;
93 public const int BI_RLE4 = 2;
100 public const int BI_BITFIELDS = 3;
105 public const int BI_JPEG = 4;
110 public const int BI_PNG = 5;
114 #region General functions
120 public static Version GetWrapperVersion()
122 if (WrapperVersion == null)
126 object[] attributes = Assembly.GetAssembly(typeof(FreeImage))
127 .GetCustomAttributes(typeof(AssemblyFileVersionAttribute),
false);
128 if ((attributes != null) && (attributes.Length != 0))
130 AssemblyFileVersionAttribute attribute =
131 attributes[0] as AssemblyFileVersionAttribute;
132 if ((attribute != null) && (attribute.Version != null))
134 return (WrapperVersion =
new Version(attribute.Version));
143 WrapperVersion =
new Version();
146 return WrapperVersion;
153 public static Version GetNativeVersion()
155 return new Version(GetVersion());
173 public static bool IsAvailable()
178 Version nativeVersion =
new Version(GetVersion());
179 Version wrapperVersion = GetWrapperVersion();
182 (nativeVersion.Major > wrapperVersion.Major) ||
183 ((nativeVersion.Major == wrapperVersion.Major) && (nativeVersion.Minor > wrapperVersion.Minor)) ||
184 ((nativeVersion.Major == wrapperVersion.Major) && (nativeVersion.Minor == wrapperVersion.Minor) && (nativeVersion.Build >= wrapperVersion.Build));
186 catch (DllNotFoundException)
190 catch (EntryPointNotFoundException)
194 catch (BadImageFormatException)
202 #region Bitmap management functions
212 public static FIBITMAP Allocate(
int width,
int height,
int bpp)
214 return Allocate(width, height, bpp, 0, 0, 0);
226 public static FIBITMAP AllocateT(
FREE_IMAGE_TYPE type,
int width,
int height,
int bpp)
228 return AllocateT(type, width, height, bpp, 0, 0, 0);
285 public static FIBITMAP AllocateEx(
int width,
int height,
int bpp,
288 return AllocateEx(width, height, bpp, color, options, palette, 0, 0, 0);
351 public static FIBITMAP AllocateEx(
int width,
int height,
int bpp,
353 uint red_mask, uint green_mask, uint blue_mask)
355 if ((palette != null) && (bpp <= 8) && (palette.Length < (1 << bpp)))
360 GCHandle handle =
new GCHandle();
363 RGBQUAD[] buffer =
new RGBQUAD[] { color.Value };
364 handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
365 return AllocateEx(width, height, bpp, handle.AddrOfPinnedObject(),
366 options, palette, red_mask, green_mask, blue_mask);
370 if (handle.IsAllocated)
376 return AllocateEx(width, height, bpp, IntPtr.Zero,
377 options, palette, red_mask, green_mask, blue_mask);
439 public static FIBITMAP AllocateExT<T>(
FREE_IMAGE_TYPE type,
int width,
int height,
int bpp,
442 return AllocateExT(type, width, height, bpp, color, options, palette, 0, 0, 0);
509 public static FIBITMAP AllocateExT<T>(
FREE_IMAGE_TYPE type,
int width,
int height,
int bpp,
511 uint red_mask, uint green_mask, uint blue_mask) where T :
struct
513 if ((palette != null) && (bpp <= 8) && (palette.Length < (1 << bpp)))
518 if (!CheckColorType(type, color.Value))
519 return FIBITMAP.
Zero;
521 GCHandle handle =
new GCHandle();
524 T[] buffer =
new T[] { color.Value };
525 handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
526 return AllocateExT(type, width, height, bpp, handle.AddrOfPinnedObject(),
527 options, palette, red_mask, green_mask, blue_mask);
531 if (handle.IsAllocated)
537 return AllocateExT(type, width, height, bpp, IntPtr.Zero,
538 options, palette, red_mask, green_mask, blue_mask);
553 public static Bitmap GetBitmap(FIBITMAP dib)
555 return GetBitmap(dib,
true);
570 internal static Bitmap GetBitmap(FIBITMAP dib,
bool copyMetadata)
574 throw new ArgumentNullException(
"dib");
578 throw new ArgumentException(
"Only bitmaps with type of FIT_BITMAP can be converted.");
583 if ((format ==
PixelFormat.Undefined) && (GetBPP(dib) == 16u))
585 throw new ArgumentException(
"Only 16bit 555 and 565 are supported.");
588 int height = (int)GetHeight(dib);
589 int width = (int)GetWidth(dib);
590 int pitch = (int)GetPitch(dib);
592 Bitmap result =
new Bitmap(width, height, format);
595 data = result.LockBits(
new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly,
format);
597 ConvertToRawBits(data.Scan0, dib, pitch, GetBPP(dib),
598 GetRedMask(dib), GetGreenMask(dib), GetBlueMask(dib),
true);
600 result.UnlockBits(data);
602 if((GetResolutionX(dib) > 0) && (GetResolutionY(dib) > 0))
605 result.SetResolution(GetResolutionX(dib), GetResolutionY(dib));
608 if (GetPalette(dib) != IntPtr.Zero)
611 ColorPalette palette = result.Palette;
613 Color[] colorPalette =
new Palette(dib).ColorData;
615 int entriesToCopy = Math.Min(colorPalette.Length, palette.Entries.Length);
618 if (IsTransparent(dib))
620 byte[] transTable = GetTransparencyTableEx(dib);
622 int maxEntriesWithTrans = Math.Min(entriesToCopy, transTable.Length);
624 for (; i < maxEntriesWithTrans; i++)
626 palette.Entries[i] = Color.FromArgb(transTable[i], colorPalette[i]);
629 for (; i < entriesToCopy; i++)
631 palette.Entries[i] = Color.FromArgb(0xFF, colorPalette[i]);
636 for (
int i = 0; i < entriesToCopy; i++)
638 palette.Entries[i] = colorPalette[i];
643 result.Palette = palette;
650 List<PropertyItem> list =
new List<PropertyItem>();
657 mData = FindFirstMetadata(model, dib, out tag);
659 if (mData.IsNull)
continue;
662 PropertyItem propItem = CreatePropertyItem();
663 propItem.Len = (int)GetTagLength(tag);
664 propItem.Id = (int)GetTagID(tag);
665 propItem.Type = (short)GetTagType(tag);
666 byte[] buffer =
new byte[propItem.Len];
670 byte* src = (byte*)GetTagValue(tag);
671 fixed (byte* dst = buffer)
677 propItem.Value = buffer;
680 while (FindNextMetadata(mData, out tag));
681 FindCloseMetadata(mData);
683 foreach (PropertyItem propItem
in list)
685 result.SetPropertyItem(propItem);
706 public static FIBITMAP CreateFromBitmap(Bitmap bitmap)
708 return CreateFromBitmap(bitmap,
false);
723 internal static FIBITMAP CreateFromBitmap(Bitmap bitmap,
bool copyMetadata)
727 throw new ArgumentNullException(
"bitmap");
729 uint bpp, red_mask, green_mask, blue_mask;
731 if (!GetFormatParameters(bitmap.PixelFormat, out type, out bpp, out red_mask, out green_mask, out blue_mask))
733 throw new ArgumentException(
"The bitmaps pixelformat is invalid.");
737 BitmapData data = bitmap.LockBits(
740 FIBITMAP result = ConvertFromRawBits(
751 bitmap.UnlockBits(data);
753 if (GetPalette(result) != IntPtr.Zero)
755 Palette palette =
new Palette(result);
756 Color[] colors = bitmap.Palette.Entries;
758 int entriesToCopy = Math.Min(palette.Length, colors.Length);
759 byte[] transTable =
new byte[entriesToCopy];
760 for (
int i = 0; i < entriesToCopy; i++)
762 RGBQUAD color = (RGBQUAD)colors[i];
763 color.rgbReserved = 0x00;
765 transTable[i] = colors[i].A;
769 FreeImage.SetTransparencyTable(result, transTable);
808 public static unsafe FIBITMAP ConvertFromRawBits(
820 fixed (byte* ptr = bits)
822 return ConvertFromRawBits(
855 public static unsafe FIBITMAP ConvertFromRawBits(
867 byte* addr = (byte*)bits;
868 if ((addr == null) || (width <= 0) || (height <= 0))
873 FIBITMAP dib = AllocateT(type, width, height, (
int)bpp, red_mask, green_mask, blue_mask);
874 if (dib != FIBITMAP.Zero)
878 for (
int i = height - 1; i >= 0; --i)
880 CopyMemory((byte*)GetScanLine(dib, i), addr, (
int)GetLine(dib));
886 for (
int i = 0; i < height; ++i)
888 CopyMemory((byte*)GetScanLine(dib, i), addr, (
int)GetLine(dib));
906 public static bool SaveBitmap(Bitmap bitmap,
string filename)
948 public static bool SaveBitmap(
954 FIBITMAP dib = CreateFromBitmap(bitmap);
955 bool result = SaveEx(dib, filename, format, flags);
968 public static FIBITMAP LoadEx(
string filename)
986 return LoadEx(filename, flags, ref format);
1027 if (!
File.Exists(filename))
1029 throw new FileNotFoundException(filename +
" could not be found.");
1031 FIBITMAP dib =
new FIBITMAP();
1035 format = GetFileType(filename, 0);
1038 if (FIFSupportsReading(format))
1040 dib = Load(format, filename, flags);
1059 FIBITMAP dib = LoadEx(filename, flags, ref format);
1060 Bitmap result = GetBitmap(dib,
true);
1069 public static void UnloadEx(ref FIBITMAP dib)
1090 public static bool SaveEx(FIBITMAP dib,
string filename)
1116 public static bool SaveEx(
1144 public static bool SaveEx(
1172 public static bool SaveEx(
1202 public static bool SaveEx(
1234 public static bool SaveEx(
1266 public static bool SaveEx(
1310 public static bool SaveEx(
1320 throw new ArgumentNullException(
"dib");
1322 if (filename == null)
1324 throw new ArgumentNullException(
"filename");
1326 bool result =
false;
1330 format = GetFIFFromFilename(filename);
1335 if (FIFSupportsWriting(format) && FIFSupportsExportType(format, GetImageType(dib)))
1338 if (!IsFilenameValidForFIF(format, filename))
1340 string extension = GetPrimaryExtensionFromFIF(format);
1341 filename = Path.ChangeExtension(filename, extension);
1344 FIBITMAP dibToSave = PrepareBitmapColorDepth(dib, format, colorDepth);
1347 result =
Save(format, dibToSave, filename, flags);
1352 if (dibToSave != dib)
1354 UnloadEx(ref dibToSave);
1357 if (result && unloadSource)
1377 public static FIBITMAP LoadFromStream(
Stream stream)
1397 return LoadFromStream(stream, flags, ref format);
1436 public static FIBITMAP LoadFromStream(
1443 throw new ArgumentNullException(
"stream");
1445 if (!stream.CanRead)
1447 throw new ArgumentException(
"stream is not capable of reading.");
1450 stream = (stream.CanSeek) ? stream :
new StreamWrapper(stream,
true);
1452 stream.Position = 0
L;
1456 format = GetFileTypeFromStream(stream);
1458 stream.Position = 0
L;
1460 if (!FIFSupportsReading(format))
1469 return LoadFromHandle(format, ref io, handle, flags);
1485 public static bool SaveToStream(
1490 return SaveToStream(
1512 public static bool SaveToStream(
1518 return SaveToStream(
1540 public static bool SaveToStream(
1546 return SaveToStream(
1569 public static bool SaveToStream(
1576 return SaveToStream(
1602 public static bool SaveToStream(
1609 return SaveToStream(
1637 public static bool SaveToStream(
1647 throw new ArgumentNullException(
"dib");
1651 throw new ArgumentNullException(
"stream");
1653 if (!stream.CanWrite)
1655 throw new ArgumentException(
"stream is not capable of writing.");
1657 if ((!FIFSupportsWriting(format)) || (!FIFSupportsExportType(format, GetImageType(dib))))
1662 FIBITMAP dibToSave = PrepareBitmapColorDepth(dib, format, colorDepth);
1663 bool result =
false;
1672 result = SaveToHandle(format, dibToSave, ref io, handle, flags);
1678 if (dibToSave != dib)
1680 UnloadEx(ref dibToSave);
1683 if (result && unloadSource)
1694 #region Plugin functions
1704 public static bool IsExtensionValidForFIF(
FREE_IMAGE_FORMAT fif,
string extension)
1706 return IsExtensionValidForFIF(fif, extension, StringComparison.CurrentCultureIgnoreCase);
1718 public static bool IsExtensionValidForFIF(
FREE_IMAGE_FORMAT fif,
string extension, StringComparison comparisonType)
1720 if (extension == null)
1722 throw new ArgumentNullException(
"extension");
1724 bool result =
false;
1726 string tempList = GetFIFExtensionList(fif);
1727 if (tempList != null)
1729 string[] extensionList = tempList.Split(
',');
1730 foreach (
string ext
in extensionList)
1732 if (extension.Equals(ext, comparisonType))
1750 public static bool IsFilenameValidForFIF(
FREE_IMAGE_FORMAT fif,
string filename)
1752 return IsFilenameValidForFIF(fif, filename, StringComparison.CurrentCultureIgnoreCase);
1764 public static bool IsFilenameValidForFIF(
FREE_IMAGE_FORMAT fif,
string filename, StringComparison comparisonType)
1766 if (filename == null)
1768 throw new ArgumentNullException(
"filename");
1770 bool result =
false;
1772 string extension = Path.GetExtension(filename);
1773 if (extension.Length != 0)
1775 extension = extension.Remove(0, 1);
1776 result = IsExtensionValidForFIF(fif, extension, comparisonType);
1790 string result = null;
1791 string extensions = GetFIFExtensionList(fif);
1792 if (extensions != null)
1794 int position = extensions.IndexOf(
',');
1797 result = extensions;
1801 result = extensions.Substring(0, position);
1809 #region Multipage functions
1818 public static FIMULTIBITMAP OpenMultiBitmapEx(
string filename)
1821 return OpenMultiBitmapEx(
1838 public static FIMULTIBITMAP OpenMultiBitmapEx(
string filename,
bool keep_cache_in_memory)
1841 return OpenMultiBitmapEx(
1847 keep_cache_in_memory);
1859 public static FIMULTIBITMAP OpenMultiBitmapEx(
1862 bool keep_cache_in_memory)
1865 return OpenMultiBitmapEx(
1871 keep_cache_in_memory);
1884 public static FIMULTIBITMAP OpenMultiBitmapEx(
1888 bool keep_cache_in_memory)
1891 return OpenMultiBitmapEx(
1897 keep_cache_in_memory);
1916 public static FIMULTIBITMAP OpenMultiBitmapEx(
1921 bool keep_cache_in_memory)
1923 return OpenMultiBitmapEx(
1929 keep_cache_in_memory);
1950 public static FIMULTIBITMAP OpenMultiBitmapEx(
1956 bool keep_cache_in_memory)
1958 if (!
File.Exists(filename) && !create_new)
1960 throw new FileNotFoundException(filename +
" could not be found.");
1965 format = GetFileType(filename, 0);
1967 FIMULTIBITMAP dib =
new FIMULTIBITMAP();
1968 if (FIFSupportsReading(format))
1970 dib = OpenMultiBitmap(format, filename, create_new, read_only, keep_cache_in_memory, flags);
1980 public static FIMULTIBITMAP OpenMultiBitmapFromStream(
Stream stream)
2003 if (!stream.CanSeek)
2004 stream =
new StreamWrapper(stream,
true);
2014 format = GetFileTypeFromHandle(ref io, handle, checked((
int)stream.Length));
2017 mdib = OpenMultiBitmapFromHandle(format, ref io, handle, flags);
2025 lock (streamHandles)
2027 streamHandles.Add(mdib, handle);
2053 if (CloseMultiBitmap_(bitmap, flags))
2056 lock (streamHandles)
2058 if (streamHandles.TryGetValue(bitmap, out handle))
2060 streamHandles.Remove(bitmap);
2076 public static bool CloseMultiBitmapEx(ref FIMULTIBITMAP bitmap)
2091 bool result =
false;
2094 if (CloseMultiBitmap(bitmap, flags))
2110 public static int GetLockedPageCount(FIMULTIBITMAP dib)
2114 throw new ArgumentNullException(
"dib");
2117 GetLockedPageNumbers(dib, null, ref result);
2128 public static int[] GetLockedPages(FIMULTIBITMAP dib)
2132 throw new ArgumentNullException(
"dib");
2136 int[] result = null;
2138 if (GetLockedPageNumbers(dib, result, ref count))
2140 result =
new int[
count];
2142 if (!GetLockedPageNumbers(dib, result, ref count))
2168 public static FIMULTIBITMAP LoadMultiBitmapFromStream(
2172 out FIMEMORY memory)
2176 throw new ArgumentNullException(
"stream");
2178 if (!stream.CanRead)
2180 throw new ArgumentException(
"stream");
2182 const int blockSize = 1024;
2184 byte[] buffer =
new byte[blockSize];
2186 stream = stream.CanSeek ? stream :
new StreamWrapper(stream,
true);
2187 memory = OpenMemory(IntPtr.Zero, 0);
2191 bytesRead = stream.Read(buffer, 0, blockSize);
2192 WriteMemory(buffer, (uint)blockSize, (uint)1, memory);
2194 while (bytesRead == blockSize);
2196 return LoadMultiBitmapFromMemory(format, memory, flags);
2201 #region Filetype functions
2218 throw new ArgumentNullException(
"stream");
2220 if (!stream.CanRead)
2222 throw new ArgumentException(
"stream is not capable of reading.");
2225 stream = (stream.CanSeek) ? stream :
new StreamWrapper(stream,
true);
2230 return GetFileTypeFromHandle(ref io, handle, 0);
2236 #region Pixel access functions
2249 public static unsafe IntPtr GetHbitmap(FIBITMAP dib, IntPtr hdc,
bool unload)
2253 throw new ArgumentNullException(
"dib");
2255 IntPtr hBitmap = IntPtr.Zero;
2256 bool release =
false;
2257 IntPtr ppvBits = IntPtr.Zero;
2259 if (release = (hdc == IntPtr.Zero))
2262 hdc = GetDC(IntPtr.Zero);
2264 if (hdc != IntPtr.Zero)
2267 IntPtr info = GetInfo(dib);
2269 hBitmap = CreateDIBSection(hdc, info, DIB_RGB_COLORS, out ppvBits, IntPtr.Zero, 0);
2270 if (hBitmap != IntPtr.Zero && ppvBits != IntPtr.Zero)
2273 CopyMemory(ppvBits, GetBits(dib), (GetHeight(dib) * GetPitch(dib)));
2283 ReleaseDC(IntPtr.Zero, hdc);
2304 public static IntPtr GetBitmapForDevice(FIBITMAP dib, IntPtr hdc,
bool unload)
2308 throw new ArgumentNullException(
"dib");
2310 IntPtr hbitmap = IntPtr.Zero;
2311 bool release =
false;
2312 if (release = (hdc == IntPtr.Zero))
2314 hdc = GetDC(IntPtr.Zero);
2316 if (hdc != IntPtr.Zero)
2318 hbitmap = CreateDIBitmap(
2331 ReleaseDC(IntPtr.Zero, hdc);
2345 public unsafe
static FIBITMAP CreateFromHbitmap(IntPtr hbitmap, IntPtr hdc)
2347 if (hbitmap == IntPtr.Zero)
2349 throw new ArgumentNullException(
"hbitmap");
2352 FIBITMAP dib =
new FIBITMAP();
2357 if (GetObject(hbitmap,
sizeof(BITMAP), (IntPtr)(&bm)) != 0)
2359 dib = Allocate(bm.bmWidth, bm.bmHeight, bm.bmBitsPixel, 0, 0, 0);
2362 colors = GetColorsUsed(dib);
2363 if (release = (hdc == IntPtr.Zero))
2365 hdc = GetDC(IntPtr.Zero);
2374 DIB_RGB_COLORS) != 0)
2378 BITMAPINFOHEADER* bmih = (BITMAPINFOHEADER*)GetInfo(dib);
2379 bmih[0].biClrImportant = bmih[0].biClrUsed = colors;
2388 ReleaseDC(IntPtr.Zero, hdc);
2401 public static bool FreeHbitmap(IntPtr hbitmap)
2403 return DeleteObject(hbitmap);
2408 #region Bitmap information functions
2418 public static uint GetResolutionX(FIBITMAP dib)
2422 throw new ArgumentNullException(
"dib");
2424 return (uint)(0.5d + 0.0254d * GetDotsPerMeterX(dib));
2435 public static uint GetResolutionY(FIBITMAP dib)
2439 throw new ArgumentNullException(
"dib");
2441 return (uint)(0.5d + 0.0254d * GetDotsPerMeterY(dib));
2452 public static void SetResolutionX(FIBITMAP dib, uint res)
2456 throw new ArgumentNullException(
"dib");
2458 SetDotsPerMeterX(dib, (uint)((
double)res / 0.0254d + 0.5d));
2469 public static void SetResolutionY(FIBITMAP dib, uint res)
2473 throw new ArgumentNullException(
"dib");
2475 SetDotsPerMeterY(dib, (uint)((
double)res / 0.0254d + 0.5d));
2488 public static unsafe
bool IsGreyscaleImage(FIBITMAP dib)
2492 throw new ArgumentNullException(
"dib");
2495 uint bpp = GetBPP(dib);
2501 RGBQUAD* palette = (RGBQUAD*)GetPalette(dib);
2502 uint paletteLength = GetColorsUsed(dib);
2503 for (
int i = 0; i < paletteLength; i++)
2505 if (palette[i].rgbRed != palette[i].rgbGreen ||
2506 palette[i].rgbRed != palette[i].rgbBlue)
2527 public static Palette GetPaletteEx(FIBITMAP dib)
2529 return new Palette(dib);
2541 public static unsafe BITMAPINFOHEADER GetInfoHeaderEx(FIBITMAP dib)
2545 throw new ArgumentNullException(
"dib");
2547 return *(BITMAPINFOHEADER*)GetInfoHeader(dib);
2559 public static BITMAPINFO GetInfoEx(FIBITMAP dib)
2563 throw new ArgumentNullException(
"dib");
2565 BITMAPINFO result =
new BITMAPINFO();
2566 result.bmiHeader = GetInfoHeaderEx(dib);
2567 IntPtr ptr = GetPalette(dib);
2568 if (ptr == IntPtr.Zero)
2570 result.bmiColors =
new RGBQUAD[0];
2574 result.bmiColors =
new MemoryArray<RGBQUAD>(ptr, (int)result.bmiHeader.biClrUsed).Data;
2586 public static PixelFormat GetPixelFormat(FIBITMAP dib)
2590 throw new ArgumentNullException(
"dib");
2597 switch (GetBPP(dib))
2600 result = PixelFormat.Format1bppIndexed;
2603 result = PixelFormat.Format4bppIndexed;
2606 result = PixelFormat.Format8bppIndexed;
2609 if ((GetBlueMask(dib) == FI16_565_BLUE_MASK) &&
2610 (GetGreenMask(dib) == FI16_565_GREEN_MASK) &&
2611 (GetRedMask(dib) == FI16_565_RED_MASK))
2613 result = PixelFormat.Format16bppRgb565;
2615 if ((GetBlueMask(dib) == FI16_555_BLUE_MASK) &&
2616 (GetGreenMask(dib) == FI16_555_GREEN_MASK) &&
2617 (GetRedMask(dib) == FI16_555_RED_MASK))
2619 result = PixelFormat.Format16bppRgb555;
2623 result = PixelFormat.Format24bppRgb;
2626 result = PixelFormat.Format32bppArgb;
2646 public static bool GetFormatParameters(
2651 out uint green_mask,
2654 bool result =
false;
2655 type = FREE_IMAGE_TYPE.FIT_UNKNOWN;
2662 case PixelFormat.Format1bppIndexed:
2663 type = FREE_IMAGE_TYPE.FIT_BITMAP;
2667 case PixelFormat.Format4bppIndexed:
2668 type = FREE_IMAGE_TYPE.FIT_BITMAP;
2672 case PixelFormat.Format8bppIndexed:
2673 type = FREE_IMAGE_TYPE.FIT_BITMAP;
2677 case PixelFormat.Format16bppRgb565:
2678 type = FREE_IMAGE_TYPE.FIT_BITMAP;
2680 red_mask = FI16_565_RED_MASK;
2681 green_mask = FI16_565_GREEN_MASK;
2682 blue_mask = FI16_565_BLUE_MASK;
2685 case PixelFormat.Format16bppRgb555:
2686 case PixelFormat.Format16bppArgb1555:
2687 type = FREE_IMAGE_TYPE.FIT_BITMAP;
2689 red_mask = FI16_555_RED_MASK;
2690 green_mask = FI16_555_GREEN_MASK;
2691 blue_mask = FI16_555_BLUE_MASK;
2694 case PixelFormat.Format24bppRgb:
2695 type = FREE_IMAGE_TYPE.FIT_BITMAP;
2697 red_mask = FI_RGBA_RED_MASK;
2698 green_mask = FI_RGBA_GREEN_MASK;
2699 blue_mask = FI_RGBA_BLUE_MASK;
2702 case PixelFormat.Format32bppRgb:
2703 case PixelFormat.Format32bppArgb:
2704 case PixelFormat.Format32bppPArgb:
2705 type = FREE_IMAGE_TYPE.FIT_BITMAP;
2707 red_mask = FI_RGBA_RED_MASK;
2708 green_mask = FI_RGBA_GREEN_MASK;
2709 blue_mask = FI_RGBA_BLUE_MASK;
2712 case PixelFormat.Format16bppGrayScale:
2713 type = FREE_IMAGE_TYPE.FIT_UINT16;
2717 case PixelFormat.Format48bppRgb:
2718 type = FREE_IMAGE_TYPE.FIT_RGB16;
2722 case PixelFormat.Format64bppArgb:
2723 case PixelFormat.Format64bppPArgb:
2724 type = FREE_IMAGE_TYPE.FIT_RGBA16;
2742 if (imageFormat != null)
2744 if (imageFormat.Equals(ImageFormat.Bmp))
2746 if (imageFormat.Equals(ImageFormat.Gif))
2748 if (imageFormat.Equals(ImageFormat.Icon))
2750 if (imageFormat.Equals(ImageFormat.Jpeg))
2752 if (imageFormat.Equals(ImageFormat.Png))
2754 if (imageFormat.Equals(ImageFormat.Tiff))
2757 return FREE_IMAGE_FORMAT.FIF_UNKNOWN;
2772 public static bool GetTypeParameters(
2776 out uint green_mask,
2779 bool result =
false;
2785 case FREE_IMAGE_TYPE.FIT_BITMAP:
2795 red_mask = FI16_555_RED_MASK;
2796 green_mask = FI16_555_GREEN_MASK;
2797 blue_mask = FI16_555_BLUE_MASK;
2802 red_mask = FI_RGBA_RED_MASK;
2803 green_mask = FI_RGBA_GREEN_MASK;
2804 blue_mask = FI_RGBA_BLUE_MASK;
2808 case FREE_IMAGE_TYPE.FIT_UNKNOWN:
2827 if (dib1.IsNull ^ dib2.IsNull)
2855 private static unsafe
bool CompareHeader(FIBITMAP dib1, FIBITMAP dib2)
2857 IntPtr i1 = GetInfoHeader(dib1);
2858 IntPtr i2 = GetInfoHeader(dib2);
2859 return CompareMemory((
void*)i1, (
void*)i2,
sizeof(BITMAPINFOHEADER));
2862 private static unsafe
bool ComparePalette(FIBITMAP dib1, FIBITMAP dib2)
2864 IntPtr pal1 = GetPalette(dib1), pal2 = GetPalette(dib2);
2865 bool hasPalette1 = pal1 != IntPtr.Zero;
2866 bool hasPalette2 = pal2 != IntPtr.Zero;
2867 if (hasPalette1 ^ hasPalette2)
2875 uint colors = GetColorsUsed(dib1);
2876 if (colors != GetColorsUsed(dib2))
2880 return CompareMemory((
void*)pal1, (
void*)pal2,
sizeof(RGBQUAD) * colors);
2883 private static unsafe
bool CompareData(FIBITMAP dib1, FIBITMAP dib2)
2885 uint width = GetWidth(dib1);
2886 if (width != GetWidth(dib2))
2890 uint height = GetHeight(dib1);
2891 if (height != GetHeight(dib2))
2895 uint bpp = GetBPP(dib1);
2896 if (bpp != GetBPP(dib2))
2900 if (GetColorType(dib1) != GetColorType(dib2))
2905 if (type != GetImageType(dib2))
2909 if (GetRedMask(dib1) != GetRedMask(dib2))
2913 if (GetGreenMask(dib1) != GetGreenMask(dib2))
2917 if (GetBlueMask(dib1) != GetBlueMask(dib2))
2925 uint line = GetLine(dib1);
2932 for (
int i = 0; i < height; i++)
2934 ptr1 = (byte*)GetScanLine(dib1, i);
2935 ptr2 = (byte*)GetScanLine(dib2, i);
2936 if (!CompareMemory(ptr1, ptr2, line))
2943 for (
int i = 0; i < height; i++)
2945 ptr1 = (byte*)GetScanLine(dib1, i);
2946 ptr2 = (byte*)GetScanLine(dib2, i);
2947 if (!CompareMemory(ptr1, ptr2, line))
2954 short* sPtr1, sPtr2;
2955 short mask = (short)(GetRedMask(dib1) | GetGreenMask(dib1) | GetBlueMask(dib1));
2958 for (
int i = 0; i < height; i++)
2960 sPtr1 = (
short*)GetScanLine(dib1, i);
2961 sPtr2 = (
short*)GetScanLine(dib2, i);
2962 if (!CompareMemory(sPtr1, sPtr1, line))
2970 for (
int i = 0; i < height; i++)
2972 sPtr1 = (
short*)GetScanLine(dib1, i);
2973 sPtr2 = (
short*)GetScanLine(dib2, i);
2974 for (
int x = 0; x < width; x++)
2976 if ((sPtr1[x] & mask) != (sPtr2[x] & mask))
2985 for (
int i = 0; i < height; i++)
2987 ptr1 = (byte*)GetScanLine(dib1, i);
2988 ptr2 = (byte*)GetScanLine(dib2, i);
2989 if (!CompareMemory(ptr1, ptr2, line))
2996 fullBytes = (int)width / 2;
2997 shift = (width % 2) == 0 ? 8 : 4;
2998 for (
int i = 0; i < height; i++)
3000 ptr1 = (byte*)GetScanLine(dib1, i);
3001 ptr2 = (byte*)GetScanLine(dib2, i);
3004 if (!CompareMemory(ptr1, ptr2, fullBytes))
3013 if ((ptr1[0] >> shift) != (ptr2[0] >> shift))
3021 fullBytes = (int)width / 8;
3022 shift = 8 - ((int)width % 8);
3023 for (
int i = 0; i < height; i++)
3025 ptr1 = (byte*)GetScanLine(dib1, i);
3026 ptr2 = (byte*)GetScanLine(dib2, i);
3029 if (!CompareMemory(ptr1, ptr2, fullBytes))
3038 if ((ptr1[0] >> shift) != (ptr2[0] >> shift))
3046 throw new NotSupportedException(
"Only 1, 4, 8, 16, 24 and 32 bpp bitmaps are supported.");
3051 for (
int i = 0; i < height; i++)
3053 ptr1 = (byte*)GetScanLine(dib1, i);
3054 ptr2 = (byte*)GetScanLine(dib2, i);
3055 if (!CompareMemory(ptr1, ptr2, line))
3064 private static bool CompareMetadata(FIBITMAP dib1, FIBITMAP dib2)
3070 if (GetMetadataCount(metadataModel, dib1) !=
3071 GetMetadataCount(metadataModel, dib2))
3075 if (GetMetadataCount(metadataModel, dib1) == 0)
3080 FIMETADATA mdHandle = FindFirstMetadata(metadataModel, dib1, out tag1);
3081 if (mdHandle.IsNull)
3087 if ((!GetMetadata(metadataModel, dib2, tag1.
Key, out tag2)) || (tag1 != tag2))
3089 FindCloseMetadata(mdHandle);
3093 while (FindNextMetadata(mdHandle, out tag1));
3094 FindCloseMetadata(mdHandle);
3108 public static unsafe byte[] GetTransparencyTableEx(FIBITMAP dib)
3112 throw new ArgumentNullException(
"dib");
3114 uint count = GetTransparencyCount(dib);
3115 byte[] result =
new byte[
count];
3116 byte* ptr = (byte*)GetTransparencyTable(dib);
3117 fixed (byte* dst = result)
3131 public static void SetTransparencyTable(FIBITMAP dib, byte[] table)
3135 throw new ArgumentNullException(
"dib");
3139 throw new ArgumentNullException(
"table");
3141 SetTransparencyTable(dib, table, table.Length);
3156 public static unsafe
int GetUniqueColors(FIBITMAP dib)
3160 throw new ArgumentNullException(
"dib");
3171 int width = (int)GetWidth(dib);
3172 int height = (int)GetHeight(dib);
3174 switch (GetBPP(dib))
3179 lut = CreateShrunkenPaletteLUT(dib, out uniquePalEnts);
3180 if (uniquePalEnts == 1)
3185 if ((*(byte*)GetScanLine(dib, 0) & 0x80) == 0)
3187 for (
int y = 0;
y < height;
y++)
3189 byte* scanline = (byte*)GetScanLine(dib,
y);
3191 for (
int x = 0; x < width; x++)
3193 if ((scanline[x / 8] & mask) > 0)
3197 mask = (mask == 0x1) ? 0x80 : (mask >> 1);
3203 for (
int y = 0;
y < height;
y++)
3205 byte* scanline = (byte*)GetScanLine(dib,
y);
3207 for (
int x = 0; x < width; x++)
3209 if ((scanline[x / 8] & mask) == 0)
3213 mask = (mask == 0x1) ? 0x80 : (mask >> 1);
3221 bitArray =
new BitArray(0x10);
3222 lut = CreateShrunkenPaletteLUT(dib, out uniquePalEnts);
3223 if (uniquePalEnts == 1)
3229 for (
int y = 0; (
y < height) && (result < uniquePalEnts);
y++)
3231 byte* scanline = (byte*)GetScanLine(dib,
y);
3233 for (
int x = 0; (x < width) && (result < uniquePalEnts); x++)
3237 hashcode = lut[scanline[x / 2] >> 4];
3241 hashcode = lut[scanline[x / 2] & 0xF];
3244 if (!bitArray[hashcode])
3246 bitArray[hashcode] =
true;
3255 bitArray =
new BitArray(0x100);
3256 lut = CreateShrunkenPaletteLUT(dib, out uniquePalEnts);
3257 if (uniquePalEnts == 1)
3263 for (
int y = 0; (
y < height) && (result < uniquePalEnts);
y++)
3265 byte* scanline = (byte*)GetScanLine(dib,
y);
3266 for (
int x = 0; (x < width) && (result < uniquePalEnts); x++)
3268 hashcode = lut[scanline[x]];
3269 if (!bitArray[hashcode])
3271 bitArray[hashcode] =
true;
3280 bitArray =
new BitArray(0x10000);
3282 for (
int y = 0;
y < height;
y++)
3284 short* scanline = (
short*)GetScanLine(dib,
y);
3285 for (
int x = 0; x < width; x++, scanline++)
3287 hashcode = *scanline;
3288 if (!bitArray[hashcode])
3290 bitArray[hashcode] =
true;
3299 bitArray =
new BitArray(0x1000000);
3301 for (
int y = 0;
y < height;
y++)
3303 byte* scanline = (byte*)GetScanLine(dib,
y);
3304 for (
int x = 0; x < width; x++, scanline += 3)
3306 hashcode = *((
int*)scanline) & 0x00FFFFFF;
3307 if (!bitArray[hashcode])
3309 bitArray[hashcode] =
true;
3318 bitArray =
new BitArray(0x1000000);
3320 for (
int y = 0;
y < height;
y++)
3322 int* scanline = (
int*)GetScanLine(dib,
y);
3323 for (
int x = 0; x < width; x++, scanline++)
3325 hashcode = *scanline & 0x00FFFFFF;
3326 if (!bitArray[hashcode])
3328 bitArray[hashcode] =
true;
3344 public static bool IsRGB555(FIBITMAP dib)
3346 return ((GetRedMask(dib) == FI16_555_RED_MASK) &&
3347 (GetGreenMask(dib) == FI16_555_GREEN_MASK) &&
3348 (GetBlueMask(dib) == FI16_555_BLUE_MASK));
3356 public static bool IsRGB565(FIBITMAP dib)
3358 return ((GetRedMask(dib) == FI16_565_RED_MASK) &&
3359 (GetGreenMask(dib) == FI16_565_GREEN_MASK) &&
3360 (GetBlueMask(dib) == FI16_565_BLUE_MASK));
3365 #region ICC profile functions
3375 public static FIICCPROFILE CreateICCProfileEx(FIBITMAP dib, byte[] data)
3377 return new FIICCPROFILE(dib, data);
3389 public static FIICCPROFILE CreateICCProfileEx(FIBITMAP dib, byte[] data,
int size)
3391 return new FIICCPROFILE(dib, data, size);
3396 #region Conversion functions
3407 public static FIBITMAP ConvertColorDepth(
3411 return ConvertColorDepth(
3430 public static FIBITMAP ConvertColorDepth(
3435 return ConvertColorDepth(
3455 public static FIBITMAP ConvertColorDepth(
3460 return ConvertColorDepth(
3480 public static FIBITMAP ConvertColorDepth(
3485 return ConvertColorDepth(
3505 public static FIBITMAP ConvertColorDepth(
3510 return ConvertColorDepth(
3531 public static FIBITMAP ConvertColorDepth(
3537 return ConvertColorDepth(
3558 public static FIBITMAP ConvertColorDepth(
3564 return ConvertColorDepth(
3585 public static FIBITMAP ConvertColorDepth(
3591 return ConvertColorDepth(
3615 internal static FIBITMAP ConvertColorDepth(
3625 throw new ArgumentNullException(
"dib");
3628 FIBITMAP result =
new FIBITMAP();
3629 FIBITMAP dibTemp =
new FIBITMAP();
3630 uint bpp = GetBPP(dib);
3631 bool reorderPalette = ((conversion & FREE_IMAGE_COLOR_DEPTH.FICD_REORDER_PALETTE) > 0);
3632 bool forceGreyscale = ((conversion & FREE_IMAGE_COLOR_DEPTH.FICD_FORCE_GREYSCALE) > 0);
3634 if (GetImageType(dib) == FREE_IMAGE_TYPE.FIT_BITMAP)
3638 case FREE_IMAGE_COLOR_DEPTH.FICD_01_BPP_THRESHOLD:
3644 result = Threshold(dib, threshold);
3648 dibTemp = ConvertTo24Bits(dib);
3649 result = ColorQuantizeEx(dibTemp, quantizationMethod, 2, null, 1);
3655 bool isGreyscale = IsGreyscaleImage(dib);
3656 if ((forceGreyscale && (!isGreyscale)) ||
3657 (reorderPalette && isGreyscale))
3659 result = Threshold(dib, threshold);
3664 case FREE_IMAGE_COLOR_DEPTH.FICD_01_BPP_DITHER:
3670 result = Dither(dib, ditherMethod);
3674 dibTemp = ConvertTo24Bits(dib);
3675 result = ColorQuantizeEx(dibTemp, quantizationMethod, 2, null, 1);
3681 bool isGreyscale = IsGreyscaleImage(dib);
3682 if ((forceGreyscale && (!isGreyscale)) ||
3683 (reorderPalette && isGreyscale))
3685 result = Dither(dib, ditherMethod);
3690 case FREE_IMAGE_COLOR_DEPTH.FICD_04_BPP:
3695 if (forceGreyscale ||
3698 dibTemp = ConvertToGreyscale(dib);
3699 result = ConvertTo4Bits(dibTemp);
3704 dibTemp = ConvertTo24Bits(dib);
3705 result = ColorQuantizeEx(dibTemp, quantizationMethod, 16, null, 4);
3711 bool isGreyscale = IsGreyscaleImage(dib);
3712 if ((forceGreyscale && (!isGreyscale)) ||
3713 (reorderPalette && isGreyscale))
3715 dibTemp = ConvertToGreyscale(dib);
3716 result = ConvertTo4Bits(dibTemp);
3723 case FREE_IMAGE_COLOR_DEPTH.FICD_08_BPP:
3729 result = ConvertToGreyscale(dib);
3733 dibTemp = ConvertTo24Bits(dib);
3734 result = ColorQuantize(dibTemp, quantizationMethod);
3740 bool isGreyscale = IsGreyscaleImage(dib);
3741 if ((forceGreyscale && (!isGreyscale)) || (reorderPalette && isGreyscale))
3743 result = ConvertToGreyscale(dib);
3748 case FREE_IMAGE_COLOR_DEPTH.FICD_16_BPP_555:
3752 dibTemp = ConvertToGreyscale(dib);
3753 result = ConvertTo16Bits555(dibTemp);
3756 else if (bpp != 16 || GetRedMask(dib) != FI16_555_RED_MASK || GetGreenMask(dib) != FI16_555_GREEN_MASK || GetBlueMask(dib) != FI16_555_BLUE_MASK)
3758 result = ConvertTo16Bits555(dib);
3762 case FREE_IMAGE_COLOR_DEPTH.FICD_16_BPP:
3766 dibTemp = ConvertToGreyscale(dib);
3767 result = ConvertTo16Bits565(dibTemp);
3770 else if (bpp != 16 || GetRedMask(dib) != FI16_565_RED_MASK || GetGreenMask(dib) != FI16_565_GREEN_MASK || GetBlueMask(dib) != FI16_565_BLUE_MASK)
3772 result = ConvertTo16Bits565(dib);
3776 case FREE_IMAGE_COLOR_DEPTH.FICD_24_BPP:
3780 dibTemp = ConvertToGreyscale(dib);
3781 result = ConvertTo24Bits(dibTemp);
3786 result = ConvertTo24Bits(dib);
3790 case FREE_IMAGE_COLOR_DEPTH.FICD_32_BPP:
3794 dibTemp = ConvertToGreyscale(dib);
3795 result = ConvertTo32Bits(dibTemp);
3800 result = ConvertTo32Bits(dib);
3831 public static FIBITMAP ColorQuantizeEx(FIBITMAP dib,
FREE_IMAGE_QUANTIZE quantize,
int PaletteSize, RGBQUAD[] ReservePalette,
bool minColorDepth)
3837 if (PaletteSize >= 256)
3839 else if (PaletteSize > 2)
3843 result = ColorQuantizeEx(dib, quantize, PaletteSize, ReservePalette, bpp);
3847 result = ColorQuantizeEx(dib, quantize, PaletteSize, ReservePalette, 8);
3864 public static FIBITMAP ColorQuantizeEx(FIBITMAP dib,
FREE_IMAGE_QUANTIZE quantize,
int PaletteSize, RGBQUAD[] ReservePalette,
int bpp)
3870 int reservedSize = (ReservePalette == null) ? 0 : ReservePalette.Length;
3874 result = ColorQuantizeEx(dib, quantize, PaletteSize, reservedSize, ReservePalette);
3878 temp = ColorQuantizeEx(dib, quantize, Math.Min(16, PaletteSize), reservedSize, ReservePalette);
3881 result = Allocate((
int)GetWidth(temp), (
int)GetHeight(temp), 4, 0, 0, 0);
3882 CloneMetadata(result, temp);
3883 CopyMemory(GetPalette(result), GetPalette(temp),
sizeof(RGBQUAD) * 16);
3885 for (
int y = (
int)GetHeight(temp) - 1;
y >= 0;
y--)
3887 Scanline<byte> srcScanline =
new Scanline<byte>(temp,
y);
3888 Scanline<FI4BIT> dstScanline =
new Scanline<FI4BIT>(result,
y);
3890 for (
int x = (
int)GetWidth(temp) - 1; x >= 0; x--)
3892 dstScanline[x] = srcScanline[x];
3899 temp = ColorQuantizeEx(dib, quantize, 2, reservedSize, ReservePalette);
3902 result = Allocate((
int)GetWidth(temp), (
int)GetHeight(temp), 1, 0, 0, 0);
3903 CloneMetadata(result, temp);
3904 CopyMemory(GetPalette(result), GetPalette(temp),
sizeof(RGBQUAD) * 2);
3906 for (
int y = (
int)GetHeight(temp) - 1;
y >= 0;
y--)
3908 Scanline<byte> srcScanline =
new Scanline<byte>(temp,
y);
3909 Scanline<FI1BIT> dstScanline =
new Scanline<FI1BIT>(result,
y);
3911 for (
int x = (
int)GetWidth(temp) - 1; x >= 0; x--)
3913 dstScanline[x] = srcScanline[x];
3941 throw new ArgumentNullException(
"src");
3945 throw new ArgumentNullException(
"dst");
3948 FITAG tag =
new FITAG(), tag2 =
new FITAG();
3956 if (!SetMetadata(model, dst, null, tag))
3963 bool keep = !((flags & FREE_IMAGE_METADATA_COPY.REPLACE_EXISTING) > 0);
3967 FIMETADATA mData = FindFirstMetadata(model, src, out tag);
3968 if (mData.IsNull)
continue;
3971 string key = GetTagKey(tag);
3972 if (!(keep && GetMetadata(model, dst, key, out tag2)))
3974 if (SetMetadata(model, dst, key, tag))
3980 while (FindNextMetadata(mData, out tag));
3981 FindCloseMetadata(mData);
3994 public static string GetImageComment(FIBITMAP dib)
3996 string result = null;
3999 throw new ArgumentNullException(
"dib");
4005 result = metadataTag.Value as string;
4019 public static bool SetImageComment(FIBITMAP dib,
string comment)
4023 throw new ArgumentNullException(
"dib");
4026 if (comment != null)
4028 FITAG tag = CreateTag();
4030 metadataTag.Value = comment;
4051 public static bool GetMetadata(
4059 throw new ArgumentNullException(
"dib");
4064 if (GetMetadata(model, dib, key, out _tag))
4087 public static bool SetMetadata(
4095 throw new ArgumentNullException(
"dib");
4097 return SetMetadata(model, dib, key, tag.tag);
4110 public static FIMETADATA FindFirstMetadata(
4117 throw new ArgumentNullException(
"dib");
4120 FIMETADATA result = FindFirstMetadata(model, dib, out _tag);
4127 if (metaDataSearchHandler.ContainsKey(result))
4129 metaDataSearchHandler[result] = model;
4133 metaDataSearchHandler.Add(result, model);
4145 public static bool FindNextMetadata(FIMETADATA mdhandle, out
MetadataTag tag)
4149 if (FindNextMetadata(mdhandle, out _tag))
4151 tag =
new MetadataTag(_tag, metaDataSearchHandler[mdhandle]);
4166 public static void FindCloseMetadata(FIMETADATA mdhandle)
4168 if (metaDataSearchHandler.ContainsKey(mdhandle))
4170 metaDataSearchHandler.Remove(mdhandle);
4172 FindCloseMetadata_(mdhandle);
4178 private static Dictionary<FIMETADATA, FREE_IMAGE_MDMODEL> metaDataSearchHandler
4179 =
new Dictionary<FIMETADATA, FREE_IMAGE_MDMODEL>(1);
4183 #region Rotation and Flipping
4193 public static FIBITMAP Rotate(FIBITMAP dib,
double angle)
4195 return Rotate(dib, angle, IntPtr.Zero);
4208 public static FIBITMAP Rotate<T>(FIBITMAP dib,
double angle,
T? backgroundColor) where T :
struct
4210 if (backgroundColor.HasValue)
4212 GCHandle handle =
new GCHandle();
4215 T[] buffer =
new T[] { backgroundColor.Value };
4216 handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
4217 return Rotate(dib, angle, handle.AddrOfPinnedObject());
4221 if (handle.IsAllocated)
4227 return Rotate(dib, angle, IntPtr.Zero);
4248 public static unsafe FIBITMAP Rotate4bit(FIBITMAP dib,
double angle)
4252 throw new ArgumentNullException(
"dib");
4255 FIBITMAP result =
new FIBITMAP();
4256 int ang = (int)angle;
4259 (GetBPP(dib) == 4) &&
4262 int width, height, xOrg, yOrg;
4263 Scanline<FI4BIT>[] src, dst;
4264 width = (int)GetWidth(dib);
4265 height = (int)GetHeight(dib);
4270 result = Allocate(height, width, 4, 0, 0, 0);
4275 CopyPalette(dib, result);
4276 src = Get04BitScanlines(dib);
4277 dst = Get04BitScanlines(result);
4278 for (
int y = 0;
y < width;
y++)
4281 for (
int x = 0; x < height; x++, yOrg--)
4283 index = src[yOrg][
y];
4289 result = Allocate(width, height, 4, 0, 0, 0);
4294 CopyPalette(dib, result);
4295 src = Get04BitScanlines(dib);
4296 dst = Get04BitScanlines(result);
4299 for (
int y = 0;
y < height;
y++, yOrg--)
4302 for (
int x = 0; x < width; x++, xOrg--)
4304 index = src[yOrg][xOrg];
4310 result = Allocate(height, width, 4, 0, 0, 0);
4315 CopyPalette(dib, result);
4316 src = Get04BitScanlines(dib);
4317 dst = Get04BitScanlines(result);
4319 for (
int y = 0;
y < width;
y++, xOrg--)
4321 for (
int x = 0; x < height; x++)
4323 index = src[x][xOrg];
4330 result =
Clone(dib);
4339 #region Upsampling / downsampling
4405 public static FIBITMAP EnlargeCanvas<T>(FIBITMAP dib,
int left,
int top,
int right,
int bottom,
4413 if (!CheckColorType(GetImageType(dib), color.Value))
4414 return FIBITMAP.
Zero;
4416 GCHandle handle =
new GCHandle();
4419 T[] buffer =
new T[] { color.Value };
4420 handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
4421 return EnlargeCanvas(dib, left, top, right, bottom, handle.AddrOfPinnedObject(), options);
4425 if (handle.IsAllocated)
4431 return EnlargeCanvas(dib, left, top, right, bottom, IntPtr.Zero, options);
4524 if (!CheckColorType(GetImageType(dib), color))
4527 GCHandle handle =
new GCHandle();
4530 T[] buffer =
new T[] { color };
4531 handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
4532 return FillBackground(dib, handle.AddrOfPinnedObject(), options);
4536 if (handle.IsAllocated)
4543 #region Wrapper functions
4550 internal static int GetNextColorDepth(
int bpp)
4579 internal static int GetPrevousColorDepth(
int bpp)
4608 internal static unsafe
string PtrToStr(byte* ptr)
4610 string result = null;
4613 System.Text.StringBuilder sb =
new System.Text.StringBuilder();
4617 sb.Append((char)(*(ptr++)));
4619 result = sb.ToString();
4624 internal static unsafe byte[] CreateShrunkenPaletteLUT(FIBITMAP dib, out
int uniqueColors)
4626 byte[] result = null;
4629 if ((!dib.IsNull) && (GetImageType(dib) ==
FREE_IMAGE_TYPE.FIT_BITMAP) && (GetBPP(dib) <= 8))
4631 int size = (int)GetColorsUsed(dib);
4632 List<RGBQUAD> newPalette =
new List<RGBQUAD>(
size);
4633 List<byte> lut =
new List<byte>(
size);
4634 RGBQUAD* palette = (RGBQUAD*)GetPalette(dib);
4638 for (
int i = 0; i <
size; i++)
4641 color.rgbReserved = 255;
4643 index = newPalette.IndexOf(color);
4646 newPalette.Add(color);
4647 lut.Add((byte)(newPalette.Count - 1));
4651 lut.Add((byte)index);
4654 result = lut.ToArray();
4655 uniqueColors = newPalette.Count;
4660 internal static PropertyItem CreatePropertyItem()
4662 return (PropertyItem)Activator.CreateInstance(typeof(PropertyItem),
true);
4665 private static unsafe
void CopyPalette(FIBITMAP src, FIBITMAP dst)
4667 RGBQUAD* orgPal = (RGBQUAD*)GetPalette(src);
4668 RGBQUAD* newPal = (RGBQUAD*)GetPalette(dst);
4669 uint size = (uint)(
sizeof(RGBQUAD) * GetColorsUsed(src));
4673 private static unsafe Scanline<FI4BIT>[] Get04BitScanlines(FIBITMAP dib)
4675 int height = (int)GetHeight(dib);
4676 Scanline<FI4BIT>[] array =
new Scanline<FI4BIT>[height];
4677 for (
int i = 0; i < height; i++)
4679 array[i] =
new Scanline<FI4BIT>(dib, i);
4693 int bpp = (int)GetBPP(dibToSave);
4699 if (FIFSupportsExportBPP(format, targetBpp))
4701 dibToSave = ConvertColorDepth(dibToSave, colorDepth,
false);
4705 throw new ArgumentException(
"FreeImage\n\nFreeImage Library plugin " +
4706 GetFormatFromFIF(format) +
" is unable to write images with a color depth of " +
4707 targetBpp +
" bpp.");
4713 if (!FIFSupportsExportBPP(format, bpp))
4721 bppUpper = GetNextColorDepth(bppUpper);
4722 if (FIFSupportsExportBPP(format, bppUpper))
4727 bppLower = GetPrevousColorDepth(bppLower);
4728 if (FIFSupportsExportBPP(format, bppLower))
4733 }
while (!((bppLower == 0) && (bppUpper == 0)));
4747 public static unsafe
bool CompareMemory(
void* buf1,
void* buf2, uint length)
4749 return (length == RtlCompareMemory(buf1, buf2, length));
4759 public static unsafe
bool CompareMemory(
void* buf1,
void* buf2,
long length)
4761 return (length == RtlCompareMemory(buf1, buf2, checked((uint)length)));
4771 public static unsafe
bool CompareMemory(IntPtr buf1, IntPtr buf2, uint length)
4773 return (length == RtlCompareMemory(buf1.ToPointer(), buf2.ToPointer(), length));
4783 public static unsafe
bool CompareMemory(IntPtr buf1, IntPtr buf2,
long length)
4785 return (length == RtlCompareMemory(buf1.ToPointer(), buf2.ToPointer(), checked((uint)length)));
4794 public static unsafe
void MoveMemory(
void* dst,
void* src,
long size)
4796 MoveMemory(dst, src, checked((uint)size));
4805 public static unsafe
void MoveMemory(IntPtr dst, IntPtr src, uint size)
4807 MoveMemory(dst.ToPointer(), src.ToPointer(), size);
4816 public static unsafe
void MoveMemory(IntPtr dst, IntPtr src,
long size)
4818 MoveMemory(dst.ToPointer(), src.ToPointer(), checked((uint)size));
4831 public static unsafe
void CopyMemory(byte*
dest, byte* src,
int len)
4837 *((
int*)dest) = *((
int*)src);
4838 *((
int*)(dest + 4)) = *((
int*)(src + 4));
4839 *((
int*)(dest + 8)) = *((
int*)(src + 8));
4840 *((
int*)(dest + 12)) = *((
int*)(src + 12));
4844 while ((len -= 0x10) >= 0x10);
4850 *((
int*)dest) = *((
int*)src);
4851 *((
int*)(dest + 4)) = *((
int*)(src + 4));
4857 *((
int*)dest) = *((
int*)src);
4863 *((
short*)dest) = *((
short*)src);
4884 public static unsafe
void CopyMemory(byte* dest, byte* src,
long len)
4899 public static unsafe
void CopyMemory(
void* dest,
void* src,
long len)
4901 CopyMemory((byte*)dest, (byte*)src, checked((
int)len));
4914 public static unsafe
void CopyMemory(
void* dest,
void* src,
int len)
4929 public static unsafe
void CopyMemory(IntPtr dest, IntPtr src,
int len)
4944 public static unsafe
void CopyMemory(IntPtr dest, IntPtr src,
long len)
4946 CopyMemory((byte*)dest, (byte*)src, checked((
int)len));
4955 public static unsafe
void CopyMemory(Array dest,
void* src,
int len)
4957 GCHandle handle = GCHandle.Alloc(
dest, GCHandleType.Pinned);
4960 CopyMemory((byte*)handle.AddrOfPinnedObject(), (byte*)src, len);
4974 public static unsafe
void CopyMemory(Array dest,
void* src,
long len)
4976 CopyMemory(dest, (byte*)src, checked((
int)len));
4985 public static unsafe
void CopyMemory(Array dest, IntPtr src,
int len)
4996 public static unsafe
void CopyMemory(Array dest, IntPtr src,
long len)
4998 CopyMemory(dest, (byte*)src, checked((
int)len));
5007 public static unsafe
void CopyMemory(
void* dest, Array src,
int len)
5009 GCHandle handle = GCHandle.Alloc(src, GCHandleType.Pinned);
5012 CopyMemory((byte*)dest, (byte*)handle.AddrOfPinnedObject(), len);
5026 public static unsafe
void CopyMemory(
void* dest, Array src,
long len)
5028 CopyMemory((byte*)dest, src, checked((
int)len));
5037 public static unsafe
void CopyMemory(IntPtr dest, Array src,
int len)
5048 public static unsafe
void CopyMemory(IntPtr dest, Array src,
long len)
5050 CopyMemory((byte*)dest, src, checked((
int)len));
5059 public static unsafe
void CopyMemory(Array dest, Array src,
int len)
5061 GCHandle dHandle = GCHandle.Alloc(
dest, GCHandleType.Pinned);
5064 GCHandle sHandle = GCHandle.Alloc(src, GCHandleType.Pinned);
5067 CopyMemory((byte*)dHandle.AddrOfPinnedObject(), (byte*)sHandle.AddrOfPinnedObject(), len);
5086 public static unsafe
void CopyMemory(Array dest, Array src,
long len)
5091 internal static string ColorToString(
Color color)
5093 return string.Format(
5094 System.Globalization.CultureInfo.CurrentCulture,
5095 "{{Name={0}, ARGB=({1}, {2}, {3}, {4})}}",
5096 new object[] { color.Name, color.A, color.R, color.G, color.B });
5099 internal static void Resize(ref
string str,
int length)
5101 if ((str != null) && (length >= 0) && (str.Length != length))
5103 char[] chars = str.ToCharArray();
5104 Array.Resize(ref chars, length);
5105 str =
new string(chars);
5109 internal static void Resize(ref
string str,
int min,
int max)
5111 if ((str != null) && (min >= 0) && (max >= 0) && (min <= max))
5113 if (str.Length < min)
5115 char[] chars = str.ToCharArray();
5116 Array.Resize(ref chars, min);
5117 str =
new string(chars);
5119 else if (str.Length > max)
5121 char[] chars = str.ToCharArray();
5122 Array.Resize(ref chars, max);
5123 str =
new string(chars);
5128 internal static void Resize<T>(ref
T[] array,
int length)
5130 if ((array != null) && (length >= 0) && (array.Length != length))
5132 Array.Resize(ref array, length);
5136 internal static void Resize<T>(ref
T[] array,
int min,
int max)
5138 if ((array != null) && (min >= 0) && (max >= 0) && (min <= max))
5140 if (array.Length < min)
5142 Array.Resize(ref array, min);
5144 else if (array.Length > max)
5146 Array.Resize(ref array, max);
5153 Type type = typeof(T);
5157 case FREE_IMAGE_TYPE.FIT_BITMAP:
5158 result = (type == typeof(RGBQUAD));
break;
5159 case FREE_IMAGE_TYPE.FIT_COMPLEX:
5160 result = (type == typeof(FICOMPLEX));
break;
5161 case FREE_IMAGE_TYPE.FIT_DOUBLE:
5162 result = (type == typeof(
double));
break;
5163 case FREE_IMAGE_TYPE.FIT_FLOAT:
5164 result = (type == typeof(
float));
break;
5165 case FREE_IMAGE_TYPE.FIT_INT16:
5166 result = (type == typeof(Int16));
break;
5167 case FREE_IMAGE_TYPE.FIT_INT32:
5168 result = (type == typeof(Int32));
break;
5169 case FREE_IMAGE_TYPE.FIT_RGB16:
5170 result = (type == typeof(FIRGB16));
break;
5171 case FREE_IMAGE_TYPE.FIT_RGBA16:
5172 result = (type == typeof(FIRGBA16));
break;
5173 case FREE_IMAGE_TYPE.FIT_RGBAF:
5174 result = (type == typeof(FIRGBAF));
break;
5175 case FREE_IMAGE_TYPE.FIT_RGBF:
5176 result = (type == typeof(FIRGBF));
break;
5177 case FREE_IMAGE_TYPE.FIT_UINT16:
5178 result = (type == typeof(UInt16));
break;
5179 case FREE_IMAGE_TYPE.FIT_UINT32:
5180 result = (type == typeof(UInt32));
break;
5182 result =
false;
break;
5199 [DllImport(
"user32.dll")]
5200 private static extern IntPtr GetDC(IntPtr hWnd);
5210 [DllImport(
"user32.dll")]
5211 private static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDC);
5231 [DllImport(
"gdi32.dll")]
5232 private static extern IntPtr CreateDIBSection(
5246 [DllImport(
"gdi32.dll")]
5247 private static extern bool DeleteObject(IntPtr hObject);
5261 [DllImport(
"gdi32.dll")]
5262 private static extern IntPtr CreateDIBitmap(
5279 [DllImport(
"gdi32.dll")]
5280 private static extern int GetObject(IntPtr hgdiobj,
int cbBuffer, IntPtr lpvObject);
5296 [DllImport(
"gdi32.dll")]
5297 private static extern unsafe
int GetDIBits(
5312 [DllImport(
"Kernel32.dll", EntryPoint =
"RtlMoveMemory", SetLastError =
false)]
5313 public static unsafe
extern void MoveMemory(
void* dst,
void* src, uint size);
5324 [DllImport(
"ntdll.dll", EntryPoint =
"RtlCompareMemory", SetLastError =
false)]
5325 internal static unsafe
extern uint RtlCompareMemory(
void* buf1,
void* buf2, uint count);
static readonly FIBITMAP Zero
A read-only field that represents a handle that has been initialized to zero.
FREE_IMAGE_QUANTIZE
Color quantization algorithms. Constants used in FreeImage_ColorQuantize.
_Use_decl_annotations_ bool HasAlpha(DXGI_FORMAT fmt)
HRESULT Resize(_In_ const Image &srcImage, _In_ size_t width, _In_ size_t height, _In_ DWORD filter, _Out_ ScratchImage &image)
Structure for implementing access to custom handles.
FREE_IMAGE_MDMODEL
Metadata models supported by FreeImage.
_In_ size_t _In_ DXGI_FORMAT _In_ size_t _In_ DXGI_FORMAT _In_ DWORD flags
_In_ size_t _In_ DXGI_FORMAT _In_ size_t _In_ float threshold
_In_ size_t _In_ DXGI_FORMAT _In_ size_t _In_ float size_t y
FREE_IMAGE_DITHER
Dithering algorithms. Constants used in FreeImage_Dither.
The clone mixin to clone the current mixins where the clone is emitted.
FREE_IMAGE_COLOR_OPTIONS
Constants used in color filling routines.
static readonly FIMULTIBITMAP Zero
A read-only field that represents a handle that has been initialized to zero.
The type of the serialized type will be passed as a generic arguments of the serializer. Example: serializer of A becomes instantiated as Serializer{A}.
SiliconStudio.Core.Mathematics.Color Color
FREE_IMAGE_COMPARE_FLAGS
List of combinable compare modes.
FREE_IMAGE_METADATA_COPY
Flags for copying data from a bitmap to another.
FREE_IMAGE_COLOR_TYPE
Image color types used in FreeImage.
System.Windows.Shapes.Rectangle Rectangle
FREE_IMAGE_SAVE_FLAGS
Flags used in save functions.
_In_ size_t _In_ size_t _In_ DXGI_FORMAT format
Wrapper for a custom handle.
FREE_IMAGE_COLOR_DEPTH
Enumeration used for color conversions. FREE_IMAGE_COLOR_DEPTH contains several colors to convert to...
FREE_IMAGE_TYPE
Image types used in FreeImage.
FREE_IMAGE_FORMAT
I/O image format identifiers.
_In_ size_t _In_ size_t size
PixelFormat
Defines various types of pixel formats.
FREE_IMAGE_LOAD_FLAGS
Flags used in load functions.