I'm using this code to save image
PictureBox1.Image.Save(filePath)
after that I crop image and I want to save it again by replacing the old one with the new cropped one
any help please
regards,,,
Use the following code when you load the image into the PictureBox instead of the one you are currently using and you'll be fine just saving later. The using statement ensures the file is released once the image is loaded.
Replace filePath with your own.
Using stream as new FileStream(filePath, FileMode.Open, FileAccess.Read)
PictureBox1.Image = Image.FromStream(stream)
End Using
EDIT
From your last comment I can see this code
Try
Me.Opacity = 0%
Me.PictureBox1.Image = cc()
PictureBox1.Image.Save(filePath)
source = Image.FromFile(filePath)
PictureBox1.Image = source
TextBox1.Text = filePath
Me.Opacity = 100%
Catch ex As Exception
MsgBox(ex.Message)
End Try
You don't need to reload the image to the PictureBox after saving. Just get rid of the following lines.
source = Image.FromFile(filePath)
PictureBox1.Image = source
That should solve your problem at least for now as you won't be saving the image to the same image you load it from (you didn't actually load it). But you will have to find a better solution for your whole algorithm later :)
This's the answer
Dim bmp1 As New Bitmap(PictureBox1.Image)
If System.IO.File.Exists(filePath) Then
System.IO.File.Delete(filePath)
End If
bmp1.Save(filePath, System.Drawing.Imaging.ImageFormat.Jpeg)
' Dispose of the image files.
bmp1.Dispose()
Related
I am using an Axiohm thermal printer for printing POS receipt(USBCOMM.dll for communication). Currently, i am able to print the required details along with an image(.bmp file). Now i need to use a new image instead of the existing image. The new image contains barcode.
When i try printing the new image, all i get is some garbage values. Below is the code that i use. Same code works with old image but not with the new image. Is there any format for image that i need to follow.
Dim filepath As String = AppDomain.CurrentDomain.BaseDirectory + "Resources\PrinterDlls\unnamed.bmp"
Using fs = New FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.Read)
Dim inpt As Byte() = New Byte(fs.Length) {}
inpt(0) = &H1F
fs.Read(inpt, 1, CInt(fs.Length))
Dim ok As Boolean = Usb_WritePort(True, inpt, inpt.Length, written, IntPtr.Zero)
If Not ok OrElse written <> inpt.Length Then
Throw New Exception("USB write failed")
End If
End Using
Well, this is embarrassing that i am answering my own question. I searched for sometime to resolve and raised the question. Soon after, i came across this video in youtube that explain the bitmap image to create for thermal printing
https://www.youtube.com/watch?v=LdB33eWLjgU
Basically, you need to ensure 3 things while creating the image:
1. 8-bit
2. Greyscale
3. Save as .bmp
And the new image will work like a charm while printing. Also ensure the width is less than the paper width.
When using the axAcroPdfLib.AxAcroPDF control in my Windows Forms application, I'm not able to reload the same image. The image is initially loaded with the LoadFile() method.
Upon using the LoadFile() method again on the same path AFTER saving changes to the PDF, the control becomes blank (no PDF shown).
If I set the src property of the control to the path, I get a message saying the file does not begin with '%PDF-'. But it does. I opened it with Word and it clearly begins with %PDF-. It's not corrupt or locked either.
I've even tried closing, disposing, or setting it to Nothing, and then completely re-instantiating it as I did the first time it's loaded - no effect. The window closes and shows with the control blank.
Loading a different file via the above methods has the same effect - blank.
Using Windows 7 64-bit, VS 2010, VB.NET.
The code is below. For right now, I'm just trying to draw a simple line on it.
Private Sub _btnBarCode_Click(ByVal sender As Object, ByVal e As EventArgs) Handles _btnBarCode.Click
Dim pdfReader As iTextSharp.text.pdf.PdfReader = Nothing
Try
pdfReader = New iTextSharp.text.pdf.PdfReader(File.ReadAllBytes(_path))
Using fs As New FileStream(_path, FileMode.Create, FileAccess.Write)
Using pdfStamper = New iTextSharp.text.pdf.PdfStamper(pdfReader, fs)
Dim pdfPage As iTextSharp.text.pdf.PdfContentByte = pdfStamper.GetOverContent(1)
Using barCodeForm As New FBarCode
barCodeForm.Barcode = _barCode
If (barCodeForm.ShowDialog(Me) = DialogResult.OK) Then
Dim screenBarCode As Point = barCodeForm.Location
Dim clientBarCode As Point = Point.op_Subtraction(PointToClient(screenBarCode), New Point(0, 50)) '_pdfControl.Location '_imgView.Location
clientBarCode = New Point(10, 50)
Dim barcodeImg As New Bitmap(200, 50)
Using gc As Graphics = Graphics.FromImage(barcodeImg)
gc.DrawLine(Pens.Red, New Point(10, 10), New Point(20, 20))
'barCodeForm._barCode.DrawBarCode(gc, clientBarCode)
End Using
Dim convert As ImageConverter = New ImageConverter()
Dim bmpBytes As Byte() = DirectCast(convert.ConvertTo(barcodeImg, GetType(Byte())), Byte())
Dim thisImage As iTextSharp.text.Image = iTextSharp.text.Image.GetInstance(bmpBytes)
thisImage.SetAbsolutePosition(clientBarCode.X, clientBarCode.Y)
thisImage.SetDpi(72, 72)
pdfPage.AddImage(thisImage)
rdrAdobePdf.LoadFile(_path) 'Blank pdf
'rdrAdobePdf.src = _path '"Does not begin with '%PDF-' (even though it does)
'Me.Close()
'_myParent.ResetPdfViewer()
'ReloadPdfViewer(Me.Barcode)
End If
End Using
End Using
End Using
Catch ex As Exception
MessageBox.Show(ex.Message, "An error occurred.")
Return
Finally
If Not pdfReader Is Nothing Then pdfReader.Close()
End Try
End Sub
Any ideas what could be the problem here?
Problem was solved by getting the reloading code out of that click method. Putting it in another click method solved the problem - not sure why. The code I used just ran .LoadFile, then Form.Show() and Form.Activate().
I am using following code to put JPG's into a DataGridView's Image cell.
If strFileName.ToLower.EndsWith(".jpg") Then
Dim inImg As Image = Image.FromFile(strFileName)
DataGridView4.Rows.Add()
DataGridView4.Rows(DataGridView4.Rows().Count - 1).Cells(0).Value = inImg
End If
The problem is that I need to save this file from within the program, but i get the message that the file is beeing used by another program.
So i tried to add inImg.Dispose() before the end if, but then the program doesnt display the images anymore in the DataGridView.
How can i add images in the DataGridView without locking them?
thanks
When you use the Image.FromFile(strFileName) method to create the Image, the method locks the file until you release the Image. The exact reason is explained below. And it's why you can't access more than one time to the same image file with this method.
You could instead:
use the Image.FromStream(stream) method.
that you use with a New FileStream or a MemoryStream that you create from the image file.
Here are possible implementation of a custom SafeImageFromFile method that doesn't lock the image file:
Public Shared Function SafeImageFromFile(path As String) As Image
Using fs As New FileStream(path, FileMode.Open, FileAccess.Read)
Dim img = Image.FromStream(fs)
Return img
End using
End Function
Or
Public Shared Function SafeImageFromFile(path As String) As Image
Dim bytes = File.ReadAllBytes(path)
Using ms As New MemoryStream(bytes)
Dim img = Image.FromStream(ms)
Return img
End Using
End Function
Usage
If strFileName.ToLower.EndsWith(".jpg") Then
Dim inImg As Image = SafeImageFromFile(strFileName)
Dim index as integer = DataGridView4.Rows.Add()
DataGridView4.Rows(index).Cells(0).Value = inImg
End If
Important note
Here I create the FileStream or a MemoryStream using a Using statement to make sure the stream is released. It works fine on my system and it seems it work for you too, though MSDN says about Image.FromStream(stream) method:
You must keep the stream open for the lifetime of the Image.
The reason of this sentence is explain here: KB814675 Bitmap and Image constructor dependencies
GDI+, and therefore the System.Drawing namespace, may defer the
decoding of raw image bits until the bits are required by the image.
Additionally, even after the image has been decoded, GDI+ may
determine that it is more efficient to discard the memory for a large
Bitmap and to re-decode later. Therefore, GDI+ must have access to the
source bits for the image for the life of the Bitmap or the Image
object.
To retain access to the source bits, GDI+ locks any source file, and
forces the application to maintain the life of any source stream, for
the life of the Bitmap or the Image object.
So know the code above could generate GDIexceptions because of releasing the stream using Using. It could happen when you save the image from the file or during the image creation. From this thread Loading an image from a stream without keeping the stream open and Hans Passant's comment they fixed several problems with indexed pixel formats in the Vista version of gdiplus.dll., it would happen only on XP.
To avoid this you need to keep the stream open. The methods would be:
Public Shared Function SafeImageFromFile(path As String) As Image
Dim fs As New FileStream(path, FileMode.Open, FileAccess.Read)
Dim img = Image.FromStream(fs)
Return img
End Function
Or
Public Shared Function SafeImageFromFile(path As String) As Image
Dim bytes = File.ReadAllBytes(path)
Dim ms = New MemoryStream(bytes)
Dim img = Image.FromStream(ms)
Return img
End Function
But those last methods have some disadvantage like not releasing the stream (memory issue) and they violate rule CA2000 Dispose objects before losing scope .
The KB article gives some workarounds:
Create a Non-Indexed Image
This approach requires that the new image be in a non-indexed pixel
format (more than 8 bits-per-pixel), even if the original image was in
an indexed format. This workaround uses the Graphics.DrawImage()
method to copy the image to a new Bitmap object:
Construct the original Bitmap from the stream, from the memory, or from the file.
Create a new Bitmap of the same size, with a pixel format of more than 8 bits-per-pixel (BPP).
Use the Graphics.FromImage() method to obtain a Graphics object for the second Bitmap.
Use Graphics.DrawImage() to draw the first Bitmap onto the second Bitmap.
Use Graphics.Dispose() to dispose of the Graphics.
Use Bitmap.Dispose() to dispose of the first Bitmap.
Create an Indexed Image
This workaround creates a Bitmap object in an indexed format:
Construct the original Bitmap from the stream, from the memory, or from the file.
Create a new Bitmap with the same size and pixel format as the first Bitmap.
Use the Bitmap.LockBits() method to lock the whole image for both Bitmap objects in their native pixel format.
Use either the Marshal.Copy function or another memory copying function to copy the image bits from the first Bitmap to the second Bitmap.
Use the Bitmap.UnlockBits() method to unlock both Bitmap objects.
Use Bitmap.Dispose() to dispose of the first Bitmap.
Here is an implementation of Non-Indexed Image creation, based on KB article and this answer https://stackoverflow.com/a/7972963/2387010 Your best bet is creating a pixel-perfect replica of the image -- though YMMV (with certain types of images there may be more than one frame, or you may have to copy palette data as well.) But for most images, this works:
Private Shared Function SafeImageFromFile(path As String) As Bitmap
Dim img As Bitmap = Nothing
Using fs As New FileStream(path, FileMode.Open, FileAccess.Read)
Using b As New Bitmap(fs)
img = New Bitmap(b.Width, b.Height, b.PixelFormat)
Using g As Graphics = Graphics.FromImage(img)
g.DrawImage(b, Point.Empty)
g.Flush()
End Using
End Using
End Using
Return img
End Function
Someone indicated that what is important is that the FileStream is opened in read mode (FileAccess.Read).
True, but it makes more sens if you don't use Using statement and so you don't release the stream, or in multi threads context: FileAccess.Write is inappropriate, and FileAccess.ReadWrite is not required, but open the stream with FileAccess.Read mode won't prevent to have an IO.Exception if another program (or yours in multi threads context) has opened the file with another mode than FileAccess.Read.
If you want to be able to display the image and at the same time be able to save data to the file, Since you don't lock the file with those methods, you should be able to save the image (delete/overwrite the previous file) using the Image.Save method.
# Chris: Opening approximately 100 large (3400x2200) images with your final code, I was receiving an invalid argument crash on [img = new bitmap(...], I have seen this before opening an image of zero size, but that was not the case here. I added fs.dispose and successfully opened thousands of images of the same size of the same set as the first test without issue. I'm interested in your comments on this.
Private Function SafeImageFromFile(FilePath As String) As Image
Dim img As Bitmap = Nothing
Using fs As New FileStream(FilePath, FileMode.Open, FileAccess.Read)
Using b As New Bitmap(fs)
img = New Bitmap(b.Width, b.Height, b.PixelFormat)
Using g As Graphics = Graphics.FromImage(img)
g.DrawImage(b, Point.Empty)
g.Flush()
End Using
End Using
fs.Dispose()
End Using
Return img
End Function
This works without issue, ran 4189 images 3400x2200 through it (twice) without issue, this moves the filestream outside of the function and re-uses it. Im closing the file to release the write lock. Im pointing a picturebox at this image in a loop for my test.
Private fsIMG As FileStream
Private Function SafeImageFromFile(FilePath As String) As Image
'Ref: http://stackoverflow.com/questions/18250848/how-to-prevent-the-image-fromfile-method-to-lock-the-file
Dim img As Bitmap = Nothing
fsIMG = New FileStream(FilePath, FileMode.Open, FileAccess.Read)
Using b As New Bitmap(fsIMG)
img = New Bitmap(b.Width, b.Height, b.PixelFormat)
Using g As Graphics = Graphics.FromImage(img)
g.DrawImage(b, Point.Empty)
g.Flush()
End Using
End Using
fsIMG.Close()
Return img
End Function
After searching the internet for long time I found out I can use this code without any error.
Private fsIMG As FileStream
Private Function SafeImageFromFile(FilePath As String) As Image
'Ref: http://stackoverflow.com/questions/18250848/how-to-prevent-the-image-fromfile-method-to-lock-the-file
Dim img As Bitmap = Nothing
fsIMG = New FileStream(FilePath, FileMode.Open, FileAccess.Read)
Using b As New Bitmap(fsIMG)
img = New Bitmap(b.Width, b.Height, b.PixelFormat)
Using g As Graphics = Graphics.FromImage(img)
g.DrawImage(b, Point.Empty)
g.Flush()
End Using
End Using
fsIMG.Close()
Return img
End Function
I encountered the same situation and used this code:
' Create memory stream from file
Dim ms As New MemoryStream()
' Open image file
Using fs As New FileStream(.FileName, FileMode.Open, FileAccess.Read)
' Save to memory stream
fs.CopyTo(ms)
End Using
' Create image from the file's copy in memory
Dim img = Image.FromStream(ms)
I didn't dispose the memory stream because it allows to save the image later using exactly the same encoding as the original file, using this code:
img.Save(someOtherStream, img.RawFormat)
I'm having trouble loading an image from My.Resources. I have already tried a no. of codes like....:
PictureBox1.Image = My.Resources.Online_lime_icon; And
PictureBox1.Image = CType(My.Resources.ResourceManager.GetObject("Online_lime_icon"), Image)
but it would still return:
Picturebox1.Image = Nothing
Try to convert it ToBitMap()
PictureBox1.Image = My.Resources.Online_lime_icon.ToBitmap()
EDIT:
#user1615710 : My.Resources.Online_lime_icon doesn't have .ToBitmap. It only has .ToString.
That means you've String resource and I think it represents fileName with or without absolute path.
Try to print/show the content of My.Resources.Online_lime_icon
Debug.Print(My.Resources.Online_lime_icon) 'or
MsgBox(My.Resources.Online_lime_icon)
If it is real path then load the image via,
PictureBox1.Image = Image.FromFile(My.Resources.Online_lime_icon)
I'm opening a file called tempImage.jpg and showing it on a form in a PictureBox. I then click a button called Clear and the file is removed from the PictureBox using PictureBox2.Image = Nothing, however I'm unable to delete the file as it is locked open. How can I release it so I can delete it? I'm using VB.NET and a forms app.
Thanks
When you use PictureBox2.Image = Nothing you're waiting for the garbage collector to finalize the resource before it releases it. You want to release it immediately, so you need to dispose of the image:
Image tmp = PictureBox2.Image
PictureBox2.Image = Nothing
tmp.Dispose()
If you're using Image.FromFile, you need to call .Dispose() on the image. When you go to clear it out, do something like...
Image currentImage = pictureBox.Image
pictureBox.Image = Nothing
currentImage.Dispose()
That will release the file.
take control of the file
'to use the image
Dim fs As New IO.FileStream("c:\foopic.jpg", IO.FileMode.Open, IO.FileAccess.Read)
PictureBox1.Image = Image.FromStream(fs)
'to release the image
PictureBox1.Image = Nothing
fs.Close()
is there a equivalent to using in vb.net
this is what i would do in c#
using( filestream fs = new filestream)
{
//whatever you want to do in here
}
//closes after your done
As i can't comment yet (not enough experience points), this is an answer for the above
"is there a equivalent to using in vb.net"
Yes, in .Net 2.0 and above you can use "Using".
In .Net 1.0 and 1.1 however, you would need to dispose if the object in the finally block
Dim fs As System.IO.FileStream = Nothing
Try
'Do stuff
Finally
'Always check to make sure the object isnt nothing (to avoid nullreference exceptions)
If fs IsNot Nothing Then
fs.Close()
fs = Nothing
End If
End Try
Adding the closing of the stream in the finally block ensures that it will get closed no matter what (as opposed to the connection getting opened, a line of code bombing out beneath before the stream is closed, and the stream staying open and locking the file)