In the Windows API image processing is done with GDI and GDI+, the latter now has a 64-bit dimension. Some programmers working on COM clients, like VBA, might like to wrestle with the Windows API declarations and the management of handles but I personally would opt for the .NET approach and I would expose the key methods to COM clients.
Below is some C# code for a class library that is ComVisible(true) and has been 'Registered for COM interop'. For some client code see the VBA listing on this counterpart blog post. Together these programs allow a picture to written to Excel cells like this...
using System;
using System.Drawing; // added assembly reference to System.Drawing
using System.Runtime.InteropServices;
using io = System.IO;
/// <summary>
/// Be a good COM citizen and define the interface separately.
/// In AssemblyInfo.cs we have [assembly: ComVisible(true)].
/// In Project Properties->Build tab under the Output section we have checked the 'Register for COM interop' checkbox.
/// </summary>
namespace ImageToByteArray
{
public interface IColour
{
byte G { get; }
bool IsNamedColor { get; }
bool IsEmpty { get; }
bool IsKnownColor { get; }
byte A { get; }
byte B { get; }
byte R { get; }
}
[ClassInterface(ClassInterfaceType.None)]
[ComDefaultInterface(typeof(IColour))]
public class Colour : IColour
{
Color m_Colour;
byte IColour.G => m_Colour.G;
bool IColour.IsNamedColor => m_Colour.IsNamedColor;
bool IColour.IsEmpty => m_Colour.IsEmpty;
bool IColour.IsKnownColor => m_Colour.IsKnownColor;
byte IColour.A => m_Colour.A;
byte IColour.B => m_Colour.B;
byte IColour.R => m_Colour.R;
public Colour(Color col)
{
m_Colour = col;
}
}
public interface IBitMap
{
int Width { get; }
int Height { get; }
Colour GetPixel(int x, int y);
bool LoadImage(string sFilePath);
}
[ClassInterface(ClassInterfaceType.None)]
[ComDefaultInterface(typeof(IBitMap))]
public class BitMap : IBitMap
{
Bitmap m_bmp;
bool m_bLoaded;
int IBitMap.Width
{
get
{
if (m_bLoaded)
{
return m_bmp.Width;
} else
{
throw new Exception("#load an image first!");
}
}
}
int IBitMap.Height
{
get
{
if (m_bLoaded)
{
return m_bmp.Height;
}
else
{
throw new Exception("#load an image first!");
}
}
}
Colour IBitMap.GetPixel(int x, int y)
{
if (m_bLoaded)
{
Color col = m_bmp.GetPixel(x, y);
return new Colour(col);
}
else
{
throw new Exception("#load an image first!");
}
}
bool IBitMap.LoadImage(string sFilePath)
{
if (!io.File.Exists(sFilePath))
{
throw new Exception("#File '" + sFilePath + "' does not exist!");
}
try
{
m_bmp = new Bitmap(sFilePath);
m_bLoaded = true;
}
catch (Exception ex)
{
throw new Exception("#Something went wrong whilst opening bitmap file '" + sFilePath + "'", ex);
}
return true;
}
}
}