namespace GMap.NET.WindowsForms.Markers{
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
public abstract class GMapMarkerTransparent : GMapMarker
{
protected GMapMarkerTransparent(PointLatLng pos)
: base(pos)
{
}
public override void OnRender(Graphics g)
{
for(Int32 i = 0; i < this.BitmapCount; i++)
{
IGMapTransparentBitmap bitmap = GetBitmap(i);
if(bitmap == null)
{
continue;
}
System.Drawing.Rectangle src = new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height);
System.Drawing.Rectangle dst = new System.Drawing.Rectangle(LocalPosition.X + bitmap.DrawOffset.X, LocalPosition.Y + bitmap.DrawOffset.Y, bitmap.Width, bitmap.Height);
bitmap.Draw(g, dst, src);
}
}
#region Abstract Members
protected abstract Int32 BitmapCount
{
get;
}
protected abstract IGMapTransparentBitmap GetBitmap(Int32 index);
#endregion
#region Load Bitmap
public static IGMapTransparentBitmap LoadTransparentBitmap(Stream stream)
{
return LoadTransparentBitmap(stream, true);
}
public static IGMapTransparentBitmap LoadTransparentBitmap(Stream stream, Boolean hasAlpha)
{
try
{
if(hasAlpha && Environment.OSVersion.Platform == PlatformID.WinCE)
return new WinCEImagingBitmap(stream);
return new StandardBitmap(stream);
}
catch(Exception)
{
return null;
}
}
#endregion
}
#region Transparent Bitmap Wrappers
public interface IGMapTransparentBitmap : IDisposable
{
Int32 Width
{
get;
}
Int32 Height
{
get;
}
Point DrawOffset
{
get;
set;
}
void Draw(Graphics graphics, System.Drawing.Rectangle destRect, System.Drawing.Rectangle sourceRect);
}
public class WinCEImagingBitmap : IGMapTransparentBitmap
{
IImage myImage;
ImageInfo myInfo;
double myScaleFactorX = 0;
double myScaleFactorY = 0;
IntPtr myBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(RECT)));
static IImagingFactory myImagingFactory;
public WinCEImagingBitmap(Stream stream)
{
// this class should only be used in WinCE
System.Diagnostics.Debug.Assert(Environment.OSVersion.Platform == PlatformID.WinCE);
if(myImagingFactory == null)
myImagingFactory = (IImagingFactory) Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("327ABDA8-072B-11D3-9D7B-0000F81EF32E")));
int bytesLength;
byte[] bytes;
MemoryStream memStream = stream as MemoryStream;
if(memStream != null)
{
bytesLength = (int) memStream.Length;
bytes = memStream.GetBuffer();
}
else
{
bytesLength = (int) stream.Length;
bytes = new byte[bytesLength];
stream.Read(bytes, 0, bytesLength);
}
uint hresult = myImagingFactory.CreateImageFromBuffer(bytes, (uint) bytesLength, BufferDisposalFlag.BufferDisposalFlagNone, out myImage);
myImage.GetImageInfo(out myInfo);
myScaleFactorX = 1 / myInfo.Xdpi * 2540;
myScaleFactorY = 1 / myInfo.Ydpi * 2540;
IBitmapImage bitmap;
myImagingFactory.CreateBitmapFromImage(myImage, 0, 0, PixelFormatID.PixelFormat32bppARGB, InterpolationHint.InterpolationHintDefault, out bitmap);
Marshal.FinalReleaseComObject(myImage);
myImage = bitmap as IImage;
}
#region IGMapTransparentBitmap Members
public Int32 Width
{
get
{
return myInfo.Width;
}
}
public Int32 Height
{
get
{
return myInfo.Height;
}
}
Point drawOffset = new Point(0, 0);
public Point DrawOffset
{
get
{
return drawOffset;
}
set
{
drawOffset = value;
}
}
public void Draw(Graphics graphics, System.Drawing.Rectangle destRect, System.Drawing.Rectangle sourceRect)
{
RECT dst = new RECT(destRect);
if(destRect == sourceRect)
{
IntPtr hdc = graphics.GetHdc();
myImage.Draw(hdc, ref dst, IntPtr.Zero);
graphics.ReleaseHdc(hdc);
}
else
{
RECT src = new RECT(sourceRect);
src.Left = (int) (src.Left * myScaleFactorX);
src.Top = (int) (src.Top * myScaleFactorY);
src.Right = (int) (src.Right * myScaleFactorX);
src.Bottom = (int) (src.Bottom * myScaleFactorY);
Marshal.StructureToPtr(src, myBuffer, false);
IntPtr hdc = graphics.GetHdc();
myImage.Draw(hdc, ref dst, myBuffer);
graphics.ReleaseHdc(hdc);
}
}
#endregion
#region IDisposable Members
public void Dispose()
{
if(myImage != null)
{
Marshal.FinalReleaseComObject(myImage);
myImage = null;
}
if(myBuffer != IntPtr.Zero)
{
Marshal.FreeHGlobal(myBuffer);
}
}
#endregion
}
public class StandardBitmap : IGMapTransparentBitmap
{
Bitmap myBitmap;
public Bitmap Bitmap
{
get
{
return myBitmap;
}
set
{
myBitmap = value;
}
}
ImageAttributes myImageAttributes;
public StandardBitmap(Bitmap bitmap, ImageAttributes imageAttributes)
{
if(Environment.OSVersion.Platform == PlatformID.WinCE)
{
// reduce the bpp to native WinCE resolution for performance
myBitmap = new Bitmap(bitmap.Width, bitmap.Height, PixelFormat.Format16bppRgb565);
using(Graphics g = Graphics.FromImage(myBitmap))
{
g.DrawImage(bitmap, 0, 0);
}
}
else
{
myBitmap = bitmap;
}
myImageAttributes = imageAttributes;
}
public StandardBitmap(Stream bitmapStream, ImageAttributes imageAttributes)
: this(new Bitmap(bitmapStream), imageAttributes)
{
}
public StandardBitmap(Stream bitmapStream)
: this(bitmapStream, null)
{
}
public StandardBitmap(Bitmap bitmap)
: this(bitmap, null)
{
}
#region IGMapTransparentBitmap Members
public Int32 Width
{
get
{
return myBitmap.Width;
}
}
public Int32 Height
{
get
{
return myBitmap.Height;
}
}
Point drawOffset = new Point(0, 0);
public Point DrawOffset
{
get
{
return drawOffset;
}
set
{
drawOffset = value;
}
}
public void Draw(Graphics graphics, System.Drawing.Rectangle destRect, System.Drawing.Rectangle sourceRect)
{
if(myImageAttributes == null)
graphics.DrawImage(myBitmap, destRect, sourceRect, GraphicsUnit.Pixel);
else
graphics.DrawImage(myBitmap, destRect, sourceRect.X, sourceRect.Y, sourceRect.Width, sourceRect.Height, GraphicsUnit.Pixel, myImageAttributes);
}
#endregion
#region IDisposable Members
public void Dispose()
{
if(myBitmap != null)
{
myBitmap.Dispose();
myBitmap = null;
}
}
#endregion
}
#endregion
#region IImage
// Pulled from gdipluspixelformats.h in the Windows Mobile 5.0 Pocket PC SDK
enum PixelFormatID : int
{
PixelFormatIndexed=0x00010000, // Indexes into a palette
PixelFormatGDI=0x00020000, // Is a GDI-supported format
PixelFormatAlpha=0x00040000, // Has an alpha component
PixelFormatPAlpha=0x00080000, // Pre-multiplied alpha
PixelFormatExtended=0x00100000, // Extended color 16 bits/channel
PixelFormatCanonical=0x00200000,
PixelFormatUndefined=0,
PixelFormatDontCare=0,
PixelFormat1bppIndexed=(1 | (1 << 8) | PixelFormatIndexed | PixelFormatGDI),
PixelFormat4bppIndexed=(2 | (4 << 8) | PixelFormatIndexed | PixelFormatGDI),
PixelFormat8bppIndexed=(3 | (8 << 8) | PixelFormatIndexed | PixelFormatGDI),
PixelFormat16bppRGB555=(5 | (16 << 8) | PixelFormatGDI),
PixelFormat16bppRGB565=(6 | (16 << 8) | PixelFormatGDI),
PixelFormat16bppARGB1555=(7 | (16 << 8) | PixelFormatAlpha | PixelFormatGDI),
PixelFormat24bppRGB=(8 | (24 << 8) | PixelFormatGDI),
PixelFormat32bppRGB=(9 | (32 << 8) | PixelFormatGDI),
PixelFormat32bppARGB=(10 | (32 << 8) | PixelFormatAlpha | PixelFormatGDI | PixelFormatCanonical),
PixelFormat32bppPARGB=(11 | (32 << 8) | PixelFormatAlpha | PixelFormatPAlpha | PixelFormatGDI),
PixelFormat48bppRGB=(12 | (48 << 8) | PixelFormatExtended),
PixelFormat64bppARGB=(13 | (64 << 8) | PixelFormatAlpha | PixelFormatCanonical | PixelFormatExtended),
PixelFormat64bppPARGB=(14 | (64 << 8) | PixelFormatAlpha | PixelFormatPAlpha | PixelFormatExtended),
PixelFormatMax=15
}
// Pulled from imaging.h in the Windows Mobile 5.0 Pocket PC SDK
enum BufferDisposalFlag : int
{
BufferDisposalFlagNone,
BufferDisposalFlagGlobalFree,
BufferDisposalFlagCoTaskMemFree,
BufferDisposalFlagUnmapView
}
// Pulled from imaging.h in the Windows Mobile 5.0 Pocket PC SDK
enum InterpolationHint : int
{
InterpolationHintDefault,
InterpolationHintNearestNeighbor,
InterpolationHintBilinear,
InterpolationHintAveraging,
InterpolationHintBicubic
}
[Flags]
enum ImageLockMode
{
ImageLockModeRead=0x0001,
ImageLockModeWrite=0x0002,
ImageLockModeUserInputBuf=0x0004,
};
#pragma warning disable 0649
// Pulled from gdiplusimaging.h in the Windows Mobile 5.0 Pocket PC SDK
struct BitmapImageData
{
public uint Width;
public uint Height;
public int Stride;
public PixelFormatID PixelFormat;
public IntPtr Scan0;
public IntPtr Reserved;
}
// Pulled from imaging.h in the Windows Mobile 5.0 Pocket PC SDK
struct ImageInfo
{
public uint GuidPart1; // I am being lazy here, I don't care at this point about the RawDataFormat GUID
public uint GuidPart2; // I am being lazy here, I don't care at this point about the RawDataFormat GUID
public uint GuidPart3; // I am being lazy here, I don't care at this point about the RawDataFormat GUID
public uint GuidPart4; // I am being lazy here, I don't care at this point about the RawDataFormat GUID
public PixelFormatID pixelFormat;
public int Width;
public int Height;
public uint TileWidth;
public uint TileHeight;
public double Xdpi;
public double Ydpi;
public uint Flags;
}
#pragma warning restore 0649
// Pulled from imaging.h in the Windows Mobile 5.0 Pocket PC SDK
[ComImport, Guid("327ABDA7-072B-11D3-9D7B-0000F81EF32E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[ComVisible(true)]
interface IImagingFactory
{
uint CreateImageFromStream(); // This is a place holder, note the lack of arguments
uint CreateImageFromFile(string filename, out IImage image);
// We need the MarshalAs attribute here to keep COM interop from sending the buffer down as a Safe Array.
uint CreateImageFromBuffer([MarshalAs(UnmanagedType.LPArray)] byte[] buffer, uint size, BufferDisposalFlag disposalFlag, out IImage image);
uint CreateNewBitmap(uint width, uint height, PixelFormatID pixelFormat, out IBitmapImage bitmap);
uint CreateBitmapFromImage(IImage image, uint width, uint height, PixelFormatID pixelFormat, InterpolationHint hints, out IBitmapImage bitmap);
uint CreateBitmapFromBuffer(); // This is a place holder, note the lack of arguments
uint CreateImageDecoder(); // This is a place holder, note the lack of arguments
uint CreateImageEncoderToStream(); // This is a place holder, note the lack of arguments
uint CreateImageEncoderToFile(); // This is a place holder, note the lack of arguments
uint GetInstalledDecoders(); // This is a place holder, note the lack of arguments
uint GetInstalledEncoders(); // This is a place holder, note the lack of arguments
uint InstallImageCodec(); // This is a place holder, note the lack of arguments
uint UninstallImageCodec(); // This is a place holder, note the lack of arguments
}
struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
public int Width
{
get
{
return Right - Left;
}
set
{
Right = Left + value;
}
}
public int Height
{
get
{
return Bottom - Top;
}
set
{
Bottom = Top + value;
}
}
public RECT(System.Drawing.Rectangle rect)
{
Left = rect.Left;
Top = rect.Top;
Right = rect.Right;
Bottom = rect.Bottom;
}
public RECT(int left, int top, int width, int height)
{
Left = left;
Top = top;
Right = left + width;
Bottom = top + height;
}
public static implicit operator RECT(System.Drawing.Rectangle rect)
{
return new RECT(rect);
}
}
// Pulled from imaging.h in the Windows Mobile 5.0 Pocket PC SDK
[ComImport, Guid("327ABDA9-072B-11D3-9D7B-0000F81EF32E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[ComVisible(true)]
interface IImage
{
uint GetPhysicalDimension(out Size size);
uint GetImageInfo(out ImageInfo info);
uint SetImageFlags(uint flags);
uint Draw(IntPtr hdc, ref RECT dstRect, IntPtr srcRect); // "Correct" declaration: uint Draw(IntPtr hdc, ref Rectangle dstRect, ref Rectangle srcRect);
uint PushIntoSink(); // This is a place holder, note the lack of arguments
uint GetThumbnail(uint thumbWidth, uint thumbHeight, out IImage thumbImage);
}
// Pulled from imaging.h in the Windows Mobile 5.0 Pocket PC SDK
[ComImport, Guid("327ABDAA-072B-11D3-9D7B-0000F81EF32E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[ComVisible(true)]
interface IBitmapImage
{
uint GetSize(out Size size);
uint GetPixelFormatID(out PixelFormatID pixelFormat);
uint LockBits(ref RECT rect, ImageLockMode flags, PixelFormatID pixelFormat, out BitmapImageData lockedBitmapData);
uint UnlockBits(ref BitmapImageData lockedBitmapData);
uint GetPalette(); // This is a place holder, note the lack of arguments
uint SetPalette(); // This is a place holder, note the lack of arguments
}
#endregion
}
|