When i used following code to convert a bitmap from 8bpp to 24bpp, the resulted image is shifted but i can't figure out the reason of that, can anyone help?
private static Bitmap ConvertTo24(Bitmap bmpIn)
{
bmpIn.Save(#"F:\sara1.bmp");
Bitmap converted = new Bitmap(bmpIn.Width, bmpIn.Height, PixelFormat.Format24bppRgb);
using (Graphics g = Graphics.FromImage(converted))
{
// Prevent DPI conversion
g.PageUnit = GraphicsUnit.Pixel;
// Draw the image
g.DrawImageUnscaled(bmpIn, 0, 0);
// g.DrawImage(bmpIn, 0, 0);
}
converted.Save(#"F:\sara2.bmp");
}
The following code worked for me:
private static Bitmap ConvertTo24(Bitmap bmpIn)
{
bmpIn.Save(#"F:\sara1.bmp");
Bitmap converted = new Bitmap(bmpIn.Width, bmpIn.Height, PixelFormat.Format24bppRgb);
using (Graphics g = Graphics.FromImage(converted))
{
// Prevent DPI conversion
g.PageUnit = GraphicsUnit.Pixel;
// Draw the image
// g.DrawImageUnscaled(bmpIn, 0, 0);
g.DrawImage(bmpIn, 0, 0, converted.Width, converted.Height);
}
converted.Save(#"F:\sara2.bmp");
}
Providing the width and height rescales the image.
You could have problem in bmpIn before receiving it in your function.
You can test following (better) code after putting your 8bpp image in f:\sara1.bmp (just to ensure that you have 8bpp image not shifted before conversion).
private static Bitmap ConvertTo24(Bitmap bmpIn)
{
//Bitmap bmpIn;
bmpIn = new Bitmap(#"f:\sara1.bmp");
Bitmap converted = new Bitmap(bmpIn.Width, bmpIn.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
using (Graphics g = Graphics.FromImage(converted))
{
g.PageUnit = GraphicsUnit.Pixel;
Rectangle rng = new Rectangle(new Point(0, 0), bmpIn.Size);
g.DrawImage(bmpIn, rng); // use this instead of following
}
converted.Save(#"F:\sara2.bmp");
}
Hope it works fine 4 u. I used DrawImage(Image img, Rectangle rng) as you are already told in comments
Answer is complete. Following is explanation. Your code (edited. Use it as it is and follow the comment)
private static Bitmap ConvertTo24(Bitmap bmpIn)
{
bmpIn.Save(#"F:\sara1.bmp");
return;
// After you have called this function. Go open your image f:\sara1.bmp from
//hrad disk-- I doubt you would find it shifted here even before conversion
Bitmap converted = new Bitmap(bmpIn.Width, bmpIn.Height, PixelFormat.Format24bppRgb);
using (Graphics g = Graphics.FromImage(converted))
{
// Prevent DPI conversion
g.PageUnit = GraphicsUnit.Pixel;
// Draw the image
g.DrawImageUnscaled(bmpIn, 0, 0);
// g.DrawImage(bmpIn, 0, 0);
}
converted.Save(#"F:\sara2.bmp");
}
Again Your code ( I just ignored your received 8bpp Bitmap and fetched it directly from f drive, supposing that you would put it before running the application or at least before calling this function)
Following code also worked fine for me.
private static Bitmap ConvertTo24(Bitmap bmpIn)
{
Bitmap bmpIn = new Bitmap(#"f:\sara1.bmp");
Bitmap converted = new Bitmap(bmpIn.Width, bmpIn.Height, PixelFormat.Format24bppRgb);
using (Graphics g = Graphics.FromImage(converted))
{
// Prevent DPI conversion
g.PageUnit = GraphicsUnit.Pixel;
// Draw the image
g.DrawImageUnscaled(bmpIn, 0, 0);
// g.DrawImage(bmpIn, 0, 0);
}
converted.Save(#"F:\sara2.bmp");
}
Related
I have a Windows Forms application that takes a screenshot of a specific portion of the screen, then displays it in a picture box (pictureBox1). It works when I don't try to convert it, but I want to convert the image to grayscale or black and white. The problem is when I convert it to grayscale, it still shows the original picture in the picture box.
Here is the code when it works, without the conversion:
private void button1_Click(object sender, EventArgs e)
{
Rectangle rectangle = new Rectangle(660, 200, 600, 100);
pictureBox1.Height = rectangle.Height;
pictureBox1.Width = rectangle.Width;
imageUploader(rectangle);
}
public void imageUploader(Rectangle rectangle)
{
Bitmap bitmap = new Bitmap(rectangle.Width, rectangle.Height, PixelFormat.Format32bppArgb);
Graphics graphics = Graphics.FromImage(bitmap);
graphics.CopyFromScreen(rectangle.Left, rectangle.Top, 0, 0, bitmap.Size, CopyPixelOperation.SourceCopy);
bitmap.Save("proba.jpeg", ImageFormat.Jpeg);
pictureBox1.Image = bitmap;
}
Here is the conversion method, which I tried out:
public void toGrayscale(Bitmap bitmap)
{
Color c;
for (int y = 0; y < bitmap.Height; y++)
{
for (int x = 0; x < bitmap.Width; x++)
{
c = bitmap.GetPixel(x,y);
Color newColor = Color.FromArgb(c.R,0,0);
bitmap.SetPixel(x,y,newColor);
}
}
}
After I used this conversion (see below) the image showed up in the picture box, but it wasn't grayscale.
Here is the modified imageUploader void with the conversion:
public void imageUploader(Rectangle rectangle)
{
Bitmap bitmap = new Bitmap(rectangle.Width, rectangle.Height, PixelFormat.Format32bppArgb);
toGrayscale(bitmap);
Graphics graphics = Graphics.FromImage(bitmap);
graphics.CopyFromScreen(rectangle.Left, rectangle.Top, 0, 0, bitmap.Size, CopyPixelOperation.SourceCopy);
bitmap.Save("proba.jpeg", ImageFormat.Jpeg);
pictureBox1.Image = bitmap;
}
It appears that your issue is here:
public void imageUploader(Rectangle rectangle)
{
Bitmap bitmap = new Bitmap(rectangle.Width, rectangle.Height, PixelFormat.Format32bppArgb);
toGrayscale(bitmap);
Graphics graphics = Graphics.FromImage(bitmap);
graphics.CopyFromScreen(rectangle.Left, rectangle.Top, 0, 0, bitmap.Size, CopyPixelOperation.SourceCopy);
bitmap.Save("proba.jpeg", ImageFormat.Jpeg);
pictureBox1.Image = bitmap;
}
You're converting each pixel of the bitmap to greyscale (oddly it looks like you're only grabbing the red channel) then copying from the screen, which overwrites your conversion. To fix it, all you should need to do is move the toGreyscale after you copy from the screen, like this:
public void imageUploader(Rectangle rectangle)
{
Bitmap bitmap = new Bitmap(rectangle.Width, rectangle.Height, PixelFormat.Format32bppArgb);
Graphics graphics = Graphics.FromImage(bitmap);
graphics.CopyFromScreen(rectangle.Left, rectangle.Top, 0, 0, bitmap.Size, CopyPixelOperation.SourceCopy);
toGrayscale(bitmap); # Moved after the copy from screen
bitmap.Save("proba.jpeg", ImageFormat.Jpeg);
pictureBox1.Image = bitmap;
}
This should fix the issue.
You are converting an empty Bitmap to greyscale, then copying over the (nominally) greyscaled Bitmap with an image from the screen. Here is your code, annotated to describe what it is doing:
// This line creates an empty Bitmap.
Bitmap bitmap = new Bitmap(rectangle.Width, rectangle.Height, PixelFormat.Format32bppArgb);
// This line converts the empty Bitmap to grayscale.
toGrayscale(bitmap);
// This line creates a Graphics drawing surface from your bitmap.
Graphics graphics = Graphics.FromImage(bitmap);
// This line overwrites the image data from your bitmap with an image from the screen.
graphics.CopyFromScreen(rectangle.Left, rectangle.Top, 0, 0, bitmap.Size, CopyPixelOperation.SourceCopy);
You need to find some way to take the data you got from the screen and make it greyscale. You have not done this. You have made a greyscale image, but then you have thrown it away by writing other data on top of it. It happens that that replacement data is not greyscale.
I'm trying to crop and resize an image in PictureBox1. My code:
//original image for eventually undo
undoImage = pictureBox1.BackgroundImage.Clone() as Image;
Bitmap sourceBitmap = new Bitmap(pictureBox1.BackgroundImage, pictureBox1.Width, pictureBox1.Height);
Graphics g = pictureBox2.CreateGraphics();
g.DrawImage(sourceBitmap, new Rectangle(0, 0, pictureBox2.Width, pictureBox2.Height), rectCropArea, GraphicsUnit.Pixel);
sourceBitmap.Dispose();
And it working properly on two PictureBoxes.
But PictureBox2.Image,PictureBox2.BackgroundImage (and any other including ErrorImage...) = null.
I tried PictureBox.DrawToBitmap, and other, like g.GetHdc() found on google, but unsuccessful.
My question:
How do I properly copy the edited image from PictureBox2 to PictureBox1?
Trivial solution:
undoImage = pictureBox1.BackgroundImage.Clone() as Image;
Bitmap sourceBitmap = new Bitmap(pictureBox1.BackgroundImage, pictureBox1.Width, pictureBox1.Height);
using (Graphics g = Graphics.FromImage(sourceBitmap))
{
g.DrawImage(sourceBitmap, new Rectangle(0, 0, pictureBox2.Width,pictureBox2.Height), rectCropArea, GraphicsUnit.Pixel);
}
pictureBox1.BackgroundImage = sourceBitmap;
On a single bitmap I need to display graphs and text values. So what I did is create a bitmap with points and creating a another bitmap with the text and place on the large bitmap.
I tried using the brush to write the text, but I am not able to see the underlying graphics even though trasparency is set.
Instead I thought to set the transparency for the text bitmap, but the bitmap which I have created are 24 bit rgb. So can we set the transparency for the 24 bit map.
Bitmap textBitmap = null;
textBitmap = new Bitmap(10, 10, PixelFormat.Format24bppRgb);
using (Graphics memoryGrahics =
Graphics.FromImage(textBitmap))
{
memoryGrahics.FillRectangle(Brushes.Black, new Rectangle(0, 0, 100, 100));
memoryGrahics.DrawString(result, f, Brushes.White, x, y);
}
//placing the text bitmap on the graphbitmap
using (Graphics g = Graphics.FromImage(GraphBitmap))
{
g.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver;
textBitmap.MakeTransparent();
g.DrawImage(textBitmap, 0, 0);
return GraphBitmap;
}
well.. it seems like you are using 2 different Graphical objects... although 1 Graphics objects with 1 bitmap can handle multiple layouts of custom drawings, like so:
int width = 800, height = 600;
var bit = new Bitmap(width, height);
var g = Graphics.FromImage(bit);
g.SmoothingMode = SmoothingMode.AntiAlias;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
var area = new Rectangle(0, 0, width, height);
g.FillRectangle(new LinearGradientBrush(area, Color.PaleGoldenrod, Color.OrangeRed, 45), area);
g.DrawImage(Image.FromFile(#"your image"), new Point(10, 10));
g.DrawString("sample", new System.Drawing.Font("Tahoma", 56), new SolidBrush(Color.Black), new PointF(50, 50));
pictureBox1.Image = bit;
note that g.DrawImage method can be used to load other bitmaps as well
I want to merge two pictures in my C# program.
the first one is any picture in grayscale mode, and the second one is like in this picture:
Both of the pictures/images have the same size, and this is my code:
Bitmap first = new Bitmap (picturebox1.image);
Bitmap second = new Bitmap (picturebox2.image);
Bitmap result = new Bitmap (first.width, first.height);
Graphics g = Graphics.FromImage(result);
g.DrawImageUnscaled(first, 0, 0);
g.Flush();
g.DrawImageUnscaled(second, 0, 0);
g.Flush();
picturebox3.image = result;
I can join those picture, but the result has smaller size than the two originals (both pictures have same size). Could anyone give me some suggestions?
Additionally, I want the result picture has condition like this :
if the edge pixel in 2nd picture dropped to the bright side at the 1st one, it will be dark, otherwise when the edge dropped to the dark side, it will be bright (seem glow).
so the text will be semi transparent.
Here's an example of the results I want.
Could anyone give some suggestions please?
It was for joining
Bitmap first = new Bitmap (picturebox1.Image);
Bitmap second = new Bitmap (picturebox2.Image);
Bitmap result = new Bitmap (first.Width+first.Width, first.Height);
Graphics g = Graphics.FromImage(result);
g.DrawImageUnscaled(first, 0, 0);
g.DrawImageUnscaled(second,first.Width, 0);
Try this for merging one on top another . set alpha by yourself ( red: U can use BitMap.MakeTransParent if u not want alpha)
public Bitmap 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)
{
return null;
}
}
private void button1_Click(object sender, EventArgs e)
{
Bitmap first = new Bitmap(pictureBox1.Image);
Bitmap second = SetImageOpacity(pictureBox2.Image, 0.5f);
//Bitmap result = new Bitmap(first.Width, first.Height);
//fix :
Bitmap result = new Bitmap(Math.Max(first.Width,second.Width), Math.Max(first.Height,second.Height));
Console.WriteLine(first.Width);
Graphics g = Graphics.FromImage(result);
g.DrawImageUnscaled(first, 0, 0);
g.DrawImageUnscaled(second, 0, 0);
pictureBox3.Image = result;
result.Save("result.jpg" );
}
}
}
And Coming For watermark why not you want to use Drawstring with alpha
here is article for all these http://www.codeproject.com/Articles/5034/How-to-implement-Alpha-blending
You need to include the System.Drawing.Imaging namespace to make this code work.
Go through following code:
private void CombineImages(FileInfo[] files)
{
//change the location to store the final image.
string finalImage = #"C:\\MyImages\\FinalImage.jpg";
List imageHeights = new List();
int nIndex = 0;
int width = 0;
foreach (FileInfo file in files)
{
Image img = Image.FromFile(file.FullName);
imageHeights.Add(img.Height);
width += img.Width;
img.Dispose();
}
imageHeights.Sort();
int height = imageHeights[imageHeights.Count - 1];
Bitmap img3 = new Bitmap(width, height);
Graphics g = Graphics.FromImage(img3);
g.Clear(SystemColors.AppWorkspace);
foreach (FileInfo file in files)
{
Image img = Image.FromFile(file.FullName);
if (nIndex == 0)
{
g.DrawImage(img, new Point(0, 0));
nIndex++;
width = img.Width;
}
else
{
g.DrawImage(img, new Point(width, 0));
width += img.Width;
}
img.Dispose();
}
g.Dispose();
img3.Save(finalImage, System.Drawing.Imaging.ImageFormat.Jpeg);
img3.Dispose();
imageLocation.Image = Image.FromFile(finalImage);
}
Follow Link:
http://www.niteshluharuka.com/2012/08/combine-several-images-to-form-a-single-image-using-c/
This codeproject article shows how to watermark an image with text as well as another image.
In summary, what you have to do is draw your watermark image over the image with the desired transparency.
It's embarrassing to ask this question but can't find an answer.
I tried this in vain.
Image resultImage = new Bitmap(image1.Width, image1.Height, PixelFormat.Format24bppRgb);
using (Graphics grp = Graphics.FromImage(resultImage))
{
grp.FillRectangle(
Brushes.White, 0, 0, image1.Width, image1.Height);
resultImage = new Bitmap(image1.Width, image1.Height, grp);
}
I basically want to fill a 1024x1024 RGB bitmap image with white in C#. How can I do that?
You almost had it:
private Bitmap DrawFilledRectangle(int x, int y)
{
Bitmap bmp = new Bitmap(x, y);
using (Graphics graph = Graphics.FromImage(bmp))
{
Rectangle ImageSize = new Rectangle(0,0,x,y);
graph.FillRectangle(Brushes.White, ImageSize);
}
return bmp;
}
You are assigning a new image to resultImage, thereby overwriting your previous attempt at creating a white image (which should succeed, by the way).
So just remove the line
resultImage = new Bitmap(image1.Width, image1.Height, grp);
Another approach,
Create a unit bitmap
var b = new Bitmap(1, 1);
b.SetPixel(0, 0, Color.White);
And scale it
var result = new Bitmap(b, 1024, 1024);
Graphics.Clear(Color)
Bitmap bmp = new Bitmap(1024, 1024);
using (Graphics g = Graphics.FromImage(bmp)){g.Clear(Color.White);}
Depending on your needs, a BitmapSource might suit. You can quickly fill a byte array with the 0xff (i.e. white) using Enumerable.Repeat().
int w = 1024;
int h = 1024;
byte[] pix = Enumerable.Repeat((byte)0xff, w * h * 4).ToArray();
SomeImage.Source = BitmapSource.Create(w, h, 96, 96, PixelFormats.Pbgra32, null, pix, w * 4);