C# Move bitmap in picturebox
I create image with LockBits from array in cycle and scale to PictureBox.Width * n and Height:
using (var bmp = new Bitmap(len, _height, PixelFormat.Format24bppRgb))
{
var data = bmp.LockBits(new Rectangle(0, 0, len, _height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
var bytes = data.Stride * data.Height;
var rgb = new byte[bytes];
var ptr = data.Scan0;
Marshal.Copy(data.Scan0, rgb, 0, bytes);
// …fill array „rgb“
Marshal.Copy(rgb, 0, ptr, bytes);
bmp.UnlockBits(data);
g = _pictureBox.CreateGraphics();
g.InterpolationMode = InterpolationMode.Default;
g.DrawImage(bmp, _pictureBox.Width - len * _scaleWidth, 0, len * _scaleWidth, _pictureBox.Height);
}
In the next iterateration:
Graphics g;
using (var bmp = new Bitmap(_pictureBox.Image))
{
g = _pictureBox.CreateGraphics();
g.InterpolationMode = InterpolationMode.Default;
g.DrawImage(_pictureBox.Image, new RectangleF(0, 0, _pictureBox.Width - len * _scaleWidth, _pictureBox.Height), new RectangleF(len * _scaleWidth, 0, _pictureBox.Width * _scaleWidth - len, _height), GraphicsUnit.Pixel);
}
g.Dispose();
In short: I cut and copy part of the image that would shift the picture, but do not get anything. Is it possible because of the scale in the previous step?
Maybe I'm wrong. Advise the algorithm for shifting and adding a new Bitmap into an end.
c# bitmap interpolation drawimage lockbits
add a comment |
I create image with LockBits from array in cycle and scale to PictureBox.Width * n and Height:
using (var bmp = new Bitmap(len, _height, PixelFormat.Format24bppRgb))
{
var data = bmp.LockBits(new Rectangle(0, 0, len, _height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
var bytes = data.Stride * data.Height;
var rgb = new byte[bytes];
var ptr = data.Scan0;
Marshal.Copy(data.Scan0, rgb, 0, bytes);
// …fill array „rgb“
Marshal.Copy(rgb, 0, ptr, bytes);
bmp.UnlockBits(data);
g = _pictureBox.CreateGraphics();
g.InterpolationMode = InterpolationMode.Default;
g.DrawImage(bmp, _pictureBox.Width - len * _scaleWidth, 0, len * _scaleWidth, _pictureBox.Height);
}
In the next iterateration:
Graphics g;
using (var bmp = new Bitmap(_pictureBox.Image))
{
g = _pictureBox.CreateGraphics();
g.InterpolationMode = InterpolationMode.Default;
g.DrawImage(_pictureBox.Image, new RectangleF(0, 0, _pictureBox.Width - len * _scaleWidth, _pictureBox.Height), new RectangleF(len * _scaleWidth, 0, _pictureBox.Width * _scaleWidth - len, _height), GraphicsUnit.Pixel);
}
g.Dispose();
In short: I cut and copy part of the image that would shift the picture, but do not get anything. Is it possible because of the scale in the previous step?
Maybe I'm wrong. Advise the algorithm for shifting and adding a new Bitmap into an end.
c# bitmap interpolation drawimage lockbits
1
You have to assign the Bitmap to the _pictureBox.Image property first, than assigning to it as nessecary. I advice you to use Control.CreateGraphics() method and write on a Form directly.
– Artur Mustafin
Sep 20 '11 at 6:44
You can pin miage to the mouse pointer, and subscribe to the mouse movements other the bitmap while left button is pressed on a form, by attaching to the MouseClick and MouseMove event on a control, in which you can use my Win32 Interop. I will edit my post to add the sample.
– Artur Mustafin
Sep 20 '11 at 7:05
add a comment |
I create image with LockBits from array in cycle and scale to PictureBox.Width * n and Height:
using (var bmp = new Bitmap(len, _height, PixelFormat.Format24bppRgb))
{
var data = bmp.LockBits(new Rectangle(0, 0, len, _height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
var bytes = data.Stride * data.Height;
var rgb = new byte[bytes];
var ptr = data.Scan0;
Marshal.Copy(data.Scan0, rgb, 0, bytes);
// …fill array „rgb“
Marshal.Copy(rgb, 0, ptr, bytes);
bmp.UnlockBits(data);
g = _pictureBox.CreateGraphics();
g.InterpolationMode = InterpolationMode.Default;
g.DrawImage(bmp, _pictureBox.Width - len * _scaleWidth, 0, len * _scaleWidth, _pictureBox.Height);
}
In the next iterateration:
Graphics g;
using (var bmp = new Bitmap(_pictureBox.Image))
{
g = _pictureBox.CreateGraphics();
g.InterpolationMode = InterpolationMode.Default;
g.DrawImage(_pictureBox.Image, new RectangleF(0, 0, _pictureBox.Width - len * _scaleWidth, _pictureBox.Height), new RectangleF(len * _scaleWidth, 0, _pictureBox.Width * _scaleWidth - len, _height), GraphicsUnit.Pixel);
}
g.Dispose();
In short: I cut and copy part of the image that would shift the picture, but do not get anything. Is it possible because of the scale in the previous step?
Maybe I'm wrong. Advise the algorithm for shifting and adding a new Bitmap into an end.
c# bitmap interpolation drawimage lockbits
I create image with LockBits from array in cycle and scale to PictureBox.Width * n and Height:
using (var bmp = new Bitmap(len, _height, PixelFormat.Format24bppRgb))
{
var data = bmp.LockBits(new Rectangle(0, 0, len, _height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
var bytes = data.Stride * data.Height;
var rgb = new byte[bytes];
var ptr = data.Scan0;
Marshal.Copy(data.Scan0, rgb, 0, bytes);
// …fill array „rgb“
Marshal.Copy(rgb, 0, ptr, bytes);
bmp.UnlockBits(data);
g = _pictureBox.CreateGraphics();
g.InterpolationMode = InterpolationMode.Default;
g.DrawImage(bmp, _pictureBox.Width - len * _scaleWidth, 0, len * _scaleWidth, _pictureBox.Height);
}
In the next iterateration:
Graphics g;
using (var bmp = new Bitmap(_pictureBox.Image))
{
g = _pictureBox.CreateGraphics();
g.InterpolationMode = InterpolationMode.Default;
g.DrawImage(_pictureBox.Image, new RectangleF(0, 0, _pictureBox.Width - len * _scaleWidth, _pictureBox.Height), new RectangleF(len * _scaleWidth, 0, _pictureBox.Width * _scaleWidth - len, _height), GraphicsUnit.Pixel);
}
g.Dispose();
In short: I cut and copy part of the image that would shift the picture, but do not get anything. Is it possible because of the scale in the previous step?
Maybe I'm wrong. Advise the algorithm for shifting and adding a new Bitmap into an end.
c# bitmap interpolation drawimage lockbits
c# bitmap interpolation drawimage lockbits
asked Sep 20 '11 at 6:30
Kir
130210
130210
1
You have to assign the Bitmap to the _pictureBox.Image property first, than assigning to it as nessecary. I advice you to use Control.CreateGraphics() method and write on a Form directly.
– Artur Mustafin
Sep 20 '11 at 6:44
You can pin miage to the mouse pointer, and subscribe to the mouse movements other the bitmap while left button is pressed on a form, by attaching to the MouseClick and MouseMove event on a control, in which you can use my Win32 Interop. I will edit my post to add the sample.
– Artur Mustafin
Sep 20 '11 at 7:05
add a comment |
1
You have to assign the Bitmap to the _pictureBox.Image property first, than assigning to it as nessecary. I advice you to use Control.CreateGraphics() method and write on a Form directly.
– Artur Mustafin
Sep 20 '11 at 6:44
You can pin miage to the mouse pointer, and subscribe to the mouse movements other the bitmap while left button is pressed on a form, by attaching to the MouseClick and MouseMove event on a control, in which you can use my Win32 Interop. I will edit my post to add the sample.
– Artur Mustafin
Sep 20 '11 at 7:05
1
1
You have to assign the Bitmap to the _pictureBox.Image property first, than assigning to it as nessecary. I advice you to use Control.CreateGraphics() method and write on a Form directly.
– Artur Mustafin
Sep 20 '11 at 6:44
You have to assign the Bitmap to the _pictureBox.Image property first, than assigning to it as nessecary. I advice you to use Control.CreateGraphics() method and write on a Form directly.
– Artur Mustafin
Sep 20 '11 at 6:44
You can pin miage to the mouse pointer, and subscribe to the mouse movements other the bitmap while left button is pressed on a form, by attaching to the MouseClick and MouseMove event on a control, in which you can use my Win32 Interop. I will edit my post to add the sample.
– Artur Mustafin
Sep 20 '11 at 7:05
You can pin miage to the mouse pointer, and subscribe to the mouse movements other the bitmap while left button is pressed on a form, by attaching to the MouseClick and MouseMove event on a control, in which you can use my Win32 Interop. I will edit my post to add the sample.
– Artur Mustafin
Sep 20 '11 at 7:05
add a comment |
2 Answers
2
active
oldest
votes
I advice you to use Control.CreateGraphics() method at Form instance, and write on a Form directly, because PaintBox control is quite slow.
Try using my helper function, this will allow you to paste a portion of your bitmap using StretchBlt (stretching) or BitBlt (no stretching) using Win32 Interop:
Sample usage:
Graphics graphics = ...;
graphics.GdiDrawImage
(
image,
new Rectangle(
(int)rectangle.Left,
(int)rectangle.Top,
(int)rectangle.Width,
(int)rectangle.Height
),
0, 0, image.Width, image.Height
);
Source code:
public static class GraphicsHelper
{
public static void GdiDrawImage(this Graphics graphics, Bitmap image, Rectangle rectangleDst, int nXSrc, int nYSrc, int nWidth, int nHeight)
{
IntPtr hdc = graphics.GetHdc();
IntPtr memdc = GdiInterop.CreateCompatibleDC(hdc);
IntPtr bmp = image.GetHbitmap();
GdiInterop.SelectObject(memdc, bmp);
GdiInterop.SetStretchBltMode(hdc, 0x04);
GdiInterop.StretchBlt(hdc, rectangleDst.Left, rectangleDst.Top, rectangleDst.Width, rectangleDst.Height, memdc, nXSrc, nYSrc, nWidth, nHeight, GdiInterop.TernaryRasterOperations.SRCCOPY);
//GdiInterop.BitBlt(..) put it here, if you did not mention stretching the source image
GdiInterop.DeleteObject(bmp);
GdiInterop.DeleteDC(memdc);
graphics.ReleaseHdc(hdc);
}
}
public class GdiInterop
{
/// <summary>
/// Enumeration for the raster operations used in BitBlt.
/// In C++ these are actually #define. But to use these
/// constants with C#, a new enumeration _type is defined.
/// </summary>
public enum TernaryRasterOperations
{
SRCCOPY = 0x00CC0020, // dest = source
SRCPAINT = 0x00EE0086, // dest = source OR dest
SRCAND = 0x008800C6, // dest = source AND dest
SRCINVERT = 0x00660046, // dest = source XOR dest
SRCERASE = 0x00440328, // dest = source AND (NOT dest)
NOTSRCCOPY = 0x00330008, // dest = (NOT source)
NOTSRCERASE = 0x001100A6, // dest = (NOT src) AND (NOT dest)
MERGECOPY = 0x00C000CA, // dest = (source AND pattern)
MERGEPAINT = 0x00BB0226, // dest = (NOT source) OR dest
PATCOPY = 0x00F00021, // dest = pattern
PATPAINT = 0x00FB0A09, // dest = DPSnoo
PATINVERT = 0x005A0049, // dest = pattern XOR dest
DSTINVERT = 0x00550009, // dest = (NOT dest)
BLACKNESS = 0x00000042, // dest = BLACK
WHITENESS = 0x00FF0062, // dest = WHITE
};
/// <summary>
/// Enumeration to be used for those Win32 function
/// that return BOOL
/// </summary>
public enum Bool
{
False = 0,
True
};
/// <summary>
/// Sets the background color.
/// </summary>
/// <param name="hdc">The HDC.</param>
/// <param name="crColor">Color of the cr.</param>
/// <returns></returns>
[DllImport("gdi32.dll")]
public static extern int SetBkColor(IntPtr hdc, int crColor);
/// <summary>
/// CreateCompatibleDC
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
/// <summary>
/// DeleteDC
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool DeleteDC(IntPtr hdc);
/// <summary>
/// SelectObject
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true)]
public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
/// <summary>
/// DeleteObject
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool DeleteObject(IntPtr hObject);
/// <summary>
/// CreateCompatibleBitmap
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern IntPtr CreateCompatibleBitmap(IntPtr hObject, int width, int height);
/// <summary>
/// BitBlt
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool BitBlt(IntPtr hObject, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hObjSource, int nXSrc, int nYSrc, TernaryRasterOperations dwRop);
/// <summary>
/// StretchBlt
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool StretchBlt(IntPtr hObject, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest, IntPtr hObjSource, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, TernaryRasterOperations dwRop);
/// <summary>
/// SetStretchBltMode
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool SetStretchBltMode(IntPtr hObject, int nStretchMode);
}
GetHbitmapcreates a copy of the bitmap data. This may be an issue when using large bitmaps like 10k x 10k RGB, which are around 400MB large: There will be the originalBitmapobject of this size and then another "GDI bitmap" of the same size. This will almost never work in a 32 bit process, 64bit is required then: stackoverflow.com/a/11559001
– Tobias Knauss
Nov 9 at 16:08
add a comment |
Notice: This is no full answer to the question, but I want to provide some useful information to the existing answer.
In contrast to the answer of Artur Mustafin, I suggest not to use the Windows GDI directly, but to use the .net methods of the Graphics class. In my tests they have performed a lot better than the GDI functions.
The GDI code is taken from the answer of Artur Mustafin.
The test was displaying an image of 1Mpix (1k x 1k) Bitmap or 100Mpix (10k x 10k) Bitmap in 1k x 1k Picturebox by drawing in the Paint event.
The tests were done in Visual Studio 2015.3 on Windows 7 Pro x64 SP1, Debug mode, on an Intel Core i7-3630QM CPU @ 2.4 GHz, 16 GB RAM.
Results:
1000x Graphics.DrawImage() unscaled of 100M Bitmap: 36.8s (x86), 24.2s (x64).
1000x Graphics.DrawImage() unscaled of 1M Bitmap: 5.2s (x86), 3.8s (x64).
100x Graphics.DrawImage() scaled of 100M Bitmap: 62.8s (x86), 39.0s (x64).
1000x Graphics.DrawImage() scaled of 1M Bitmap: 5.2s (x86), 3.8s (x64).
100x GdiDrawImage() StretchBlockTransfer of 100M Bitmap: OutOfMem@x86, 88.5s (x64).
1000x GdiDrawImage() StretchBlockTransfer of 1M Bitmap: 12.9s (x86), 11.5s (x64).
100x GdiDrawImage() BitBlockTransfer of 100M Bitmap: OutOfMem@x86, 49.7s (x64).
1000x GdiDrawImage() BitBlockTransfer of 1M Bitmap: 7.2s (x86), 5.8s (x64).
Test code:
public partial class FormPictureboxPaint : Form
{
private Bitmap m_oBitmap;
public FormPictureboxPaint ()
{
InitializeComponent ();
string sFile = Application.StartupPath + @"......bitmap.png"; // The bitmap file contains an image with 10k x 10k pixels.
m_oBitmap = new Bitmap (sFile);
if (false) // CHANGE TO TRUE IF TESTING WITH 1k x 1k BITMAPS
{
var oBitmap = new Bitmap (m_oBitmap, new Size (1000, 1000));
m_oBitmap.Dispose ();
m_oBitmap = null;
GC.Collect ();
GC.WaitForFullGCComplete ();
GC.WaitForPendingFinalizers ();
m_oBitmap = oBitmap;
}
}
private void pictureBox1_Paint (object sender, PaintEventArgs e)
{
var oGraphics = e.Graphics;
DateTime dtNow = DateTime.Now;
// UNCOMMENT THE FOLLOWING LINES FOR TESTS WITH DrawImage
// COMMENT THE FOLLOWING LINES FOR TESTS WITH GDI
//for (int ixCnt = 0; ixCnt < 1000; ixCnt++)
// PictureboxPaint01 (oGraphics);
// COMMENT THE FOLLOWING LINES FOR TESTS WITH DrawImage
// UNCOMMENT THE FOLLOWING LINES FOR TESTS WITH GDI
for (int ixCnt = 0; ixCnt < 100; ixCnt++)
PictureboxPaint02 (oGraphics);
TimeSpan ts = (DateTime.Now - dtNow);
}
private void PictureboxPaint01 (Graphics i_oGraphics)
{
//_oGraphics.DrawImage (m_oBitmap, new Point ());
i_oGraphics.DrawImage (m_oBitmap, new Rectangle (0, 0, 1000, 1000));
}
private void PictureboxPaint02 (Graphics i_oGraphics)
{
// from https://stackoverflow.com/a/7481071
i_oGraphics.GdiDrawImage
(
m_oBitmap,
new Rectangle (
(int)pictureBox1.Left,
(int)pictureBox1.Top,
(int)pictureBox1.Width,
(int)pictureBox1.Height
),
0, 0, m_oBitmap.Width, m_oBitmap.Height
);
}
}
public static class GraphicsHelper
{
public static void GdiDrawImage (this Graphics graphics, Bitmap image, Rectangle rectangleDst, int nXSrc, int nYSrc, int nWidth, int nHeight)
{
IntPtr hdc = graphics.GetHdc ();
IntPtr memdc = GdiInterop.CreateCompatibleDC (hdc);
IntPtr bmp = image.GetHbitmap ();
GdiInterop.SelectObject (memdc, bmp);
GdiInterop.SetStretchBltMode (hdc, 0x04);
GdiInterop.StretchBlt (hdc, rectangleDst.Left, rectangleDst.Top, rectangleDst.Width, rectangleDst.Height, memdc, nXSrc, nYSrc, nWidth, nHeight, GdiInterop.TernaryRasterOperations.SRCCOPY);
//GdiInterop.BitBlt (hdc, rectangleDst.Left, rectangleDst.Top, rectangleDst.Width, rectangleDst.Height, memdc, nXSrc, nYSrc, GdiInterop.TernaryRasterOperations.SRCCOPY); //put it here, if you did not mention stretching the source image
GdiInterop.DeleteObject (bmp);
GdiInterop.DeleteDC (memdc);
graphics.ReleaseHdc (hdc);
}
}
public class GdiInterop
{
public enum TernaryRasterOperations
{
SRCCOPY = 0x00CC0020, // dest = source
};
public enum Bool
{
False = 0,
True
};
[DllImport ("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern IntPtr CreateCompatibleDC (IntPtr hDC);
[DllImport ("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool DeleteDC (IntPtr hdc);
[DllImport ("gdi32.dll", ExactSpelling = true)]
public static extern IntPtr SelectObject (IntPtr hDC, IntPtr hObject);
[DllImport ("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool DeleteObject (IntPtr hObject);
[DllImport ("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool BitBlt (IntPtr hObject, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hObjSource, int nXSrc, int nYSrc, TernaryRasterOperations dwRop);
[DllImport ("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool StretchBlt (IntPtr hObject, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest, IntPtr hObjSource, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, TernaryRasterOperations dwRop);
[DllImport ("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool SetStretchBltMode (IntPtr hObject, int nStretchMode);
}
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f7481004%2fc-sharp-move-bitmap-in-picturebox%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
I advice you to use Control.CreateGraphics() method at Form instance, and write on a Form directly, because PaintBox control is quite slow.
Try using my helper function, this will allow you to paste a portion of your bitmap using StretchBlt (stretching) or BitBlt (no stretching) using Win32 Interop:
Sample usage:
Graphics graphics = ...;
graphics.GdiDrawImage
(
image,
new Rectangle(
(int)rectangle.Left,
(int)rectangle.Top,
(int)rectangle.Width,
(int)rectangle.Height
),
0, 0, image.Width, image.Height
);
Source code:
public static class GraphicsHelper
{
public static void GdiDrawImage(this Graphics graphics, Bitmap image, Rectangle rectangleDst, int nXSrc, int nYSrc, int nWidth, int nHeight)
{
IntPtr hdc = graphics.GetHdc();
IntPtr memdc = GdiInterop.CreateCompatibleDC(hdc);
IntPtr bmp = image.GetHbitmap();
GdiInterop.SelectObject(memdc, bmp);
GdiInterop.SetStretchBltMode(hdc, 0x04);
GdiInterop.StretchBlt(hdc, rectangleDst.Left, rectangleDst.Top, rectangleDst.Width, rectangleDst.Height, memdc, nXSrc, nYSrc, nWidth, nHeight, GdiInterop.TernaryRasterOperations.SRCCOPY);
//GdiInterop.BitBlt(..) put it here, if you did not mention stretching the source image
GdiInterop.DeleteObject(bmp);
GdiInterop.DeleteDC(memdc);
graphics.ReleaseHdc(hdc);
}
}
public class GdiInterop
{
/// <summary>
/// Enumeration for the raster operations used in BitBlt.
/// In C++ these are actually #define. But to use these
/// constants with C#, a new enumeration _type is defined.
/// </summary>
public enum TernaryRasterOperations
{
SRCCOPY = 0x00CC0020, // dest = source
SRCPAINT = 0x00EE0086, // dest = source OR dest
SRCAND = 0x008800C6, // dest = source AND dest
SRCINVERT = 0x00660046, // dest = source XOR dest
SRCERASE = 0x00440328, // dest = source AND (NOT dest)
NOTSRCCOPY = 0x00330008, // dest = (NOT source)
NOTSRCERASE = 0x001100A6, // dest = (NOT src) AND (NOT dest)
MERGECOPY = 0x00C000CA, // dest = (source AND pattern)
MERGEPAINT = 0x00BB0226, // dest = (NOT source) OR dest
PATCOPY = 0x00F00021, // dest = pattern
PATPAINT = 0x00FB0A09, // dest = DPSnoo
PATINVERT = 0x005A0049, // dest = pattern XOR dest
DSTINVERT = 0x00550009, // dest = (NOT dest)
BLACKNESS = 0x00000042, // dest = BLACK
WHITENESS = 0x00FF0062, // dest = WHITE
};
/// <summary>
/// Enumeration to be used for those Win32 function
/// that return BOOL
/// </summary>
public enum Bool
{
False = 0,
True
};
/// <summary>
/// Sets the background color.
/// </summary>
/// <param name="hdc">The HDC.</param>
/// <param name="crColor">Color of the cr.</param>
/// <returns></returns>
[DllImport("gdi32.dll")]
public static extern int SetBkColor(IntPtr hdc, int crColor);
/// <summary>
/// CreateCompatibleDC
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
/// <summary>
/// DeleteDC
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool DeleteDC(IntPtr hdc);
/// <summary>
/// SelectObject
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true)]
public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
/// <summary>
/// DeleteObject
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool DeleteObject(IntPtr hObject);
/// <summary>
/// CreateCompatibleBitmap
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern IntPtr CreateCompatibleBitmap(IntPtr hObject, int width, int height);
/// <summary>
/// BitBlt
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool BitBlt(IntPtr hObject, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hObjSource, int nXSrc, int nYSrc, TernaryRasterOperations dwRop);
/// <summary>
/// StretchBlt
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool StretchBlt(IntPtr hObject, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest, IntPtr hObjSource, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, TernaryRasterOperations dwRop);
/// <summary>
/// SetStretchBltMode
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool SetStretchBltMode(IntPtr hObject, int nStretchMode);
}
GetHbitmapcreates a copy of the bitmap data. This may be an issue when using large bitmaps like 10k x 10k RGB, which are around 400MB large: There will be the originalBitmapobject of this size and then another "GDI bitmap" of the same size. This will almost never work in a 32 bit process, 64bit is required then: stackoverflow.com/a/11559001
– Tobias Knauss
Nov 9 at 16:08
add a comment |
I advice you to use Control.CreateGraphics() method at Form instance, and write on a Form directly, because PaintBox control is quite slow.
Try using my helper function, this will allow you to paste a portion of your bitmap using StretchBlt (stretching) or BitBlt (no stretching) using Win32 Interop:
Sample usage:
Graphics graphics = ...;
graphics.GdiDrawImage
(
image,
new Rectangle(
(int)rectangle.Left,
(int)rectangle.Top,
(int)rectangle.Width,
(int)rectangle.Height
),
0, 0, image.Width, image.Height
);
Source code:
public static class GraphicsHelper
{
public static void GdiDrawImage(this Graphics graphics, Bitmap image, Rectangle rectangleDst, int nXSrc, int nYSrc, int nWidth, int nHeight)
{
IntPtr hdc = graphics.GetHdc();
IntPtr memdc = GdiInterop.CreateCompatibleDC(hdc);
IntPtr bmp = image.GetHbitmap();
GdiInterop.SelectObject(memdc, bmp);
GdiInterop.SetStretchBltMode(hdc, 0x04);
GdiInterop.StretchBlt(hdc, rectangleDst.Left, rectangleDst.Top, rectangleDst.Width, rectangleDst.Height, memdc, nXSrc, nYSrc, nWidth, nHeight, GdiInterop.TernaryRasterOperations.SRCCOPY);
//GdiInterop.BitBlt(..) put it here, if you did not mention stretching the source image
GdiInterop.DeleteObject(bmp);
GdiInterop.DeleteDC(memdc);
graphics.ReleaseHdc(hdc);
}
}
public class GdiInterop
{
/// <summary>
/// Enumeration for the raster operations used in BitBlt.
/// In C++ these are actually #define. But to use these
/// constants with C#, a new enumeration _type is defined.
/// </summary>
public enum TernaryRasterOperations
{
SRCCOPY = 0x00CC0020, // dest = source
SRCPAINT = 0x00EE0086, // dest = source OR dest
SRCAND = 0x008800C6, // dest = source AND dest
SRCINVERT = 0x00660046, // dest = source XOR dest
SRCERASE = 0x00440328, // dest = source AND (NOT dest)
NOTSRCCOPY = 0x00330008, // dest = (NOT source)
NOTSRCERASE = 0x001100A6, // dest = (NOT src) AND (NOT dest)
MERGECOPY = 0x00C000CA, // dest = (source AND pattern)
MERGEPAINT = 0x00BB0226, // dest = (NOT source) OR dest
PATCOPY = 0x00F00021, // dest = pattern
PATPAINT = 0x00FB0A09, // dest = DPSnoo
PATINVERT = 0x005A0049, // dest = pattern XOR dest
DSTINVERT = 0x00550009, // dest = (NOT dest)
BLACKNESS = 0x00000042, // dest = BLACK
WHITENESS = 0x00FF0062, // dest = WHITE
};
/// <summary>
/// Enumeration to be used for those Win32 function
/// that return BOOL
/// </summary>
public enum Bool
{
False = 0,
True
};
/// <summary>
/// Sets the background color.
/// </summary>
/// <param name="hdc">The HDC.</param>
/// <param name="crColor">Color of the cr.</param>
/// <returns></returns>
[DllImport("gdi32.dll")]
public static extern int SetBkColor(IntPtr hdc, int crColor);
/// <summary>
/// CreateCompatibleDC
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
/// <summary>
/// DeleteDC
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool DeleteDC(IntPtr hdc);
/// <summary>
/// SelectObject
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true)]
public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
/// <summary>
/// DeleteObject
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool DeleteObject(IntPtr hObject);
/// <summary>
/// CreateCompatibleBitmap
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern IntPtr CreateCompatibleBitmap(IntPtr hObject, int width, int height);
/// <summary>
/// BitBlt
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool BitBlt(IntPtr hObject, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hObjSource, int nXSrc, int nYSrc, TernaryRasterOperations dwRop);
/// <summary>
/// StretchBlt
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool StretchBlt(IntPtr hObject, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest, IntPtr hObjSource, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, TernaryRasterOperations dwRop);
/// <summary>
/// SetStretchBltMode
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool SetStretchBltMode(IntPtr hObject, int nStretchMode);
}
GetHbitmapcreates a copy of the bitmap data. This may be an issue when using large bitmaps like 10k x 10k RGB, which are around 400MB large: There will be the originalBitmapobject of this size and then another "GDI bitmap" of the same size. This will almost never work in a 32 bit process, 64bit is required then: stackoverflow.com/a/11559001
– Tobias Knauss
Nov 9 at 16:08
add a comment |
I advice you to use Control.CreateGraphics() method at Form instance, and write on a Form directly, because PaintBox control is quite slow.
Try using my helper function, this will allow you to paste a portion of your bitmap using StretchBlt (stretching) or BitBlt (no stretching) using Win32 Interop:
Sample usage:
Graphics graphics = ...;
graphics.GdiDrawImage
(
image,
new Rectangle(
(int)rectangle.Left,
(int)rectangle.Top,
(int)rectangle.Width,
(int)rectangle.Height
),
0, 0, image.Width, image.Height
);
Source code:
public static class GraphicsHelper
{
public static void GdiDrawImage(this Graphics graphics, Bitmap image, Rectangle rectangleDst, int nXSrc, int nYSrc, int nWidth, int nHeight)
{
IntPtr hdc = graphics.GetHdc();
IntPtr memdc = GdiInterop.CreateCompatibleDC(hdc);
IntPtr bmp = image.GetHbitmap();
GdiInterop.SelectObject(memdc, bmp);
GdiInterop.SetStretchBltMode(hdc, 0x04);
GdiInterop.StretchBlt(hdc, rectangleDst.Left, rectangleDst.Top, rectangleDst.Width, rectangleDst.Height, memdc, nXSrc, nYSrc, nWidth, nHeight, GdiInterop.TernaryRasterOperations.SRCCOPY);
//GdiInterop.BitBlt(..) put it here, if you did not mention stretching the source image
GdiInterop.DeleteObject(bmp);
GdiInterop.DeleteDC(memdc);
graphics.ReleaseHdc(hdc);
}
}
public class GdiInterop
{
/// <summary>
/// Enumeration for the raster operations used in BitBlt.
/// In C++ these are actually #define. But to use these
/// constants with C#, a new enumeration _type is defined.
/// </summary>
public enum TernaryRasterOperations
{
SRCCOPY = 0x00CC0020, // dest = source
SRCPAINT = 0x00EE0086, // dest = source OR dest
SRCAND = 0x008800C6, // dest = source AND dest
SRCINVERT = 0x00660046, // dest = source XOR dest
SRCERASE = 0x00440328, // dest = source AND (NOT dest)
NOTSRCCOPY = 0x00330008, // dest = (NOT source)
NOTSRCERASE = 0x001100A6, // dest = (NOT src) AND (NOT dest)
MERGECOPY = 0x00C000CA, // dest = (source AND pattern)
MERGEPAINT = 0x00BB0226, // dest = (NOT source) OR dest
PATCOPY = 0x00F00021, // dest = pattern
PATPAINT = 0x00FB0A09, // dest = DPSnoo
PATINVERT = 0x005A0049, // dest = pattern XOR dest
DSTINVERT = 0x00550009, // dest = (NOT dest)
BLACKNESS = 0x00000042, // dest = BLACK
WHITENESS = 0x00FF0062, // dest = WHITE
};
/// <summary>
/// Enumeration to be used for those Win32 function
/// that return BOOL
/// </summary>
public enum Bool
{
False = 0,
True
};
/// <summary>
/// Sets the background color.
/// </summary>
/// <param name="hdc">The HDC.</param>
/// <param name="crColor">Color of the cr.</param>
/// <returns></returns>
[DllImport("gdi32.dll")]
public static extern int SetBkColor(IntPtr hdc, int crColor);
/// <summary>
/// CreateCompatibleDC
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
/// <summary>
/// DeleteDC
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool DeleteDC(IntPtr hdc);
/// <summary>
/// SelectObject
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true)]
public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
/// <summary>
/// DeleteObject
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool DeleteObject(IntPtr hObject);
/// <summary>
/// CreateCompatibleBitmap
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern IntPtr CreateCompatibleBitmap(IntPtr hObject, int width, int height);
/// <summary>
/// BitBlt
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool BitBlt(IntPtr hObject, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hObjSource, int nXSrc, int nYSrc, TernaryRasterOperations dwRop);
/// <summary>
/// StretchBlt
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool StretchBlt(IntPtr hObject, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest, IntPtr hObjSource, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, TernaryRasterOperations dwRop);
/// <summary>
/// SetStretchBltMode
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool SetStretchBltMode(IntPtr hObject, int nStretchMode);
}
I advice you to use Control.CreateGraphics() method at Form instance, and write on a Form directly, because PaintBox control is quite slow.
Try using my helper function, this will allow you to paste a portion of your bitmap using StretchBlt (stretching) or BitBlt (no stretching) using Win32 Interop:
Sample usage:
Graphics graphics = ...;
graphics.GdiDrawImage
(
image,
new Rectangle(
(int)rectangle.Left,
(int)rectangle.Top,
(int)rectangle.Width,
(int)rectangle.Height
),
0, 0, image.Width, image.Height
);
Source code:
public static class GraphicsHelper
{
public static void GdiDrawImage(this Graphics graphics, Bitmap image, Rectangle rectangleDst, int nXSrc, int nYSrc, int nWidth, int nHeight)
{
IntPtr hdc = graphics.GetHdc();
IntPtr memdc = GdiInterop.CreateCompatibleDC(hdc);
IntPtr bmp = image.GetHbitmap();
GdiInterop.SelectObject(memdc, bmp);
GdiInterop.SetStretchBltMode(hdc, 0x04);
GdiInterop.StretchBlt(hdc, rectangleDst.Left, rectangleDst.Top, rectangleDst.Width, rectangleDst.Height, memdc, nXSrc, nYSrc, nWidth, nHeight, GdiInterop.TernaryRasterOperations.SRCCOPY);
//GdiInterop.BitBlt(..) put it here, if you did not mention stretching the source image
GdiInterop.DeleteObject(bmp);
GdiInterop.DeleteDC(memdc);
graphics.ReleaseHdc(hdc);
}
}
public class GdiInterop
{
/// <summary>
/// Enumeration for the raster operations used in BitBlt.
/// In C++ these are actually #define. But to use these
/// constants with C#, a new enumeration _type is defined.
/// </summary>
public enum TernaryRasterOperations
{
SRCCOPY = 0x00CC0020, // dest = source
SRCPAINT = 0x00EE0086, // dest = source OR dest
SRCAND = 0x008800C6, // dest = source AND dest
SRCINVERT = 0x00660046, // dest = source XOR dest
SRCERASE = 0x00440328, // dest = source AND (NOT dest)
NOTSRCCOPY = 0x00330008, // dest = (NOT source)
NOTSRCERASE = 0x001100A6, // dest = (NOT src) AND (NOT dest)
MERGECOPY = 0x00C000CA, // dest = (source AND pattern)
MERGEPAINT = 0x00BB0226, // dest = (NOT source) OR dest
PATCOPY = 0x00F00021, // dest = pattern
PATPAINT = 0x00FB0A09, // dest = DPSnoo
PATINVERT = 0x005A0049, // dest = pattern XOR dest
DSTINVERT = 0x00550009, // dest = (NOT dest)
BLACKNESS = 0x00000042, // dest = BLACK
WHITENESS = 0x00FF0062, // dest = WHITE
};
/// <summary>
/// Enumeration to be used for those Win32 function
/// that return BOOL
/// </summary>
public enum Bool
{
False = 0,
True
};
/// <summary>
/// Sets the background color.
/// </summary>
/// <param name="hdc">The HDC.</param>
/// <param name="crColor">Color of the cr.</param>
/// <returns></returns>
[DllImport("gdi32.dll")]
public static extern int SetBkColor(IntPtr hdc, int crColor);
/// <summary>
/// CreateCompatibleDC
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
/// <summary>
/// DeleteDC
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool DeleteDC(IntPtr hdc);
/// <summary>
/// SelectObject
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true)]
public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
/// <summary>
/// DeleteObject
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool DeleteObject(IntPtr hObject);
/// <summary>
/// CreateCompatibleBitmap
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern IntPtr CreateCompatibleBitmap(IntPtr hObject, int width, int height);
/// <summary>
/// BitBlt
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool BitBlt(IntPtr hObject, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hObjSource, int nXSrc, int nYSrc, TernaryRasterOperations dwRop);
/// <summary>
/// StretchBlt
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool StretchBlt(IntPtr hObject, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest, IntPtr hObjSource, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, TernaryRasterOperations dwRop);
/// <summary>
/// SetStretchBltMode
/// </summary>
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool SetStretchBltMode(IntPtr hObject, int nStretchMode);
}
edited Sep 20 '11 at 6:46
answered Sep 20 '11 at 6:38
Artur Mustafin
1,780817
1,780817
GetHbitmapcreates a copy of the bitmap data. This may be an issue when using large bitmaps like 10k x 10k RGB, which are around 400MB large: There will be the originalBitmapobject of this size and then another "GDI bitmap" of the same size. This will almost never work in a 32 bit process, 64bit is required then: stackoverflow.com/a/11559001
– Tobias Knauss
Nov 9 at 16:08
add a comment |
GetHbitmapcreates a copy of the bitmap data. This may be an issue when using large bitmaps like 10k x 10k RGB, which are around 400MB large: There will be the originalBitmapobject of this size and then another "GDI bitmap" of the same size. This will almost never work in a 32 bit process, 64bit is required then: stackoverflow.com/a/11559001
– Tobias Knauss
Nov 9 at 16:08
GetHbitmap creates a copy of the bitmap data. This may be an issue when using large bitmaps like 10k x 10k RGB, which are around 400MB large: There will be the original Bitmap object of this size and then another "GDI bitmap" of the same size. This will almost never work in a 32 bit process, 64bit is required then: stackoverflow.com/a/11559001– Tobias Knauss
Nov 9 at 16:08
GetHbitmap creates a copy of the bitmap data. This may be an issue when using large bitmaps like 10k x 10k RGB, which are around 400MB large: There will be the original Bitmap object of this size and then another "GDI bitmap" of the same size. This will almost never work in a 32 bit process, 64bit is required then: stackoverflow.com/a/11559001– Tobias Knauss
Nov 9 at 16:08
add a comment |
Notice: This is no full answer to the question, but I want to provide some useful information to the existing answer.
In contrast to the answer of Artur Mustafin, I suggest not to use the Windows GDI directly, but to use the .net methods of the Graphics class. In my tests they have performed a lot better than the GDI functions.
The GDI code is taken from the answer of Artur Mustafin.
The test was displaying an image of 1Mpix (1k x 1k) Bitmap or 100Mpix (10k x 10k) Bitmap in 1k x 1k Picturebox by drawing in the Paint event.
The tests were done in Visual Studio 2015.3 on Windows 7 Pro x64 SP1, Debug mode, on an Intel Core i7-3630QM CPU @ 2.4 GHz, 16 GB RAM.
Results:
1000x Graphics.DrawImage() unscaled of 100M Bitmap: 36.8s (x86), 24.2s (x64).
1000x Graphics.DrawImage() unscaled of 1M Bitmap: 5.2s (x86), 3.8s (x64).
100x Graphics.DrawImage() scaled of 100M Bitmap: 62.8s (x86), 39.0s (x64).
1000x Graphics.DrawImage() scaled of 1M Bitmap: 5.2s (x86), 3.8s (x64).
100x GdiDrawImage() StretchBlockTransfer of 100M Bitmap: OutOfMem@x86, 88.5s (x64).
1000x GdiDrawImage() StretchBlockTransfer of 1M Bitmap: 12.9s (x86), 11.5s (x64).
100x GdiDrawImage() BitBlockTransfer of 100M Bitmap: OutOfMem@x86, 49.7s (x64).
1000x GdiDrawImage() BitBlockTransfer of 1M Bitmap: 7.2s (x86), 5.8s (x64).
Test code:
public partial class FormPictureboxPaint : Form
{
private Bitmap m_oBitmap;
public FormPictureboxPaint ()
{
InitializeComponent ();
string sFile = Application.StartupPath + @"......bitmap.png"; // The bitmap file contains an image with 10k x 10k pixels.
m_oBitmap = new Bitmap (sFile);
if (false) // CHANGE TO TRUE IF TESTING WITH 1k x 1k BITMAPS
{
var oBitmap = new Bitmap (m_oBitmap, new Size (1000, 1000));
m_oBitmap.Dispose ();
m_oBitmap = null;
GC.Collect ();
GC.WaitForFullGCComplete ();
GC.WaitForPendingFinalizers ();
m_oBitmap = oBitmap;
}
}
private void pictureBox1_Paint (object sender, PaintEventArgs e)
{
var oGraphics = e.Graphics;
DateTime dtNow = DateTime.Now;
// UNCOMMENT THE FOLLOWING LINES FOR TESTS WITH DrawImage
// COMMENT THE FOLLOWING LINES FOR TESTS WITH GDI
//for (int ixCnt = 0; ixCnt < 1000; ixCnt++)
// PictureboxPaint01 (oGraphics);
// COMMENT THE FOLLOWING LINES FOR TESTS WITH DrawImage
// UNCOMMENT THE FOLLOWING LINES FOR TESTS WITH GDI
for (int ixCnt = 0; ixCnt < 100; ixCnt++)
PictureboxPaint02 (oGraphics);
TimeSpan ts = (DateTime.Now - dtNow);
}
private void PictureboxPaint01 (Graphics i_oGraphics)
{
//_oGraphics.DrawImage (m_oBitmap, new Point ());
i_oGraphics.DrawImage (m_oBitmap, new Rectangle (0, 0, 1000, 1000));
}
private void PictureboxPaint02 (Graphics i_oGraphics)
{
// from https://stackoverflow.com/a/7481071
i_oGraphics.GdiDrawImage
(
m_oBitmap,
new Rectangle (
(int)pictureBox1.Left,
(int)pictureBox1.Top,
(int)pictureBox1.Width,
(int)pictureBox1.Height
),
0, 0, m_oBitmap.Width, m_oBitmap.Height
);
}
}
public static class GraphicsHelper
{
public static void GdiDrawImage (this Graphics graphics, Bitmap image, Rectangle rectangleDst, int nXSrc, int nYSrc, int nWidth, int nHeight)
{
IntPtr hdc = graphics.GetHdc ();
IntPtr memdc = GdiInterop.CreateCompatibleDC (hdc);
IntPtr bmp = image.GetHbitmap ();
GdiInterop.SelectObject (memdc, bmp);
GdiInterop.SetStretchBltMode (hdc, 0x04);
GdiInterop.StretchBlt (hdc, rectangleDst.Left, rectangleDst.Top, rectangleDst.Width, rectangleDst.Height, memdc, nXSrc, nYSrc, nWidth, nHeight, GdiInterop.TernaryRasterOperations.SRCCOPY);
//GdiInterop.BitBlt (hdc, rectangleDst.Left, rectangleDst.Top, rectangleDst.Width, rectangleDst.Height, memdc, nXSrc, nYSrc, GdiInterop.TernaryRasterOperations.SRCCOPY); //put it here, if you did not mention stretching the source image
GdiInterop.DeleteObject (bmp);
GdiInterop.DeleteDC (memdc);
graphics.ReleaseHdc (hdc);
}
}
public class GdiInterop
{
public enum TernaryRasterOperations
{
SRCCOPY = 0x00CC0020, // dest = source
};
public enum Bool
{
False = 0,
True
};
[DllImport ("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern IntPtr CreateCompatibleDC (IntPtr hDC);
[DllImport ("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool DeleteDC (IntPtr hdc);
[DllImport ("gdi32.dll", ExactSpelling = true)]
public static extern IntPtr SelectObject (IntPtr hDC, IntPtr hObject);
[DllImport ("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool DeleteObject (IntPtr hObject);
[DllImport ("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool BitBlt (IntPtr hObject, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hObjSource, int nXSrc, int nYSrc, TernaryRasterOperations dwRop);
[DllImport ("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool StretchBlt (IntPtr hObject, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest, IntPtr hObjSource, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, TernaryRasterOperations dwRop);
[DllImport ("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool SetStretchBltMode (IntPtr hObject, int nStretchMode);
}
add a comment |
Notice: This is no full answer to the question, but I want to provide some useful information to the existing answer.
In contrast to the answer of Artur Mustafin, I suggest not to use the Windows GDI directly, but to use the .net methods of the Graphics class. In my tests they have performed a lot better than the GDI functions.
The GDI code is taken from the answer of Artur Mustafin.
The test was displaying an image of 1Mpix (1k x 1k) Bitmap or 100Mpix (10k x 10k) Bitmap in 1k x 1k Picturebox by drawing in the Paint event.
The tests were done in Visual Studio 2015.3 on Windows 7 Pro x64 SP1, Debug mode, on an Intel Core i7-3630QM CPU @ 2.4 GHz, 16 GB RAM.
Results:
1000x Graphics.DrawImage() unscaled of 100M Bitmap: 36.8s (x86), 24.2s (x64).
1000x Graphics.DrawImage() unscaled of 1M Bitmap: 5.2s (x86), 3.8s (x64).
100x Graphics.DrawImage() scaled of 100M Bitmap: 62.8s (x86), 39.0s (x64).
1000x Graphics.DrawImage() scaled of 1M Bitmap: 5.2s (x86), 3.8s (x64).
100x GdiDrawImage() StretchBlockTransfer of 100M Bitmap: OutOfMem@x86, 88.5s (x64).
1000x GdiDrawImage() StretchBlockTransfer of 1M Bitmap: 12.9s (x86), 11.5s (x64).
100x GdiDrawImage() BitBlockTransfer of 100M Bitmap: OutOfMem@x86, 49.7s (x64).
1000x GdiDrawImage() BitBlockTransfer of 1M Bitmap: 7.2s (x86), 5.8s (x64).
Test code:
public partial class FormPictureboxPaint : Form
{
private Bitmap m_oBitmap;
public FormPictureboxPaint ()
{
InitializeComponent ();
string sFile = Application.StartupPath + @"......bitmap.png"; // The bitmap file contains an image with 10k x 10k pixels.
m_oBitmap = new Bitmap (sFile);
if (false) // CHANGE TO TRUE IF TESTING WITH 1k x 1k BITMAPS
{
var oBitmap = new Bitmap (m_oBitmap, new Size (1000, 1000));
m_oBitmap.Dispose ();
m_oBitmap = null;
GC.Collect ();
GC.WaitForFullGCComplete ();
GC.WaitForPendingFinalizers ();
m_oBitmap = oBitmap;
}
}
private void pictureBox1_Paint (object sender, PaintEventArgs e)
{
var oGraphics = e.Graphics;
DateTime dtNow = DateTime.Now;
// UNCOMMENT THE FOLLOWING LINES FOR TESTS WITH DrawImage
// COMMENT THE FOLLOWING LINES FOR TESTS WITH GDI
//for (int ixCnt = 0; ixCnt < 1000; ixCnt++)
// PictureboxPaint01 (oGraphics);
// COMMENT THE FOLLOWING LINES FOR TESTS WITH DrawImage
// UNCOMMENT THE FOLLOWING LINES FOR TESTS WITH GDI
for (int ixCnt = 0; ixCnt < 100; ixCnt++)
PictureboxPaint02 (oGraphics);
TimeSpan ts = (DateTime.Now - dtNow);
}
private void PictureboxPaint01 (Graphics i_oGraphics)
{
//_oGraphics.DrawImage (m_oBitmap, new Point ());
i_oGraphics.DrawImage (m_oBitmap, new Rectangle (0, 0, 1000, 1000));
}
private void PictureboxPaint02 (Graphics i_oGraphics)
{
// from https://stackoverflow.com/a/7481071
i_oGraphics.GdiDrawImage
(
m_oBitmap,
new Rectangle (
(int)pictureBox1.Left,
(int)pictureBox1.Top,
(int)pictureBox1.Width,
(int)pictureBox1.Height
),
0, 0, m_oBitmap.Width, m_oBitmap.Height
);
}
}
public static class GraphicsHelper
{
public static void GdiDrawImage (this Graphics graphics, Bitmap image, Rectangle rectangleDst, int nXSrc, int nYSrc, int nWidth, int nHeight)
{
IntPtr hdc = graphics.GetHdc ();
IntPtr memdc = GdiInterop.CreateCompatibleDC (hdc);
IntPtr bmp = image.GetHbitmap ();
GdiInterop.SelectObject (memdc, bmp);
GdiInterop.SetStretchBltMode (hdc, 0x04);
GdiInterop.StretchBlt (hdc, rectangleDst.Left, rectangleDst.Top, rectangleDst.Width, rectangleDst.Height, memdc, nXSrc, nYSrc, nWidth, nHeight, GdiInterop.TernaryRasterOperations.SRCCOPY);
//GdiInterop.BitBlt (hdc, rectangleDst.Left, rectangleDst.Top, rectangleDst.Width, rectangleDst.Height, memdc, nXSrc, nYSrc, GdiInterop.TernaryRasterOperations.SRCCOPY); //put it here, if you did not mention stretching the source image
GdiInterop.DeleteObject (bmp);
GdiInterop.DeleteDC (memdc);
graphics.ReleaseHdc (hdc);
}
}
public class GdiInterop
{
public enum TernaryRasterOperations
{
SRCCOPY = 0x00CC0020, // dest = source
};
public enum Bool
{
False = 0,
True
};
[DllImport ("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern IntPtr CreateCompatibleDC (IntPtr hDC);
[DllImport ("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool DeleteDC (IntPtr hdc);
[DllImport ("gdi32.dll", ExactSpelling = true)]
public static extern IntPtr SelectObject (IntPtr hDC, IntPtr hObject);
[DllImport ("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool DeleteObject (IntPtr hObject);
[DllImport ("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool BitBlt (IntPtr hObject, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hObjSource, int nXSrc, int nYSrc, TernaryRasterOperations dwRop);
[DllImport ("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool StretchBlt (IntPtr hObject, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest, IntPtr hObjSource, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, TernaryRasterOperations dwRop);
[DllImport ("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool SetStretchBltMode (IntPtr hObject, int nStretchMode);
}
add a comment |
Notice: This is no full answer to the question, but I want to provide some useful information to the existing answer.
In contrast to the answer of Artur Mustafin, I suggest not to use the Windows GDI directly, but to use the .net methods of the Graphics class. In my tests they have performed a lot better than the GDI functions.
The GDI code is taken from the answer of Artur Mustafin.
The test was displaying an image of 1Mpix (1k x 1k) Bitmap or 100Mpix (10k x 10k) Bitmap in 1k x 1k Picturebox by drawing in the Paint event.
The tests were done in Visual Studio 2015.3 on Windows 7 Pro x64 SP1, Debug mode, on an Intel Core i7-3630QM CPU @ 2.4 GHz, 16 GB RAM.
Results:
1000x Graphics.DrawImage() unscaled of 100M Bitmap: 36.8s (x86), 24.2s (x64).
1000x Graphics.DrawImage() unscaled of 1M Bitmap: 5.2s (x86), 3.8s (x64).
100x Graphics.DrawImage() scaled of 100M Bitmap: 62.8s (x86), 39.0s (x64).
1000x Graphics.DrawImage() scaled of 1M Bitmap: 5.2s (x86), 3.8s (x64).
100x GdiDrawImage() StretchBlockTransfer of 100M Bitmap: OutOfMem@x86, 88.5s (x64).
1000x GdiDrawImage() StretchBlockTransfer of 1M Bitmap: 12.9s (x86), 11.5s (x64).
100x GdiDrawImage() BitBlockTransfer of 100M Bitmap: OutOfMem@x86, 49.7s (x64).
1000x GdiDrawImage() BitBlockTransfer of 1M Bitmap: 7.2s (x86), 5.8s (x64).
Test code:
public partial class FormPictureboxPaint : Form
{
private Bitmap m_oBitmap;
public FormPictureboxPaint ()
{
InitializeComponent ();
string sFile = Application.StartupPath + @"......bitmap.png"; // The bitmap file contains an image with 10k x 10k pixels.
m_oBitmap = new Bitmap (sFile);
if (false) // CHANGE TO TRUE IF TESTING WITH 1k x 1k BITMAPS
{
var oBitmap = new Bitmap (m_oBitmap, new Size (1000, 1000));
m_oBitmap.Dispose ();
m_oBitmap = null;
GC.Collect ();
GC.WaitForFullGCComplete ();
GC.WaitForPendingFinalizers ();
m_oBitmap = oBitmap;
}
}
private void pictureBox1_Paint (object sender, PaintEventArgs e)
{
var oGraphics = e.Graphics;
DateTime dtNow = DateTime.Now;
// UNCOMMENT THE FOLLOWING LINES FOR TESTS WITH DrawImage
// COMMENT THE FOLLOWING LINES FOR TESTS WITH GDI
//for (int ixCnt = 0; ixCnt < 1000; ixCnt++)
// PictureboxPaint01 (oGraphics);
// COMMENT THE FOLLOWING LINES FOR TESTS WITH DrawImage
// UNCOMMENT THE FOLLOWING LINES FOR TESTS WITH GDI
for (int ixCnt = 0; ixCnt < 100; ixCnt++)
PictureboxPaint02 (oGraphics);
TimeSpan ts = (DateTime.Now - dtNow);
}
private void PictureboxPaint01 (Graphics i_oGraphics)
{
//_oGraphics.DrawImage (m_oBitmap, new Point ());
i_oGraphics.DrawImage (m_oBitmap, new Rectangle (0, 0, 1000, 1000));
}
private void PictureboxPaint02 (Graphics i_oGraphics)
{
// from https://stackoverflow.com/a/7481071
i_oGraphics.GdiDrawImage
(
m_oBitmap,
new Rectangle (
(int)pictureBox1.Left,
(int)pictureBox1.Top,
(int)pictureBox1.Width,
(int)pictureBox1.Height
),
0, 0, m_oBitmap.Width, m_oBitmap.Height
);
}
}
public static class GraphicsHelper
{
public static void GdiDrawImage (this Graphics graphics, Bitmap image, Rectangle rectangleDst, int nXSrc, int nYSrc, int nWidth, int nHeight)
{
IntPtr hdc = graphics.GetHdc ();
IntPtr memdc = GdiInterop.CreateCompatibleDC (hdc);
IntPtr bmp = image.GetHbitmap ();
GdiInterop.SelectObject (memdc, bmp);
GdiInterop.SetStretchBltMode (hdc, 0x04);
GdiInterop.StretchBlt (hdc, rectangleDst.Left, rectangleDst.Top, rectangleDst.Width, rectangleDst.Height, memdc, nXSrc, nYSrc, nWidth, nHeight, GdiInterop.TernaryRasterOperations.SRCCOPY);
//GdiInterop.BitBlt (hdc, rectangleDst.Left, rectangleDst.Top, rectangleDst.Width, rectangleDst.Height, memdc, nXSrc, nYSrc, GdiInterop.TernaryRasterOperations.SRCCOPY); //put it here, if you did not mention stretching the source image
GdiInterop.DeleteObject (bmp);
GdiInterop.DeleteDC (memdc);
graphics.ReleaseHdc (hdc);
}
}
public class GdiInterop
{
public enum TernaryRasterOperations
{
SRCCOPY = 0x00CC0020, // dest = source
};
public enum Bool
{
False = 0,
True
};
[DllImport ("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern IntPtr CreateCompatibleDC (IntPtr hDC);
[DllImport ("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool DeleteDC (IntPtr hdc);
[DllImport ("gdi32.dll", ExactSpelling = true)]
public static extern IntPtr SelectObject (IntPtr hDC, IntPtr hObject);
[DllImport ("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool DeleteObject (IntPtr hObject);
[DllImport ("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool BitBlt (IntPtr hObject, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hObjSource, int nXSrc, int nYSrc, TernaryRasterOperations dwRop);
[DllImport ("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool StretchBlt (IntPtr hObject, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest, IntPtr hObjSource, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, TernaryRasterOperations dwRop);
[DllImport ("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool SetStretchBltMode (IntPtr hObject, int nStretchMode);
}
Notice: This is no full answer to the question, but I want to provide some useful information to the existing answer.
In contrast to the answer of Artur Mustafin, I suggest not to use the Windows GDI directly, but to use the .net methods of the Graphics class. In my tests they have performed a lot better than the GDI functions.
The GDI code is taken from the answer of Artur Mustafin.
The test was displaying an image of 1Mpix (1k x 1k) Bitmap or 100Mpix (10k x 10k) Bitmap in 1k x 1k Picturebox by drawing in the Paint event.
The tests were done in Visual Studio 2015.3 on Windows 7 Pro x64 SP1, Debug mode, on an Intel Core i7-3630QM CPU @ 2.4 GHz, 16 GB RAM.
Results:
1000x Graphics.DrawImage() unscaled of 100M Bitmap: 36.8s (x86), 24.2s (x64).
1000x Graphics.DrawImage() unscaled of 1M Bitmap: 5.2s (x86), 3.8s (x64).
100x Graphics.DrawImage() scaled of 100M Bitmap: 62.8s (x86), 39.0s (x64).
1000x Graphics.DrawImage() scaled of 1M Bitmap: 5.2s (x86), 3.8s (x64).
100x GdiDrawImage() StretchBlockTransfer of 100M Bitmap: OutOfMem@x86, 88.5s (x64).
1000x GdiDrawImage() StretchBlockTransfer of 1M Bitmap: 12.9s (x86), 11.5s (x64).
100x GdiDrawImage() BitBlockTransfer of 100M Bitmap: OutOfMem@x86, 49.7s (x64).
1000x GdiDrawImage() BitBlockTransfer of 1M Bitmap: 7.2s (x86), 5.8s (x64).
Test code:
public partial class FormPictureboxPaint : Form
{
private Bitmap m_oBitmap;
public FormPictureboxPaint ()
{
InitializeComponent ();
string sFile = Application.StartupPath + @"......bitmap.png"; // The bitmap file contains an image with 10k x 10k pixels.
m_oBitmap = new Bitmap (sFile);
if (false) // CHANGE TO TRUE IF TESTING WITH 1k x 1k BITMAPS
{
var oBitmap = new Bitmap (m_oBitmap, new Size (1000, 1000));
m_oBitmap.Dispose ();
m_oBitmap = null;
GC.Collect ();
GC.WaitForFullGCComplete ();
GC.WaitForPendingFinalizers ();
m_oBitmap = oBitmap;
}
}
private void pictureBox1_Paint (object sender, PaintEventArgs e)
{
var oGraphics = e.Graphics;
DateTime dtNow = DateTime.Now;
// UNCOMMENT THE FOLLOWING LINES FOR TESTS WITH DrawImage
// COMMENT THE FOLLOWING LINES FOR TESTS WITH GDI
//for (int ixCnt = 0; ixCnt < 1000; ixCnt++)
// PictureboxPaint01 (oGraphics);
// COMMENT THE FOLLOWING LINES FOR TESTS WITH DrawImage
// UNCOMMENT THE FOLLOWING LINES FOR TESTS WITH GDI
for (int ixCnt = 0; ixCnt < 100; ixCnt++)
PictureboxPaint02 (oGraphics);
TimeSpan ts = (DateTime.Now - dtNow);
}
private void PictureboxPaint01 (Graphics i_oGraphics)
{
//_oGraphics.DrawImage (m_oBitmap, new Point ());
i_oGraphics.DrawImage (m_oBitmap, new Rectangle (0, 0, 1000, 1000));
}
private void PictureboxPaint02 (Graphics i_oGraphics)
{
// from https://stackoverflow.com/a/7481071
i_oGraphics.GdiDrawImage
(
m_oBitmap,
new Rectangle (
(int)pictureBox1.Left,
(int)pictureBox1.Top,
(int)pictureBox1.Width,
(int)pictureBox1.Height
),
0, 0, m_oBitmap.Width, m_oBitmap.Height
);
}
}
public static class GraphicsHelper
{
public static void GdiDrawImage (this Graphics graphics, Bitmap image, Rectangle rectangleDst, int nXSrc, int nYSrc, int nWidth, int nHeight)
{
IntPtr hdc = graphics.GetHdc ();
IntPtr memdc = GdiInterop.CreateCompatibleDC (hdc);
IntPtr bmp = image.GetHbitmap ();
GdiInterop.SelectObject (memdc, bmp);
GdiInterop.SetStretchBltMode (hdc, 0x04);
GdiInterop.StretchBlt (hdc, rectangleDst.Left, rectangleDst.Top, rectangleDst.Width, rectangleDst.Height, memdc, nXSrc, nYSrc, nWidth, nHeight, GdiInterop.TernaryRasterOperations.SRCCOPY);
//GdiInterop.BitBlt (hdc, rectangleDst.Left, rectangleDst.Top, rectangleDst.Width, rectangleDst.Height, memdc, nXSrc, nYSrc, GdiInterop.TernaryRasterOperations.SRCCOPY); //put it here, if you did not mention stretching the source image
GdiInterop.DeleteObject (bmp);
GdiInterop.DeleteDC (memdc);
graphics.ReleaseHdc (hdc);
}
}
public class GdiInterop
{
public enum TernaryRasterOperations
{
SRCCOPY = 0x00CC0020, // dest = source
};
public enum Bool
{
False = 0,
True
};
[DllImport ("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern IntPtr CreateCompatibleDC (IntPtr hDC);
[DllImport ("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool DeleteDC (IntPtr hdc);
[DllImport ("gdi32.dll", ExactSpelling = true)]
public static extern IntPtr SelectObject (IntPtr hDC, IntPtr hObject);
[DllImport ("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool DeleteObject (IntPtr hObject);
[DllImport ("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool BitBlt (IntPtr hObject, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hObjSource, int nXSrc, int nYSrc, TernaryRasterOperations dwRop);
[DllImport ("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool StretchBlt (IntPtr hObject, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest, IntPtr hObjSource, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, TernaryRasterOperations dwRop);
[DllImport ("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern Bool SetStretchBltMode (IntPtr hObject, int nStretchMode);
}
answered Nov 13 at 9:02
Tobias Knauss
1,95211230
1,95211230
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f7481004%2fc-sharp-move-bitmap-in-picturebox%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
You have to assign the Bitmap to the _pictureBox.Image property first, than assigning to it as nessecary. I advice you to use Control.CreateGraphics() method and write on a Form directly.
– Artur Mustafin
Sep 20 '11 at 6:44
You can pin miage to the mouse pointer, and subscribe to the mouse movements other the bitmap while left button is pressed on a form, by attaching to the MouseClick and MouseMove event on a control, in which you can use my Win32 Interop. I will edit my post to add the sample.
– Artur Mustafin
Sep 20 '11 at 7:05