I had an error come up:
A Graphics Object cannot be Created from an Image that has an Indexed Pixel Format
So I implemented this code into my method: Solution for "A Graphics Object cannot be Created from an Image that has an Indexed Pixel Format"
But now my watermark doesnt want to draw on my image.
Please can anyone assist.
Code:
private Image AddWaterMark(Image original)
{
Image waterMark = Image.FromFile(ConfigurationManager.AppSettings["GalleryFolder"] + #"\watermark.png");
Bitmap bm = (Bitmap)original;
Size waterMarkResize = ResizeFit(new Size(original.Width, original.Height));
using (Image watermarkImage = new Bitmap(waterMark, waterMarkResize))
using (Graphics imageGraphics = Graphics.FromImage(new Bitmap(bm.Width, bm.Height)))
{
imageGraphics.DrawImage(bm, new Rectangle(0, 0, bm.Width, bm.Height), 0, 0, bm.Width, bm.Height, GraphicsUnit.Pixel);
using (TextureBrush watermarkBrush = new TextureBrush(watermarkImage))
{
int x = (original.Width / 2 - watermarkImage.Width / 2);
int y = (original.Height / 2 - watermarkImage.Height / 2);
watermarkBrush.TranslateTransform(x, y);
imageGraphics.FillRectangle(watermarkBrush, new Rectangle(new Point(x, y), new Size(watermarkImage.Width + 1, watermarkImage.Height)));
}
}
return bm;
}
You're creating a new Bitmap to pass to Graphics.FromImage then returning the uneditted original Bitmap. Create the new Bitmap independently, pass it to FromImage then return the new Bitmap.
var edit = new Bitmap(bm.Width, bm.Height);
// ...
using (Graphics imagesGraphics = Graphics.FromImage(edit))
{
// draw original
// draw watermark
}
return edit;
Related
Trying to add a watermark image to a png image, i´ve been able to do it, but i want to take out the hardCoded size regulation for the rectangle of the waterMark, and make it always stay in the center of the image. How can i achieve this.
public Form1()
{
InitializeComponent();
picBox.Parent = this;
picBox.Dock = DockStyle.Fill;
picBox.SizeMode = PictureBoxSizeMode.Zoom;
Bitmap Jpg = new Bitmap(#"C:\Users\tferreira\Desktop\213123.PNG");
using (Bitmap Bmp = new Bitmap(#"C:\Users\tferreira\Desktop\logo.png"))
{
using (Bitmap WatermarkBmp = new Bitmap(Bmp, Bmp.Width / 1, Bmp.Height / 1))
{
picBox.Image = WatermarkImage(Jpg, WatermarkBmp, new Point(400, 100), 0.40F);
}
}
}
public Bitmap WatermarkImage(Bitmap ImageToWatermark, Bitmap Watermark, Point WatermarkPosition, float Opacity)
{
using (Graphics G = Graphics.FromImage(ImageToWatermark))
{
using (ImageAttributes IA = new ImageAttributes())
{
ColorMatrix CM = new ColorMatrix();
CM.Matrix33 = Opacity;
IA.SetColorMatrix(CM);
G.DrawImage(Watermark, new Rectangle(WatermarkPosition, Watermark.Size), 0, 0, Watermark.Width, Watermark.Height, GraphicsUnit.Pixel, IA);
}
}
return ImageToWatermark;
}
Right now the images are hardCoded but that will be taken out. If anyone can help me make this watermark allways stay centered i thank you.
I fixed this problem with this nice peace of code.
System.Drawing.Image img = System.Drawing.Image.FromFile(JpgFilePath);
Bitmap jpg = new Bitmap(img);
filePath = JpgFilePath;
int Width = jpg.Width;
int Height = jpg.Height;
jpg.SetResolution(300, 300);
WaterMarked = WatermarkImage(jpg, WaterMarkBit, new Point((Width - WaterMarkBit.Width) / 2, (Height - WaterMarkBit.Height) / 2), 0.4F);
WaterMarked.Save(filePath.Replace(".jpg", "") + ".tif", ImageFormat.Tiff);
filesJpgForTif.Add(JpgFilePath.Replace("jpg", "tif"));
Using the the sizes of the image and sizes of the watermark and divide it by 2 it makes the image always stay centered.
I am using GetUserMedia API to capture image and draw it to canvas. Using toDataURL() of canvas I get the "ImageUrl". The url is saved as png image to local file. What I am looking is that before saving the image add some comment about image at bottom of image(not over the image) like a footer. I have the below code. Can any one suggest me how to do this in c#.
imageByte= Convert.FromBase64String(ImageUrl);
using (var streamBitmap = new MemoryStream(imageByte))
{
using (var img = Image.FromStream(streamBitmap))
{
img.Save(localPath);
}
}
You can create new Bitmap which will be higher from the original image to fit also the footer below. Next copy the original image and footer to that bitmap and save the new bitmap.
The method to do would like this (assuming the footer width <= image width):
public Bitmap AppendImageFooter(System.Drawing.Image bmp, System.Drawing.Image footer)
{
//Create new image that will be bigger then original image to make place for footer
Bitmap newImage = new Bitmap(bmp.Height+footer.Height,bmp.Width);
//Get graphics from new Image and copy original image and next footer below
Graphics g = Graphics.FromImage(newImage);
g.DrawImage(bmp, new Point(0, 0));
g.DrawImage(footer, new Point(0, bmp.Height));
g.Dispose();
return newImage;
}
And you can fit it in your code at this place:
var footer = Image.FromFile("path_to_your_footer.png");
imageByte= Convert.FromBase64String(ImageUrl);
using (var streamBitmap = new MemoryStream(imageByte))
{
using (var img = Image.FromStream(streamBitmap))
{
var imageWithFooter = AppendImageFooter(img, footer);
imageWithFooter.Save(localPath);
}
}
Edited in reply to additional question from comments:
You can build the footer in runtime. Sample code below, of course you can draw whatever you like in whatever style you like:
public Bitmap AppendImageFooter(System.Drawing.Image bmp, string text)
{
//Create new image that will be bigger then original image to make place for footer
Bitmap newImage = new Bitmap(bmp.Height+200,bmp.Width);
//Get graphics and copy image and below the footer
Graphics g = Graphics.FromImage(bmp);
g.DrawImage(bmp, new Point(0, 0));
g.FillRectangle(new SolidBrush(Color.Black), 0, bmp.Height, bmp.Width, 200);
g.DrawString(text, new Font("Arial", 14), new SolidBrush(Color.White), 20, bmp.Height + 20);
//Anything else you like, circles, rectangles, texts etc..
g.Dispose();
return newImage;
}
Here is the simplest way: I just created new image(footer), a new Image on which old image + footer image is drawn.
int footerHeight = 30;
Bitmap bitmapImg = new Bitmap(img);// Original Image
Bitmap bitmapComment = new Bitmap(img.Width, footerHeight);// Footer
Bitmap bitmapNewImage = new Bitmap(img.Width, img.Height + footerHeight);//New Image
Graphics graphicImage = Graphics.FromImage(bitmapNewImage);
graphicImage.Clear(Color.White);
graphicImage.DrawImage(bitmapImg, new Point(0, 0));
graphicImage.DrawImage(bitmapComment, new Point(bitmapComment.Width, 0));
graphicImage.DrawString("Hi, This is Vivek !", new Font("Arial", 15), new SolidBrush(Color.Black), 0, bitmapImg.Height + footerHeight / 6);
bitmapNewImage.Save(yourImagePath);
bitmapImg.Dispose();
bitmapComment.Dispose();
bitmapNewImage.Dispose();
'img' is the original Image.
I need to fill an rectangle on bottom of my image, but not over the image, so it should be a kind of append a rectangle to bottom of image.
What I have for now:
private void DrawRectangle()
{
string imageFilePath = #"c:\Test.jpg";
Bitmap bitmap = (Bitmap)Image.FromFile(imageFilePath);
using (Graphics graphics = Graphics.FromImage(bitmap))
{
using (Image img = Image.FromFile(imageFilePath))
{
SolidBrush brush = new SolidBrush(Color.Black);
int width = img.Width;
int height = img.Height - 350;
graphics.FillRectangle(brush, 0, height, width, 350);
}
}
bitmap.Save(#"c:\Test1.jpg");
}
But this is over the image.
Any idea's?
Thank you.
You need to know the dimensions of your original image in order to set the size of the new bitmap, which must be larger to accommodate the rectangle.
private void DrawRectangle()
{
string imageFilePath = #"c:\Test.jpg";
int rectHeight = 100;
using (Image img = Image.FromFile(imageFilePath)) // load original image
using (Bitmap bitmap = new Bitmap(img.Width, img.Height + rectHeight)) // create blank bitmap of desired size
using (Graphics graphics = Graphics.FromImage(bitmap))
{
// draw existing image onto new blank bitmap
graphics.DrawImage(img, 0, 0, img.Width, img.Height);
SolidBrush brush = new SolidBrush(Color.Black);
// draw your rectangle below the original image
graphics.FillRectangle(brush, 0, img.Height, img.Width, rectHeight);
bitmap.Save(#"c:\Test1.bmp");
}
}
take a look at the FillRectangle() method overloads.. it has one with the following definition: FillRectangle(Brush brush, int PositionX, int PositionY, int Width, int Height)
your problem most likely stems on using an improper overload for what you're doing.
I have two Bitmaps, named largeBmp and smallBmp. I want to draw smallBmp onto largeBmp, then draw the result onto the screen. SmallBmp's white pixels should be transparent. Here is the code I'm using:
public Bitmap Superimpose(Bitmap largeBmp, Bitmap smallBmp) {
Graphics g = Graphics.FromImage(largeBmp);
g.CompositingMode = CompositingMode.SourceCopy;
smallBmp.MakeTransparent();
int margin = 5;
int x = largeBmp.Width - smallBmp.Width - margin;
int y = largeBmp.Height - smallBmp.Height - margin;
g.DrawImage(smallBmp, new Point(x, y));
return largeBmp;
}
The problem is that the result winds up transparent wherever smallBmp was transparent! I just want to see through to largeBmp, not to what's behind it.
CompositingMode.SourceCopy is the problem here. You want CompositingMode.SourceOver to get alpha blending.
Specify the transparency color of your small bitmap. e.g.
Bitmap largeImage = new Bitmap();
Bitmap smallImage = new Bitmap();
--> smallImage.MakeTransparent(Color.White);
Graphics g = Graphics.FromImage(largeImage);
g.DrawImage(smallImage, new Point(10,10);
Winform copy image on top of another
private void timerFFTp_Tick(object sender, EventArgs e)
{
if (drawBitmap)
{
Bitmap bitmap = new Bitmap(_fftControl.Width, _fftControl.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
_fftControl.DrawToBitmap(bitmap, new Rectangle(0, 0, _fftControl.Width, _fftControl.Height));
if (!fDraw)
{
bitmap.MakeTransparent();
Bitmap fftFormBitmap = new Bitmap(_fftForm.BackgroundImage);
Graphics g = Graphics.FromImage(fftFormBitmap);
g.DrawImage(bitmap, 0, 0);
_fftForm.BackgroundImage = fftFormBitmap;
}
else
{
fDraw = false;
_fftForm.Width = bitmap.Width + 16;
_fftForm.Height = bitmap.Height + 48;
_fftForm.BackgroundImage = bitmap;
}
}
}
Whats going on is i need to draw a black rectangle over the image. I have to load a tif and then show a blackbox over it. I was helped with some code but i continously got the error: A Graphics object cannot be created from an image that has an indexed pixel format.
So i had to read it in to bit format, but when i display the box it resizes the box wierd. And completly displays the the picture box in all black nothing of the original image. if someone could help me where i'm going wrong that would be awesome.
Bitmap original = (Bitmap)System.Drawing.Image.FromFile(coveted, true);
Bitmap newImage = new Bitmap(original.Width, original.Height);
pictureBox1.Image = newImage;
using (Graphics g = Graphics.FromImage(pictureBox1.Image))
{
using (SolidBrush brush = new SolidBrush(Color.Black))
{
g.FillRectangle(brush, new Rectangle(x1value, y1value, x3value, y3value));
}
}
I'm not sure how I can make this clearer. Whats happening is I have a tif in a unsupported format. So I have to change it to a Bitmap so I can actually draw a rectangle on it. Then I need to display this redacted image (the original with the redaction) in a picturebox. Whats going on with the code above, is once it's completed, all it displays is a blackbox with no original image.
I believe i ran something about using a Bitmap from stream and then closing the stream. Anybody familiar with this?
Thanks to all the help from STO members!! heres the correct code for redacting images if you encounter the error "A Graphics object cannot be created from an image that has an indexed pixel format.".
if you're given the redacted starting points (obviously you have to make the Regex work to your situation):
//Regex for pulling points from a file
string x1 = x1 = Regex.Match(l, #"\r\n(\d+)\r\n(\d+)").Groups[2].Value;
string y1 = y1 = Regex.Match(l, #"\r\n(\d+)\r\n(\d+)\r\n(\d+)").Groups[3].Value;
string x2 = x2 = Regex.Match(l, #"\r\n(\d+)\r\n(\d+)\r\n(\d+)\r\n(\d+)").Groups[4].Value;
string y2 = y2 = Regex.Match(l, #"\r\n(\d+)\r\n(\d+)\r\n(\d+)\r\n(\d+)\r\n(\d+)").Groups[5].Value;
string x3 = x3 = Regex.Match(l, #"\r\n(\d+)\r\n(\d+)\r\n(\d+)\r\n(\d+)\r\n(\d+)\r\n(\d+)").Groups[6].Value;
string y3 = y3 = Regex.Match(l, #"\r\n(\d+)\r\n(\d+)\r\n(\d+)\r\n(\d+)\r\n(\d+)\r\n(\d+)\r\n(\d+)").Groups[7].Value;
{
//convert string to int for redacted points
int x1value = Convert.ToInt32(x1);
int y1value = Convert.ToInt32(y1);
int x3value = Convert.ToInt32(x3);
int y3value = Convert.ToInt32(y3);
{
//BEGIN Workaround for indexed pixels
Bitmap original = (Bitmap)System.Drawing.Image.FromFile(YOURFILE, true);
Bitmap newImage = new Bitmap(original);
pictureBox1.Image = newImage; //END Workaround for indexed pixels
using (Graphics g = Graphics.FromImage(pictureBox1.Image)) //start redaction
{
using (SolidBrush brush = new SolidBrush(Color.Black))
{
g.DrawImageUnscaled(newImage, 0,0);
g.FillRectangle(brush, new Rectangle(x1value, y1value, x3value, y3value));
}
} //End Redaction
pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage; //Resized to fit into a static picturebox
}
}
Instead of
Bitmap newImage = new Bitmap(original.Width, original.Height);
you want
Bitmap newImage = new Bitmap(original);
This will make your newImage start with the contents of original.
The difference will be that you will end up with newImage.PixelFormat == PixelFormat.Format32bppArgb, while I'm assuming original.PixelFormat == PixelFormat.Format1bppIndexed.
With PixelFormat.Format32bppArgb, you can create a Graphics object; you cannot with PixelFormat.Format1bppIndexed.
This should work for you:
original = (Bitmap)System.Drawing.Image.FromFile(coveted, true);
using (Graphics g = Graphics.FromImage(original))
{
using (SolidBrush brush = new SolidBrush(Color.Black))
{
g.FillRectangle(brush, new Rectangle(x1value, y1value, x3value, y3value));
}
}
pictureBox1.Image = original;
You aren't drawing the original image on the newImage.
To do so :
g.DrawImageUnscaled(original, 0, 0);
Also, I would do it as follows, I think it works better drawing in RAM, and then showing it to screen. Perhaps I'm wrong though.
using (Graphics g = Graphics.FromImage(newImage))
{
g.DrawImageUnscaled(original, 0, 0);
using (SolidBrush brush = new SolidBrush(Color.Black))
{
g.FillRectangle(brush, new Rectangle(x1value, y1value, x3value, y3value));
}
}
pictureBox1.Image = newImage;
I haven't tested the code above.. good luck though.