Related
I am drawing multiple images over earh map, I am using perspective correct texturing link on each image.
I want to store rendered image in to file (sorce file is 1280x760, the rendered images is around 160x90 in most cases rotated). Currently I am doing this with GL.ReadPixels
int width = 1920;
int height = 1080;
using (Bitmap bitmap = new Bitmap(width, height))
{
System.Drawing.Imaging.BitmapData bits = bitmap.LockBits(new Rectangle(0, 0, width, height), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
GL.ReadPixels(0, (0, width, height, OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, bits.Scan0);
bitmap.UnlockBits(bits);
bitmap.RotateFlip(RotateFlipType.Rotate180FlipX);
bitmap.Save("output.png", System.Drawing.Imaging.ImageFormat.Png);
}
The problem occurs when I move the map, rendered images are not visible anymore on the screen and it looks like that in this case GL.ReadPixels returns empty pixels.
How to get rendered image even if this is not currently rendered on screen?
Extra question, if I use framebuffer the result is the same but using the frame buffer I never see image on the screen, it looks like framebuffer is not drawn on the screen, but GL.ReadPixels can get image out.
Which lines of code are needed to draw framebuffer also on the screen?
Any idea?
I am adding some code with drawing in to framebuffer but the result is empty image.
int FBOHandle = 0;
int ColorTexture = 0;
int DepthTexture = 0;
public bool canRender = false;
public void onRender()
{
int zoom = (int)MainForm.mainMap.Zoom;
VideoMapOverlayBitmap pob = null;
lock (videoMapOverlayBitmapsSync)
videoMapOverlayBitmaps.TryGetValue(zoom, out pob);
if (pob == null)
return;
if (canRender)
{
canRender = false;
int fboWidth = 1920;
int fboHeight = 1080;
// Create Color Tex for framebuffer
GL.GenTextures(1, out ColorTexture);
GL.BindTexture(TextureTarget.Texture2D, ColorTexture);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba8, fboWidth, fboHeight, 0, OpenTK.Graphics.OpenGL.PixelFormat.Rgba, PixelType.UnsignedByte, IntPtr.Zero);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToBorder);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToBorder);
// GL.Ext.GenerateMipmap( GenerateMipmapTarget.Texture2D );
// Create Depth Tex for framebuffer
GL.GenTextures(1, out DepthTexture);
GL.BindTexture(TextureTarget.Texture2D, DepthTexture);
GL.TexImage2D(TextureTarget.Texture2D, 0, (PixelInternalFormat)All.DepthComponent32, fboWidth, fboHeight, 0, OpenTK.Graphics.OpenGL.PixelFormat.DepthComponent, PixelType.UnsignedInt, IntPtr.Zero);
// things go horribly wrong if DepthComponent's Bitcount does not match the main Framebuffer's Depth
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToBorder);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToBorder);
// GL.Ext.GenerateMipmap( GenerateMipmapTarget.Texture2D );
// Create a FBO and attach the textures
GL.Ext.GenFramebuffers(1, out FBOHandle);
GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, FBOHandle);
GL.Ext.FramebufferTexture2D(FramebufferTarget.FramebufferExt, FramebufferAttachment.ColorAttachment0Ext, TextureTarget.Texture2D, ColorTexture, 0);
GL.Ext.FramebufferTexture2D(FramebufferTarget.FramebufferExt, FramebufferAttachment.DepthAttachmentExt, TextureTarget.Texture2D, DepthTexture, 0);
//check for errors on framebuffer
FramebufferErrorCode errorCode = GL.Ext.CheckFramebufferStatus(FramebufferTarget.Framebuffer);
if (errorCode != FramebufferErrorCode.FramebufferComplete)
{
if (errorCode == FramebufferErrorCode.FramebufferUnsupported)
Console.WriteLine("FramebufferUnsupported");
OnUnload();
return;
}
GL.ClearColor(0, 0, 0, 0);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
/*
//this corrupts my main screen
GL.ClearColor(Color.White);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
GL.Ortho(0, fboWidth, fboHeight, 0, -1, 1); // Up-left corner pixel has coordinate (0, 0)
GL.Viewport(0, 0, fboWidth, fboHeight); // Use all of the glControl painting area
*/
// Render all images
PureProjection proj = MainForm.mainMap.MapProvider.Projection;
List<VideoLogEntry> log = Log;
//go over all images in the loop
foreach (var videoEntry in log)
{
if (videoEntry == null)
continue;
if (videoEntry.projectedRectangleEmpty())
continue;
PointLatLng[] rect = videoEntry.getProjectedRectangle();
if (videoEntry.bmp != null)
videoEntry.createTexture();
GL.Enable(EnableCap.Texture2D);
GL.BindTexture(TextureTarget.Texture2D, videoEntry.texture);
//GL.Ext.FramebufferTexture2D(FramebufferTarget.FramebufferExt, FramebufferAttachment.ColorAttachment0Ext, TextureTarget.Texture2D, videoEntry.texture, 0);
//GL.DrawBuffers(1, new int[] { videoEntry.texture }); //compiler error
//Do the magick for "Perspective correct texturing"
// center point
GPoint localTargetPosition = MainForm.instance.gMapControl.FromLatLngToLocalWithOffset(videoEntry.target);
videoEntry.UpdatePolygonLocalPosition(videoEntry.projectedRectangle);
// determines distances to center for all vertexes
double dUL = Common.distance(new double[] { videoEntry.LocalPoints[0].X, videoEntry.LocalPoints[0].Y }, new double[] { localTargetPosition.X, localTargetPosition.Y });
double dUR = Common.distance(new double[] { videoEntry.LocalPoints[1].X, videoEntry.LocalPoints[1].Y }, new double[] { localTargetPosition.X, localTargetPosition.Y });
double dLR = Common.distance(new double[] { videoEntry.LocalPoints[2].X, videoEntry.LocalPoints[2].Y }, new double[] { localTargetPosition.X, localTargetPosition.Y });
double dLL = Common.distance(new double[] { videoEntry.LocalPoints[3].X, videoEntry.LocalPoints[3].Y }, new double[] { localTargetPosition.X, localTargetPosition.Y });
var texCoords = new[]
{
new Vector4(0, 0, 1, 1),
new Vector4(1, 0, 1, 1),
new Vector4(1, 1, 1, 1),
new Vector4(0, 1, 1, 1)
};
texCoords[0] *= (float)((dUL + dLR) / dLR);
texCoords[1] *= (float)((dUR + dLL) / dLL);
texCoords[2] *= (float)((dLR + dUL) / dUL);
texCoords[3] *= (float)((dLL + dUR) / dUR);
GL.Begin(PrimitiveType.Quads);
{
GL.TexCoord4(texCoords[0]); GL.Vertex4(videoEntry.LocalPoints[0].X, videoEntry.LocalPoints[0].Y, 1, 1); //UL LocalPoints[0] gimbalUL
GL.TexCoord4(texCoords[1]); GL.Vertex4(videoEntry.LocalPoints[1].X, videoEntry.LocalPoints[1].Y, 1, 1); //UR LocalPoints[1] gimbalUR
GL.TexCoord4(texCoords[2]); GL.Vertex4(videoEntry.LocalPoints[2].X, videoEntry.LocalPoints[2].Y, 1, 1); //LR LocalPoints[2] gimbalLR
GL.TexCoord4(texCoords[3]); GL.Vertex4(videoEntry.LocalPoints[3].X, videoEntry.LocalPoints[3].Y, 1, 1); //LL LocalPoints[3] gimbalLL
}
GL.End();
GL.Disable(EnableCap.Texture2D);
}
// Grab your screenshot
// draw FBO in to file
lock (pob.masterBitmapSync)
{
using (Bitmap mybitmap = new Bitmap(fboWidth, fboHeight))
{
//fill bitmal so we will see what ReadPixels draw
using (Graphics gfx = Graphics.FromImage(mybitmap))
using (SolidBrush brush = new SolidBrush(Color.FromArgb(0, 0, 255)))
{
gfx.FillRectangle(brush, 0, 0, mybitmap.Width, mybitmap.Height);
}
GPoint p = new GPoint(0, 0);
int outputWidth = mybitmap.Width;
int outputHeight = mybitmap.Height;
System.Drawing.Imaging.BitmapData bits = mybitmap.LockBits(new Rectangle(0, 0, mybitmap.Width, mybitmap.Height), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
GL.ReadPixels((int)p.X, (int)p.Y, outputWidth, outputHeight, OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, bits.Scan0);
mybitmap.UnlockBits(bits);
//mybitmap.RotateFlip(RotateFlipType.Rotate180FlipX);
mybitmap.Save(#"c:\Downloads\aaa\ReadPixels_" + DateTime.Now.ToString("HHmmss_fff") + ".png", System.Drawing.Imaging.ImageFormat.Png);
pob.masterBitmap.Dispose();
pob.masterBitmap = null;
pob.masterBitmap = (Bitmap)mybitmap.Clone();
}
}
// Unload and dispose the frame buffer
GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, 0);
// Clean up what we allocated before exiting
if (ColorTexture != 0)
GL.DeleteTextures(1, ref ColorTexture);
ColorTexture = 0;
if (DepthTexture != 0)
GL.DeleteTextures(1, ref DepthTexture);
DepthTexture = 0;
if (FBOHandle != 0)
GL.Ext.DeleteFramebuffers(1, ref FBOHandle);
FBOHandle = 0;
}
}
How to get rendered image even if this is not currently rendered on screen?
Create a new frame buffer, bind that frame buffer, set up viewport, set up ortho projection matrix, render your desired piece of the map into it, call GL.ReadPixels, save screenshot, unload and dispose the framebuffer.
Here's some sample code:
// Create framebuffer
int fboId = GL.GenFramebuffer();
GL.BindFramebuffer(FramebufferTarget.Framebuffer, fboId);
// Set up a framebuffer attachment here
int width = ...
int height = ...
int textureId = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, textureId);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba8, width, height, 0, PixelFormat.Rgba, PixelType.Float, IntPtr.Zero);
GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, (FramebufferAttachment)fbAtt.AttachmentType, TextureTarget.Texture2D, textureId, 0);
GL.DrawBuffers(1, new int[] { textureId });
GL.Viewport(0, 0, width, height);
// Set up ortho modo. probably also want to disable depth testing and any active blend modes
....
// Render your map now
....
// Grab your screenshot
....
// Unload and dispose the frame buffer
...
// Reset everything (viewport, ortho mode, etc.) if you don't your normal map to flicker for a frame
....
Your other question I don't quite understand
I'm trying to make an image cropping tool.
I am following this https://www.codeproject.com/Articles/703519/Cropping-Particular-Region-In-Image-Using-Csharp
But since it's a bit old and the plugin/DLL's it uses have changed I have been trying to adapt his code from OpenCvSharp 2.0 to OpenCvSharp 2.4
When I'm converting the bitmaps to IplImages and using Cv.Mul() it gives me this error:
Attempted to read or write protected memory. This is often an indication that other memory is corrupt
I have never used OpenCvSharp other ways of creating the IplImage even reading the IplImage from a written image.
Code:
public static IplImage BitmapToIplImage(Bitmap bitmap)
{
IplImage tmp, tmp2;
System.Drawing.Rectangle bRect = new System.Drawing.Rectangle(new System.Drawing.Point(0, 0), new System.Drawing.Size((int)bitmap.Width, (int)bitmap.Height));
BitmapData bmData = bitmap.LockBits(bRect, ImageLockMode.ReadWrite, bitmap.PixelFormat);
tmp = Cv.CreateImage(Cv.Size(bitmap.Width, bitmap.Height), BitDepth.U8, 3);
tmp2 = Cv.CreateImage(Cv.Size(bitmap.Width, bitmap.Height), BitDepth.U8, 1);
byte[] data = new byte[Math.Abs(bmData.Stride * bmData.Height)];
tmp.SetData(bmData.Scan0, data.Length);
bitmap.UnlockBits(bmData);
// Cv.CvtColor(tmp, tmp2, ColorConversion.RgbToGray);
return tmp;
}
private void CropImage()
{
IplImage ipl = Cv.CreateImage(new CvSize(curBmp.Width, curBmp.Height), BitDepth.U8, 3);
Graphics ga = Graphics.FromImage(curBmp);
ga.FillRectangle(new SolidBrush(System.Drawing.Color.Black), new System.Drawing.Rectangle(0, 0, curBmp.Width, curBmp.Height));
SolidBrush brush = new SolidBrush(System.Drawing.Color.FromArgb(1, 1, 1));
curGraphics.FillClosedCurve(brush, imagePoints.ToArray());
Cv.Mul(BitmapToIplImage(curOgBmp), BitmapToIplImage(curBmp), ipl, 1);
ComputeCrop();
Stream s = null;
ipl.ToStream(s, ".png", null);
curBmp = new Bitmap(s);
RefreshImageViewer();
}
-----------------------------EDIT-----------------------------------------
I tried to follow what Markus posted, and I got it to work without any errors in the code.
Although the image cropped is a bit strange here are the methods I use, plus the RefreshImageViewer that is how I put the bitmap in the image control.
I have been trying to see if I missed something for hours, but I think not.
Output example: Imgur image link
Code:
public void RefreshImageViewer()
{
bmpSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
curBmp.GetHbitmap(),
IntPtr.Zero,
System.Windows.Int32Rect.Empty,
BitmapSizeOptions.FromWidthAndHeight(curBmp.Width, curBmp.Height));
imageViewer.Source = bmpSource;
curGraphics = Graphics.FromImage(curBmp);
}
private void CropImage()
{
Graphics Ga = Graphics.FromImage(curBmp);
//the black image
Ga.FillRectangle(new SolidBrush(System.Drawing.Color.Black), new System.Drawing.Rectangle(0, 0, curBmp.Width, curBmp.Height));
//draw from the last point to first point
Ga.DrawLine(new System.Drawing.Pen(System.Drawing.Color.Red, 3), imagePoints[imagePoints.Count - 1], imagePoints[0]);
//all of the rgb values are being set 1 inside the polygon
SolidBrush Brush = new SolidBrush(System.Drawing.Color.FromArgb(1, 1, 1));
//we have to prepare one mask of Multiplying operation for cropping region
curGraphics.FillPolygon(Brush, imagePoints.ToArray());
Mat accc = (BitmapToMat(curOgBmp).Mul(BitmapToMat(curBmp))).ToMat();
System.Drawing.Rectangle r = ComputeCrop();
curBmp = accc.ToBitmap().Clone(r, curOgBmp.PixelFormat);
RefreshImageViewer();
}
private System.Drawing.Rectangle ComputeCrop()
{
int smallestX = curBmp.Width, biggestX = 0, biggestY = 0, smallestY = curBmp.Height;
for (int i = 0; i < imagePoints.Count; i++)
{
biggestX = Math.Max(biggestX, imagePoints[i].X);
smallestX = Math.Min(smallestX, imagePoints[i].X);
biggestY = Math.Max(biggestY, imagePoints[i].Y);
smallestY = Math.Min(smallestY, imagePoints[i].Y);
}
System.Drawing.Rectangle rectCrop = new System.Drawing.Rectangle(smallestX, smallestY, biggestX - smallestX, biggestY - smallestY);
return rectCrop;
}
public static Mat BitmapToMat(Bitmap bitmap)
{
Mat tmp, tmp2;
System.Drawing.Rectangle bRect = new System.Drawing.Rectangle(new System.Drawing.Point(0, 0), new System.Drawing.Size((int)bitmap.Width, (int)bitmap.Height));
BitmapData bmData = bitmap.LockBits(bRect, ImageLockMode.ReadWrite, bitmap.PixelFormat);
tmp2 = new Mat(new OpenCvSharp.Size(bitmap.Width, bitmap.Height), MatType.CV_8U);
tmp = new Mat(bitmap.Height, bitmap.Width, MatType.CV_8UC3, bmData.Scan0);
bitmap.UnlockBits(bmData);
return tmp;
}
“IplImage” ist the old image container from OpenCv 1. As Andreas already mentioned, today you should use “Mat” instead. Have also a look here : Difference between cvMat, Mat and IpImage
Unfortunately, your code sample is not complete, hence I corrected the two methods from the original project ( https://www.codeproject.com/Articles/703519/Cropping-Particular-Region-In-Image-Using-Csharp).
The following methods are tested and work as intended in the original project in combination with the latest OpenCVSharp version (v4.x) . It should be very simple now to convert the changes to your code.
public static Mat BitmapToIplImage(Bitmap bitmap)
{
Mat tmp, tmp2;
Rectangle bRect = new Rectangle(new System.Drawing.Point(0, 0), new System.Drawing.Size((int)bitmap.Width, (int)bitmap.Height));
BitmapData bmData = bitmap.LockBits(bRect, ImageLockMode.ReadWrite, bitmap.PixelFormat);
tmp2 = new Mat(new Size(bitmap.Width, bitmap.Height), MatType.CV_8U);
tmp = new Mat(bitmap.Height, bitmap.Width, MatType.CV_8UC3, bmData.Scan0);
bitmap.UnlockBits(bmData);
return tmp;
}
private void crop()
{
timer1.Stop();
Graphics Ga = Graphics.FromImage(bmp);
//the black image
Ga.FillRectangle(new SolidBrush(Color.Black), new Rectangle(0, 0, bmp.Width, bmp.Height));
//draw from the last point to first point
Ga.DrawLine(new Pen(Color.Red, 3), polygonPoints[polygonPoints.Count - 1], polygonPoints[0]);
//all of the rgb values are being set 1 inside the polygon
SolidBrush Brush = new SolidBrush(Color.FromArgb(1, 1, 1));
//we have to prepare one mask of Multiplying operation for cropping region
G.FillClosedCurve(Brush, polygonPoints.ToArray());
var accc= (BitmapToIplImage(Source).Mul(BitmapToIplImage(bmp))).ToMat();
computecrop();
croplast = accc.ToBitmap().Clone(rectcrop, Source.PixelFormat);//just show cropped region part of image
pictureBox2.Image = croplast; // crop region of image
}
I'm creating Heatmap depending on the gazed areas of a given image. I can create the heatmap and save it to my desktop as a new file. But I want to create another image, which is made of the heatmap and the image which was gazed to collect the eye tracking data. I want the original picture to be the solid background, and then overlap (or overlay I don't know) the heatmap as transparent, and merge them into one new file. Is there a way to do it in c#?
Thank you
Ok i found an answer,
first I resize my background picture
public static Bitmap ResizeImage(Bitmap image, int width, int height)
{
var destRect = new Rectangle(0, 0, width, height);
var destImage = new Bitmap(width, height);
destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
using (var graphics = Graphics.FromImage(destImage))
{
graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
using (var wrapMode = new ImageAttributes())
{
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
}
}
return destImage;
}
after that the heatmap must be set to another opacity level, in order to make background visible
public static Image SetImageOpacity(Image image, float opacity)
{
try
{
//create a Bitmap the size of the image provided
Bitmap bmp = new Bitmap(image.Width, image.Height);
//create a graphics object from the image
using (Graphics gfx = Graphics.FromImage(bmp))
{
//create a color matrix object
ColorMatrix matrix = new ColorMatrix();
//set the opacity
matrix.Matrix33 = opacity;
//create image attributes
ImageAttributes attributes = new ImageAttributes();
//set the color(opacity) of the image
attributes.SetColorMatrix(matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
//now draw the image
gfx.DrawImage(image, new Rectangle(0, 0, bmp.Width, bmp.Height), 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, attributes);
}
return bmp;
}
catch (Exception ex)
{
//MessageBox.Show(ex.Message);
throw ex;
//return null;
}
}
finally we need to merge those two
public static Image Overlap(Image source1, Image source2)
{
var target = new Bitmap(source1.Width, source1.Height, PixelFormat.Format32bppArgb);
var graphics = Graphics.FromImage(target);
graphics.CompositingMode = CompositingMode.SourceOver; // this is the default, but just to be clear
graphics.DrawImage(source1, 0, 0);
graphics.DrawImage(source2, 0, 0);
return target;
}
here is my background:
original RTE
and here is the merged version, with the heatmap of the eyetracking data
RTE + heatmap
hy there!
i left out usings etc... just plain code:
var image = Image.FromFile(/* my magic source */);
var bitmap = new Bitmap(image.Width, image.Height);
var canvas = Graphics.FromImage(bitmap);
var brush = new SolidBrush(/* my magic color */);
canvas.FillRectangle(brush, 0, 0, image.Width, image.Height);
canvas.DrawImage(image, new Rectangle(0, 0, image.Width, image.Height));
canvas.Save();
bitmap.Save(/* my magic target */);
i want to draw image with alpha 55% on canvas. image is a .png-file and uses transparency itself. (NOTE: i do not want to make image.MakeTransparent() - it is already transparent, i just need some alpha-effect)
how can i achieve this?
Try ColorMatrix and ImageAttributes:
ColorMatrix cm = new ColorMatrix();
cm.Matrix33 = 0.55f;
ImageAttributes ia = new ImageAttributes();
ia.SetColorMatrix(cm);
canvas.DrawImage(image, new Rectangle(0, 0, image.Width, image.Height), 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, ia);
I have 2 forms, A and B. On the Form A, I click a button and an Image is being loaded to a PictureBox located ona the Form B. And, I want to set GrayScale to this image by:
public void SetGrayScale(PictureBox pb)
{
ColorMatrix matrix = new ColorMatrix(new float[][]
{
new float[] {0.299f, 0.299f, 0.299f, 0, 0},
new float[] {0.587f, 0.587f, 0.587f, 0, 0},
new float[] {0.114f, 0.114f, 0.114f, 0, 0},
new float[] { 0, 0, 0, 1, 0},
new float[] { 0, 0, 0, 0, 0}
});
Image image = (Bitmap)pb.Image.Clone();
ImageAttributes attributes = new ImageAttributes();
attributes.SetColorMatrix(matrix);
Graphics graphics = Graphics.FromImage(image);
graphics.DrawImage(image,
new Rectangle(0, 0, image.Width, image.Height),
0,
0,
image.Width,
image.Height,
GraphicsUnit.Pixel,
attributes);
graphics.Dispose();
pb.Image = image;
}
This code works properly when the PictureBox is on the same form (A). But, when it is on the Form B, the OutOfMemoryException is raised. Why ?
More questions/things for you to investigate rather than an actual answer I'm afraid:
As in the comment to your answer - is the Image object correct?
If not then that implies that there's something wrong with the PictureBox object passed into this method, or that you can't access the PictureBox's Image properly.
My first thought was threading, but both forms should be in the UI thread.
Ok, I've Fixed it :)
The solution is, I had to created a Bitmap object from the OpenDialog.FileName, and later set PictureBox.Image = myBitmap
I didn't do it at the beginning, I was just setting PictureBox.Load(OpenDialog.FileName). And that was my mistake.
Ok, thank's for Your cooperation, ChrisF ! :)