none
IImage.Draw does not draw.

    Question

  • I've been working on this for 2 days now. The image is loaded, i can get it's dimensions with GetImageInfo. Device context is created as well, i know that because the YellowGreen rectangle is being drawn. The problem lies in the last line. Image.Draw. It looks like it does absolutely nothing. It should hide the YellowGreen rectangle with the image, but id doesn't. I've tried so many different ways to call this function, with srcRect and without, with scalling and without. Please help.


    My code:

    if( _imagingFactory == null )
          _imagingFactory = ( IImagingFactory )Activator.CreateInstance( Type.GetTypeFromCLSID( new Guid( "327ABDA8-072B-11D3-9D7B-0000F81EF32E" ) ) );

    ImageInfo info;

    int hresult = _imagingFactory.CreateImageFromFile( filename, out image );

    image.GetImageInfo( out info );

    _hdcMem = GDIPlus.CreateCompatibleDC( _hdc );
    _hBitmap = GDIPlus.CreateCompatibleBitmap( _hdc, ( int )info.Width, ( int )info.Height );
    _hOldBitmap = GDIPlus.SelectObject( _hdcMem, _hBitmap );

    _bitmapSize = new Size( ( int )info.Width, ( int )info.Height );
    RECT destRect = new RECT( 0, 0, ( int )info.Width, ( int )info.Height );

    FillRectangle( _hdcMem, Color.YellowGreen, new Rectangle( 0, 70, 230, 50 ) );
    int result = image.Draw( _hdcMem, ref destRect, IntPtr.Zero );



    // Pulled from gdipluspixelformats.h in the Windows Mobile 5.0 Pocket PC SDK
        public 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
        public enum BufferDisposalFlag : int
        {
            BufferDisposalFlagNone,
            BufferDisposalFlagGlobalFree,
            BufferDisposalFlagCoTaskMemFree,
            BufferDisposalFlagUnmapView
        }

        // Pulled from imaging.h in the Windows Mobile 5.0 Pocket PC SDK
        public enum InterpolationHint : int
        {
            InterpolationHintDefault,
            InterpolationHintNearestNeighbor,
            InterpolationHintBilinear,
            InterpolationHintAveraging,
            InterpolationHintBicubic
        }

        [Flags]
        public 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
        public 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
        public 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 uint Width;
            public uint 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 )]
        public 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
        }

        public 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( 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( 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 )]
        public 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 )]
        public 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
        }
    • Edited by mike_pl Thursday, August 6, 2009 3:07 PM
    Thursday, August 6, 2009 12:46 PM

Answers

  • Don't know what's wrong in Your code, but I'm posting a proper implementation of most IImaging methods so You can check if You have the same. They're working and are checked.

    public class IImaging
    	{
    		#region stałe i struktury
    
    		public enum PixelFormatID : int
    		{
    			PixelFormatIndexed = 0x00010000,
    			PixelFormatGDI = 0x00020000,
    			PixelFormatAlpha = 0x00040000,
    			PixelFormatPAlpha = 0x00080000,
    			PixelFormatExtended = 0x00100000,
    			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
    		}
    
    		public enum BufferDisposalFlag : int
    		{
    			BufferDisposalFlagNone,
    			BufferDisposalFlagGlobalFree,
    			BufferDisposalFlagCoTaskMemFree,
    			BufferDisposalFlagUnmapView
    		}
    
    		public enum InterpolationHint : int
    		{
    			InterpolationHintDefault,
    			InterpolationHintNearestNeighbor,
    			InterpolationHintBilinear,
    			InterpolationHintAveraging,
    			InterpolationHintBicubic
    		}
    
    		public struct BitmapData
    		{
    			public uint Width;
    			public uint Height;
    			public int Stride;
    			public PixelFormatID PixelFormat;
    			public IntPtr Scan0;
    			public IntPtr Reserved;
    		}
    
    		public struct ImageInfo
    		{
    			public uint GuidPart1;
    			public uint GuidPart2;
    			public uint GuidPart3;
    			public uint GuidPart4;
    			public PixelFormatID pixelFormat;
    			public uint Width;
    			public uint Height;
    			public uint TileWidth;
    			public uint TileHeight;
    			public double Xdpi;
    			public double Ydpi;
    			public uint Flags;
    		}
    
    		#endregion
    
    		#region interfejsy
    
    		[ComImport, Guid("327ABDA7-072B-11D3-9D7B-0000F81EF32E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    		[ComVisible(true)]
    		public interface IImagingFactory
    		{
    			uint CreateImageFromStream(IStream stream, out IImage image);
    			uint CreateImageFromFile(string filename, out IImage image);
    			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(BitmapData bitmapData, out IBitmapImage bitmap);
    			uint CreateImageDecoder();	// pominięte
    			uint CreateImageEncoderToStream();	// pominięte
    			uint CreateImageEncoderToFile();	// pominięte
    			uint GetInstalledDecoders();	// pominięte
    			uint GetInstalledEncoders();	// pominięte
    			uint InstallImageCodec();	// pominięte
    			uint UninstallImageCodec();	// pominięte
    		}
    
    		[ComImport, Guid("327ABDA9-072B-11D3-9D7B-0000F81EF32E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    		[ComVisible(true)]
    		public interface IImage
    		{
    			uint GetPhysicalDimension(out Size size);
    			uint GetImageInfo(out ImageInfo info);
    			uint SetImageFlags(uint flags);
    			uint Draw(IntPtr hdc, ref Rectangle dstRect, IntPtr srcRect);
    			uint PushIntoSink();	// pominięte
    			uint GetThumbnail(uint thumbWidth, uint thumbHeight, out IImage thumbImage);
    		}
    
    		[ComImport, Guid("327ABDAA-072B-11D3-9D7B-0000F81EF32E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    		[ComVisible(true)]
    		public interface IBitmapImage
    		{
    			uint GetSize(out Size size);
    			uint GetPixelFormatID(out PixelFormatID pixelFormat);
    			uint LockBits(ref Rectangle rect, uint flags, PixelFormatID pixelFormat, out BitmapData lockedBitmapData);
    			uint UnlockBits(ref BitmapData lockedBitmapData);
    			uint GetPalette();	// pominięte
    			uint SetPalette();	// pominięte
    		}
    
    		[ComImport, Guid("0000000c-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    		[ComVisible(true)]
    		public interface IStream
    		{
    			void Read([Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pv, int cb, IntPtr pcbRead);
    			void Write([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pv, int cb, IntPtr pcbWritten);
    			void Seek(long dlibMove, int dwOrigin, IntPtr plibNewPosition);
    			void SetSize(long libNewSize);
    			void CopyTo(IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten);
    			void Commit(int grfCommitFlags);
    			void Revert();
    			void LockRegion(long libOffset, long cb, int dwLockType);
    			void UnlockRegion(long libOffset, long cb, int dwLockType);
    			void Stat();	// pominięte
    			void Clone(out IStream ppstm);
    		}
    
    		#endregion
    
    		#region metody
    
    		public static IImagingFactory CreateFactory()
    		{
    			return (IImagingFactory)Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("327ABDA8-072B-11D3-9D7B-0000F81EF32E")));
    		}
    
    		#endregion
    	}

    To check that You're using it well I'm also providing an example of how to paint a PNG onto a pictureBox control during its OnPaint event:

    private void pictureBox1_Paint(object sender, PaintEventArgs e)
    {
    	Graphics g = e.Graphics;
    	IntPtr hdc = g.GetHdc();
    
    	IImaging.IImagingFactory factory = IImaging.CreateFactory();
    	IImaging.IImage image;
    	factory.CreateImageFromFile(@"\Storage Card\test.png", out image);
    	Rectangle rect = new Rectangle(0, 0, pictureBox1.Width, pictureBox1.Height);
    	image.Draw(hdc, ref rect, IntPtr.Zero); 
    	g.ReleaseHdc(hdc);
    }

    Usually the funniest error is using control's ClientRectangle property instead of doing it exacly as You'd do in BitBlt. Check that it works and provide proper thanks :D.

    PS. Sorry for my native markup in regions.

    If You'll find my answer satisfactory or helpful - mark it as answered or vote for it! Thank You.
    "If You think You know better then me, why is Your code not working, then don't waste my time at this forum. Otherwise - do as I'm suggesting."
    • Proposed as answer by Mal Loth Tuesday, August 25, 2009 5:07 PM
    • Marked as answer by mike_pl Wednesday, August 26, 2009 12:21 PM
    Tuesday, August 25, 2009 5:06 PM

  • It's working! Thanks a lot Mal Loth!

    I've noticed minor differences between our implementations. The thing that made my code run was your definition of IImage.Draw. I've noticed that you use Rectangle instead of RECT. It turnd out i was using wrong RECT structure. The funniest thing is that the code in my first post should work fine (I used the code from one of my previous test projects because it had less experimenting in it, and thus was easier to post). The code in my first post is correct! I don't know why i started at some point using other implementation of RECT structure witch had private fields (width, height, top, left), and i think that is why IImage.Draw stopped working for me. *Sighs* I feel so dumb right now.

    Sorry for wasting your time guys.

    PS. I don't mind your native markup. There is a reason my nickname is mike_pl ;)
    • Marked as answer by mike_pl Wednesday, August 26, 2009 12:21 PM
    Wednesday, August 26, 2009 12:21 PM

All replies

  • Get HDC from the graphics (proper method) You get from event args in OnPaint event. 
    Remember to release HDC after You draw the image.

    If You'll find my answer satisfactory or helpful - mark it as answered! Thank You. PS. Votes also doesn't hurt :).
    • Proposed as answer by Mal Loth Thursday, August 6, 2009 5:49 PM
    • Marked as answer by ZHE ZHAO Wednesday, August 12, 2009 2:20 AM
    • Unmarked as answer by mike_pl Tuesday, August 25, 2009 2:29 PM
    • Unproposed as answer by mike_pl Tuesday, August 25, 2009 2:36 PM
    Thursday, August 6, 2009 5:49 PM
  • Thanks for the reply but it does not solve my problem.

    I've tried that already :)

    This is how i tested it:

    protected override void OnPaint( PaintEventArgs e )
            {
                if( _bmp != null )
                {
                    _pTarget = e.Graphics.GetHdc();
                    RECT rect = new RECT( 10, 10, 60, 60 );
                    Form1.FillRectangle( _pTarget, Color.Red, new Rectangle( 50, 50, 100, 100 ) );
                    Form1.FillRectangle( _pTarget, Color.Blue, new Rectangle( 150, 150, 200, 220 ) );
                    _bmp.Draw( _pTarget, ref rect, IntPtr.Zero );
                    e.Graphics.ReleaseHdc( _pTarget );
                    //GDIPlus.ReleaseDC( _pTarget );
                }
            }

    Again the rectangles are being drawn but not the image.

    Any other ideas?
    Tuesday, August 25, 2009 2:34 PM
  • You aren't trying to draw simple bitmap, do You? IImaging supports only JPG, GIF and PNG.
    TIFF and TGA aren't supported. If You're debugging, can You see anything in IImage class variables?

    If You'll find my answer satisfactory or helpful - mark it as answered or vote for it! Thank You.
    "If You think You know better then me, why is Your code not working, then don't waste my time at this forum. Otherwise - do as I'm suggesting."
    Tuesday, August 25, 2009 3:40 PM
  • Thanks again for answering.

    I'm trying to load a JPG image. I get much from iimage since it's a com object. Using GetImageInfo i can get the size of the image i'm trying to draw.
    Tuesday, August 25, 2009 4:45 PM
  • Don't know what's wrong in Your code, but I'm posting a proper implementation of most IImaging methods so You can check if You have the same. They're working and are checked.

    public class IImaging
    	{
    		#region stałe i struktury
    
    		public enum PixelFormatID : int
    		{
    			PixelFormatIndexed = 0x00010000,
    			PixelFormatGDI = 0x00020000,
    			PixelFormatAlpha = 0x00040000,
    			PixelFormatPAlpha = 0x00080000,
    			PixelFormatExtended = 0x00100000,
    			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
    		}
    
    		public enum BufferDisposalFlag : int
    		{
    			BufferDisposalFlagNone,
    			BufferDisposalFlagGlobalFree,
    			BufferDisposalFlagCoTaskMemFree,
    			BufferDisposalFlagUnmapView
    		}
    
    		public enum InterpolationHint : int
    		{
    			InterpolationHintDefault,
    			InterpolationHintNearestNeighbor,
    			InterpolationHintBilinear,
    			InterpolationHintAveraging,
    			InterpolationHintBicubic
    		}
    
    		public struct BitmapData
    		{
    			public uint Width;
    			public uint Height;
    			public int Stride;
    			public PixelFormatID PixelFormat;
    			public IntPtr Scan0;
    			public IntPtr Reserved;
    		}
    
    		public struct ImageInfo
    		{
    			public uint GuidPart1;
    			public uint GuidPart2;
    			public uint GuidPart3;
    			public uint GuidPart4;
    			public PixelFormatID pixelFormat;
    			public uint Width;
    			public uint Height;
    			public uint TileWidth;
    			public uint TileHeight;
    			public double Xdpi;
    			public double Ydpi;
    			public uint Flags;
    		}
    
    		#endregion
    
    		#region interfejsy
    
    		[ComImport, Guid("327ABDA7-072B-11D3-9D7B-0000F81EF32E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    		[ComVisible(true)]
    		public interface IImagingFactory
    		{
    			uint CreateImageFromStream(IStream stream, out IImage image);
    			uint CreateImageFromFile(string filename, out IImage image);
    			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(BitmapData bitmapData, out IBitmapImage bitmap);
    			uint CreateImageDecoder();	// pominięte
    			uint CreateImageEncoderToStream();	// pominięte
    			uint CreateImageEncoderToFile();	// pominięte
    			uint GetInstalledDecoders();	// pominięte
    			uint GetInstalledEncoders();	// pominięte
    			uint InstallImageCodec();	// pominięte
    			uint UninstallImageCodec();	// pominięte
    		}
    
    		[ComImport, Guid("327ABDA9-072B-11D3-9D7B-0000F81EF32E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    		[ComVisible(true)]
    		public interface IImage
    		{
    			uint GetPhysicalDimension(out Size size);
    			uint GetImageInfo(out ImageInfo info);
    			uint SetImageFlags(uint flags);
    			uint Draw(IntPtr hdc, ref Rectangle dstRect, IntPtr srcRect);
    			uint PushIntoSink();	// pominięte
    			uint GetThumbnail(uint thumbWidth, uint thumbHeight, out IImage thumbImage);
    		}
    
    		[ComImport, Guid("327ABDAA-072B-11D3-9D7B-0000F81EF32E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    		[ComVisible(true)]
    		public interface IBitmapImage
    		{
    			uint GetSize(out Size size);
    			uint GetPixelFormatID(out PixelFormatID pixelFormat);
    			uint LockBits(ref Rectangle rect, uint flags, PixelFormatID pixelFormat, out BitmapData lockedBitmapData);
    			uint UnlockBits(ref BitmapData lockedBitmapData);
    			uint GetPalette();	// pominięte
    			uint SetPalette();	// pominięte
    		}
    
    		[ComImport, Guid("0000000c-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    		[ComVisible(true)]
    		public interface IStream
    		{
    			void Read([Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pv, int cb, IntPtr pcbRead);
    			void Write([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pv, int cb, IntPtr pcbWritten);
    			void Seek(long dlibMove, int dwOrigin, IntPtr plibNewPosition);
    			void SetSize(long libNewSize);
    			void CopyTo(IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten);
    			void Commit(int grfCommitFlags);
    			void Revert();
    			void LockRegion(long libOffset, long cb, int dwLockType);
    			void UnlockRegion(long libOffset, long cb, int dwLockType);
    			void Stat();	// pominięte
    			void Clone(out IStream ppstm);
    		}
    
    		#endregion
    
    		#region metody
    
    		public static IImagingFactory CreateFactory()
    		{
    			return (IImagingFactory)Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("327ABDA8-072B-11D3-9D7B-0000F81EF32E")));
    		}
    
    		#endregion
    	}

    To check that You're using it well I'm also providing an example of how to paint a PNG onto a pictureBox control during its OnPaint event:

    private void pictureBox1_Paint(object sender, PaintEventArgs e)
    {
    	Graphics g = e.Graphics;
    	IntPtr hdc = g.GetHdc();
    
    	IImaging.IImagingFactory factory = IImaging.CreateFactory();
    	IImaging.IImage image;
    	factory.CreateImageFromFile(@"\Storage Card\test.png", out image);
    	Rectangle rect = new Rectangle(0, 0, pictureBox1.Width, pictureBox1.Height);
    	image.Draw(hdc, ref rect, IntPtr.Zero); 
    	g.ReleaseHdc(hdc);
    }

    Usually the funniest error is using control's ClientRectangle property instead of doing it exacly as You'd do in BitBlt. Check that it works and provide proper thanks :D.

    PS. Sorry for my native markup in regions.

    If You'll find my answer satisfactory or helpful - mark it as answered or vote for it! Thank You.
    "If You think You know better then me, why is Your code not working, then don't waste my time at this forum. Otherwise - do as I'm suggesting."
    • Proposed as answer by Mal Loth Tuesday, August 25, 2009 5:07 PM
    • Marked as answer by mike_pl Wednesday, August 26, 2009 12:21 PM
    Tuesday, August 25, 2009 5:06 PM

  • It's working! Thanks a lot Mal Loth!

    I've noticed minor differences between our implementations. The thing that made my code run was your definition of IImage.Draw. I've noticed that you use Rectangle instead of RECT. It turnd out i was using wrong RECT structure. The funniest thing is that the code in my first post should work fine (I used the code from one of my previous test projects because it had less experimenting in it, and thus was easier to post). The code in my first post is correct! I don't know why i started at some point using other implementation of RECT structure witch had private fields (width, height, top, left), and i think that is why IImage.Draw stopped working for me. *Sighs* I feel so dumb right now.

    Sorry for wasting your time guys.

    PS. I don't mind your native markup. There is a reason my nickname is mike_pl ;)
    • Marked as answer by mike_pl Wednesday, August 26, 2009 12:21 PM
    Wednesday, August 26, 2009 12:21 PM
  • No problem. I'm here to help :). Glad to see a "native face" in this forum :).
    If You'll find my answer satisfactory or helpful - mark it as answered or vote for it! Thank You.
    "If You think You know better then me, why is Your code not working, then don't waste my time at this forum. Otherwise - do as I'm suggesting."
    Wednesday, August 26, 2009 7:28 PM
  • Hi,

     

    What if I need to draw only a specific portion of the image instead of passing a IntPtr.Zero as scrRect? How should it be done?

    I've tried to change the IImage Draw declaration like the following but it doesn't work:

    "uint Draw(IntPtr hdc, ref Rectangle dstRect, ref Rectangle srcRect);"

     

    thanks,

    Monday, October 4, 2010 2:09 PM
  • Check your units on that rectangle.... (the documentation for IImage they are supposed to be in like 0.1 mm units I think)

     

    The code for this is laying around the forums somewhere.. but never fear, I found them for you... I believe originally from Alex Feinman... but never fear, here is what I use, which I may have modified some..

     

    public static class Imaging
            {
                public static RECT ConvertToSrcRectUnits(RECT rectangle, ImageInfo info)
                {
                    double scaleFactorX = 1 / info.Xdpi * 2540;
                    double scaleFactorY = 1 / info.Ydpi * 2540;
                    rectangle.Left = (int)Math.Round(rectangle.Left * scaleFactorX);
                    rectangle.Right = (int)Math.Round(rectangle.Right * scaleFactorX);
                    rectangle.Top = (int)Math.Round(rectangle.Top * scaleFactorY);
                    rectangle.Bottom = (int)Math.Round(rectangle.Bottom * scaleFactorY);
                    return rectangle;
                }

                public static RECT ConvertToSrcRectUnits(Rectangle rectangle, ImageInfo info)
                {
                    RECT srcRect;
                    double scaleFactorX = 1 / info.Xdpi * 2540;
                    double scaleFactorY = 1 / info.Ydpi * 2540;
                    srcRect.Left = (int)Math.Round(rectangle.Left * scaleFactorX);
                    srcRect.Right = (int)Math.Round(rectangle.Right * scaleFactorX);
                    srcRect.Top = (int)Math.Round(rectangle.Top * scaleFactorY);
                    srcRect.Bottom = (int)Math.Round(rectangle.Bottom * scaleFactorY);
                    return srcRect;
                }
            }

    // from IImage interface  (you may also try ref or other things if you do not want to user pointers... but I think for my purpose pointers were the best)

    uint Draw(IntPtr hdc, RECT* dstRect, RECT* srcRect);

     

    // this is my RECT struct

    public struct RECT
        {
            public static RECT GetRect(Rectangle r)
            {
                RECT temp;
                temp.Left = r.Left;
                temp.Right = r.Right;
                temp.Top = r.Top;
                temp.Bottom = r.Bottom;
                return temp;
            }

            public int Left;
            public int Top;
            public int Right;
            public int Bottom;

            public int Width
            {
                get
                {
                    return Right - Left;
                }
            }
            public int Height
            {
                get
                {
                    return Bottom - Top;
                }
            }
            public void Translate(int x, int y)
            {
                Left += x;
                Right += x;
                Top += y;
                Bottom += y;
            }
            public void Inflate(int width, int height)
            {
                Left -= width;
                Top -= height;
                Right += width;
                Bottom += height;
            }
            public void Extend(int width, int height)
            {
                Right += width;
                Bottom += height;
            }
            public bool IntersectsWith(Rectangle rect)
            {
                return ((((rect.X < (this.Right)) && (this.Left < (rect.Right))) && (rect.Y < (this.Bottom))) && (this.Top < (rect.Bottom)));
            }
            public RECT(int left, int top, int right, int bottom)
            {
                Left = left;
                Top = top;
                Right = right;
                Bottom = bottom;
            }
        }

     

    • Proposed as answer by Alan M_ Monday, October 4, 2010 6:42 PM
    Monday, October 4, 2010 6:42 PM