I'm trying to edit an image by including a water mark on it. I make my changes using Graphics and when I try to save the file it throws me an exception Message:"A generic error occurred in GDI+."
Below is my code:
public static void Test()
{
try
{
Bitmap bmpPic = new Bitmap(Image.FromFile("Desktop/cropped/cropped/croppedsent1386.jpeg"));
using (Graphics g = Graphics.FromImage(bmpPic))
{
Brush brush = new SolidBrush(Color.FromArgb(80, 255, 255, 255));
Point postionWaterMark = new Point((bmpPic.Width / 6), (bmpPic.Height / 2));
g.DrawString("Identifid", new System.Drawing.Font("Arial", 30, FontStyle.Bold, GraphicsUnit.Pixel), brush, postionWaterMark);
}
string filepath = "Desktop/cropped/cropped/croppedsent1386.jpeg";
bmpPic.Save(filepath, ImageFormat.Jpeg);
}
catch(Exception ex)
{
Console.WriteLine(ex);
}
Console.WriteLine("End of test ");
}
-Stack Trace-
StackTrace " at System.Drawing.SafeNativeMethods.Gdip.CheckStatus(Int32 status)\r\n at System.Drawing.Image.Save(String filename, ImageCodecInfo encoder, EncoderParameters encoderParams)\r\n at System.Drawing.Image.Save(String filename, ImageFormat format)\r\n at ConsoleWatermark.Program.Test() in C:\\Users\\xavie\\source\\repos\\Samples\\ConsoleWatermark\\Program.cs:line 49"
I'm stumped as to why this is failing as I have permissions to edit files .
Error appears because you trying to overwrite (when bmpPic.Save()) same image file, which you already loaded as Bitmap. Until Bitmap wouldn't be disposed - file would be locked by it. To solve, you should save new watermarked image to an other new file:
string filepath = ".../croppedsent1386_WATERMARKED.jpeg"; // <--- New file
bmpPic.Save(filepath, ImageFormat.Jpeg);
Complete version (with few notations):
static void Main(string[] args)
{
try
{
// Source image file
string imageFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), "myImage.png");
// Add "using" to bitmap too for proper disposage and to release file after completion
using (Bitmap bitmap = new Bitmap(Image.FromFile(imageFile)))
{
using (Graphics g = Graphics.FromImage(bitmap))
{
Brush brush = new SolidBrush(Color.FromArgb(80, 255, 255, 255));
Point watermarkPosition = new Point(bitmap.Width / 6, bitmap.Height / 2);
g.DrawString("IDENTIFID", new Font("Arial", 30, FontStyle.Bold, GraphicsUnit.Pixel), brush, watermarkPosition);
// Save to a new file
string newImageFile = imageFile.Replace("myImage.png", "myImage_WATERMARKED.png");
bitmap.Save(newImageFile, ImageFormat.Png);
}
}
Console.WriteLine("Image saved!");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message + "\n\nStack trace:\n" + ex.StackTrace);
}
Console.ReadKey();
}
Related
I'm using selenium to go to x website and take screenshot
public static void TakeScreenshot(IWebDriver driver, int x, int y, int width, int height)
{
var name =
$#"{Environment.GetFolderPath(Environment.SpecialFolder.Desktop)}\{"screenshots"}\{Guid.NewGuid()}.{
ScreenshotImageFormat.Png
}";
Rectangle rect = new Rectangle(x, y, width, height);
Screenshot screenshot = ((ITakesScreenshot)driver).GetScreenshot();
var bitmapScreen = new Bitmap(new MemoryStream(screenshot.AsByteArray));
var croppedArea = new Rectangle(rect.Location, rect.Size);
bitmapScreen.Clone(croppedArea, bitmapScreen.PixelFormat).Save(name);
}
and after saving that I'm trying to read text from that image using tesseract
var testImagePath = #".\Content\300.png";
var dataPath = #".\tessdata";
try
{
using (var tEngine = new TesseractEngine(dataPath, "eng", EngineMode.Default)) //creating the tesseract OCR engine with English as the language
{
using (var img = Pix.LoadFromFile(testImagePath)) // Load of the image file from the Pix object which is a wrapper for Leptonica PIX structure
{
using (var page = tEngine.Process(img)) //process the specified image
{
var text = page.GetText(); //Gets the image's content as plain text.
Console.WriteLine(text); //display the text
Console.WriteLine(page.GetMeanConfidence()); //Get's the mean confidence that as a percentage of the recognized text.
Console.ReadLine();
}
}
}
}
catch (Exception e)
{
Console.WriteLine("Unexpected Error: " + e.Message);
}
but I'm getting that dummy text:
so I tried to rescale that image
bitmapScreen.SetResolution(300, 300);
as I found here
but result is the same
Hi I am getting this error while saving an Image at the given path
string WriteImage(string data, string imgPath)
{
try
{
data = "*" + data + "*";
Bitmap barcode = new Bitmap(1, 1);
Font threeOfNine = new Font("IDAutomationHC39M", 60, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
Graphics graphics = Graphics.FromImage(barcode);
SizeF dataSize = graphics.MeasureString(data, threeOfNine);
barcode = new Bitmap(barcode, dataSize.ToSize());
graphics = Graphics.FromImage(barcode);
graphics.Clear(Color.White);
graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixel;
graphics.DrawString(data, threeOfNine, new SolidBrush(Color.Black), 0, 0);
graphics.Flush();
threeOfNine.Dispose();
graphics.Dispose();
barcode.SetResolution(300, 300);
barcode.Save(imgPath, System.Drawing.Imaging.ImageFormat.Jpeg);
return imgPath.Substring(imgPath.LastIndexOf("\\")+1);
}
catch
{
return "";
}
}
Dont know what i am doing wrong.
As I wrote in my comment, I'm not seeing any problem. The following version of your code outputs information in the event of an error so you can debug it. It also disposes of resources properly:
public static string WriteImage(string data, string imgPath)
{
try
{
data = "*" + data + "*";
using (var dummyBitmap = new Bitmap(1, 1))
using (var threeOfNine = new Font("IDAutomationHC39M", 60, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point))
{
SizeF dataSize;
using (var graphics = Graphics.FromImage(dummyBitmap))
{
dataSize = graphics.MeasureString(data, threeOfNine);
}
using (var barcode = new Bitmap(dummyBitmap, dataSize.ToSize()))
using (var graphics = Graphics.FromImage(barcode))
using (var brush = new SolidBrush(Color.Black))
{
graphics.Clear(Color.White);
graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixel;
graphics.DrawString(data, threeOfNine, brush, 0, 0);
graphics.Flush();
barcode.SetResolution(300, 300);
barcode.Save(imgPath, System.Drawing.Imaging.ImageFormat.Jpeg);
return imgPath.Substring(imgPath.LastIndexOf("\\") + 1);
}
}
}
catch (Exception ex)
{
Debug.WriteLine("Error saving string \"" + data + "\" to a bitmap at location: " + imgPath);
Debug.WriteLine(ex.ToString());
return "";
}
}
i'm working on an ASP.net 2.0 c# project where i am creating a basic Captcha script. the html looks like this:
<img height="30" width="80" alt="" src="Captcha.aspx" />
and here is the code behind for Captcha.aspx
protected void Page_Load(object sender, EventArgs e)
{
Bitmap objBMP = new System.Drawing.Bitmap(60, 20);
Graphics objGraphics = System.Drawing.Graphics.FromImage(objBMP);
objGraphics.Clear( ColorTranslator.FromHtml( "#054196" ) );
objGraphics.TextRenderingHint = TextRenderingHint.AntiAlias;
// configure the text
Font objFont = new Font("Arial", 8, FontStyle.Bold);
string randomStr = "";
int[] myIntArray = new int[5];
int x;
// randomise the text
Random autoRand = new Random();
for (x = 0; x < 5; x++)
{
myIntArray[x] = System.Convert.ToInt32(autoRand.Next(0, 9));
randomStr += (myIntArray[x].ToString());
}
//add string to session
Session.Add("randomStr", randomStr);
// draw the text
objGraphics.DrawString( randomStr, objFont, Brushes.White, 3, 3);
// Set the content type and return the image
Response.ContentType = "image/jpeg";
Encoder quality = Encoder.Quality;
EncoderParameter qualityParam = new EncoderParameter(quality, 100L);
EncoderParameters encParams = new EncoderParameters( 1 );
encParams.Param[0] = qualityParam;
ImageCodecInfo jpgEncoder = GetEncoder(ImageFormat.Jpeg);
objBMP.Save(Response.OutputStream, jpgEncoder, encParams);
objFont.Dispose();
objGraphics.Dispose();
objBMP.Dispose();
Response.Flush();
}
private ImageCodecInfo GetEncoder(ImageFormat format)
{
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();
foreach (ImageCodecInfo codec in codecs)
{
if (codec.FormatID == format.Guid)
{
return codec;
}
}
return null;
}
this works fine on my local machine, but when uploaded to our dev server it fails. i don't have direct access to the dev server to debug due to my role in the project so it's a bit of trial and error atm.
any ideas?
turns out the server didn't like the aspx page for some reason. so i moved the captcha to a ashx file and then it worked!
how File.Delete() file temp.jpg with process A if locked by process B. how close handles file temp.jpg
IOExceoption:
The process cannot access the file Because it is being used by another process
protected void ButtonJcrop_Click(object sender, EventArgs e)
{
MembershipUser user = Membership.GetUser();
String tempPath = Server.MapPath("..") + #"\Users\" + user.ProviderUserKey.ToString() + #"\temp.gif";
System.Drawing.Image img = System.Drawing.Image.FromFile(tempPath);
Bitmap bmpCropped = new Bitmap(100, 100);
Graphics g = Graphics.FromImage(bmpCropped);
Rectangle rectDestination = new Rectangle(0, 0, bmpCropped.Width, bmpCropped.Height);
Rectangle rectCropArea = new Rectangle(Int32.Parse(hfX.Value), Int32.Parse(hfY.Value), Int32.Parse(hfWidth.Value), Int32.Parse(hfHeight.Value));
g.DrawImage(img, rectDestination, rectCropArea, GraphicsUnit.Pixel);
String mapPath = #"\Users\" + user.ProviderUserKey.ToString() + #"\" + user.ProviderUserKey.ToString() + ".gif";
bmpCropped.Save(Server.MapPath("..") + mapPath);
// bmpCropped.Save(Server.MapPath("..") + #"\Images\thumbs\CroppedImages\" + Session["WorkingImage"]);
imCropped.ImageUrl = Request.ApplicationPath + mapPath;
**File.Delete(tempPath);**
PlaceHolderImCropped.Visible = true;
}
Wait for process B to release the resource.
Pro-tip:
Process B locked the file for a reason. Stealing it is a bad idea in any situation I can think of that isn't pathological.
If you're in a pathological situation:
Get out of the pathological situation. You're only digging
yourself in deeper.
Kill process B.
Are there other techniques? Yes. They are by definition not safe, however, so don't do that.
The only way is for the locking process to pass control to the next process. Then you can catch the exception or the file will be locked until the locking process dies or passes control.
File tempPath is read by
System.Drawing.Image img
So before you delete that file, just use Dispose() method.
img.Dispose();
Bitmap bmpCropped = new Bitmap(100, 100);
Graphics g = Graphics.FromImage(bmpCropped);
Rectangle rectDestination = new Rectangle(0, 0, bmpCropped.Width, bmpCropped.Height);
Rectangle rectCropArea = new Rectangle(Int32.Parse(hfX.Value), Int32.Parse(hfY.Value), Int32.Parse(hfWidth.Value), Int32.Parse(hfHeight.Value));
using (System.Drawing.Image img = System.Drawing.Image.FromFile(tempPath)) g.DrawImage(img, rectDestination, rectCropArea, GraphicsUnit.Pixel);
This is the code which I run to generate a PDF
public string ScreenshotFullLength(string Url) {
UrlScreenshot Shot = new UrlScreenshot(Url, 975, 100);
int maxHeight = 1250;
// If you do skip the crop function you 'll get the
// full lenght of the page. We'll scale it to match
// a 400 pixel width
//int newHeight = (Shot.Bitmap.Width / 400) * Shot.Bitmap.Height;
//Shot.Resize(400, newHeight);
string Filename = LazyAssFilename();
string path = Server.MapPath("~") + "/tmp/" + Filename;
Shot.Bitmap.Save(path, ImageFormat.Png);
string pdfURL = "";
Document document = new Document();
try {
// step 2:
// we create a writer that listens to the document
// and directs a PDF-stream to a file
pdfURL = Server.MapPath("~") + "\\tmp\\Attest_" + EOFName + ".pdf";
PdfWriter.GetInstance(document, new FileStream(pdfURL, FileMode.Create));
// step 3: we open the document
document.Open();
// step 4: we add content
iTextSharp.text.Image jpg = iTextSharp.text.Image.GetInstance(path);
if (jpg.Height > maxHeight) {
//we moeten er meer dan 1 maken en croppen
int loops = (int)(jpg.Height / maxHeight);
int rest = (int)(jpg.Height % maxHeight);
int i;
for (i = 0; i < loops; i++) {
Bitmap bmpImage = new Bitmap(path);
Bitmap bmpCrop = bmpImage.Clone(new System.Drawing.Rectangle(0, i * maxHeight, 975, maxHeight),
bmpImage.PixelFormat);
iTextSharp.text.Image crpd = iTextSharp.text.Image.GetInstance(bmpCrop, ImageFormat.Png);
crpd.Alignment = iTextSharp.text.Image.MIDDLE_ALIGN;
crpd.ScalePercent(60);
document.Add(crpd);
}
//the rest
Bitmap bmpImage2 = new Bitmap(path);
Bitmap bmpCrop2 = bmpImage2.Clone(new System.Drawing.Rectangle(0, i * maxHeight, 975, rest),
bmpImage2.PixelFormat);
iTextSharp.text.Image crpdRest = iTextSharp.text.Image.GetInstance(bmpCrop2, ImageFormat.Png);
crpdRest.Alignment = iTextSharp.text.Image.MIDDLE_ALIGN;
crpdRest.ScalePercent(60);
document.Add(crpdRest);
} else {
jpg.Alignment = iTextSharp.text.Image.MIDDLE_ALIGN;
jpg.ScalePercent(60);
document.Add(jpg);
}
} catch (DocumentException de) {
Console.Error.WriteLine(de.Message);
} catch (IOException ioe) {
Console.Error.WriteLine(ioe.Message);
}
// step 5: we close the document
document.Close();
try {
//screenshots deleten
File.Delete(path);
} catch { }
return pdfURL;
}
This runs on a website, to make a PDF of a webpage.
However when multiple people access this code from the website, to generate their PDF's, I get the error: Object is currently in use elsewhere.
STACKTRACE: at System.Drawing.Image.Save(String filename, ImageCodecInfo encoder, EncoderParameters encoderParams) at ...
How would I fix this? The error gets thrown at Shot.Bitmap.Save(path, ImageFormat.Png);
I encountered the same problem, I have a worker thread pumping out GUI to its graphical interface, but it only throws this exception some of the time.
Wrapping it with an Invoke fixed it.
_parent.Invoke( new Action(() => eg.Graphics.DrawImage( _icon, rc )));
Just spotted this similar question. One of the answers suggests that GDI+ isn't threadsafe, in which case you'll need a lock around your Save() and maybe a few other methods.
Just to confirm, reading the information for the Image class, although it is ambiguous as to whether this means a single instance, or different instances of the same class.
Any public static (Shared in Visual Basic) members of this type are
thread safe. Any instance members are not guaranteed to be thread
safe.