הערה
הגישה לדף זה מחייבת הרשאה. באפשרותך לנסות להיכנס או לשנות מדריכי כתובות.
הגישה לדף זה מחייבת הרשאה. באפשרותך לנסות לשנות מדריכי כתובות.
Question
Saturday, January 30, 2016 2:09 AM
Hi there,
If I open a 2 mb (JPG) image from my camera and then save it like this:
Dim bmpOriginal As Bitmap = New Bitmap("c:\test\test.jpg")
bmp.Save("c:\test\test 2.png")
The saved file is 2 mb.
If I redraw the image and save it like this:
Dim bmpOriginal As Bitmap = New Bitmap("c:\test\test.jpg")
Using bmp As New Bitmap(bmpOriginal.Width, bmpOriginal.Height),
g As Graphics = Graphics.FromImage(bmp)
g.DrawImage(bmpOriginal, 0, 0, bmp.Height, bmp.Width)
bmp.Save("c:\test\test 3.png")
End Using
The saved file is 12 mb.
Why is the re-drawn memory bitmap a different file size?
I can save a jpg with guality settings using EncoderParameters and get a nice 200 kb file at 50 percent quality.
Is there a way to minimize the size of the redrawn PNG file saved similar to the above?
All replies (19)
Saturday, January 30, 2016 4:28 AM ✅Answered | 1 vote
If I open a 2 mb PNG image from my camera and then save it like this:
Dim bmpOriginal As Bitmap = New Bitmap("c:\test\test.jpg") bmp.Save("c:\test\test 2.png")
Why is the re-drawn memory bitmap a different file size?
Based on the code you have posted, I would say it's because you are saving a different bitmap. Or is that just a typo?
Is there a way to minimize the size of the redrawn PNG file saved similar to the above?
From the PNG description, file size is affected by:
color depth
Color depth can range from 1 to 64 bits per pixel.
ancillary chunks
PNG supports metadata—this may be useful for editing, but unnecessary for viewing, as on websites.
interlacing
As each pass of the Adam7 algorithm is separately filtered, this can increase file size.
filter
As a precompression stage, each line is filtered by a predictive filter, which can change from line to line. As the ultimate DEFLATE step operates on the whole image's filtered data, one cannot optimize this row-by-row; the choice of filter for each row is thus potentially very variable, though heuristics exist.
compression
With additional computation, DEFLATE compressors can produce smaller files.
However, in this case, I would also look at the size recorded for the image, and the actual size - it is possible that the camera has the wrong size information. You should also confirm that the saved file really is PNG, and not a BMP with a PNG filename extension.
Saturday, January 30, 2016 2:21 PM ✅Answered | 1 vote
Hey Tom,
I believe Acamar was reffering to this code you posted. It loads the image into a Bitmap named bmpOriginal but, you are saving a Bitmap named bmp instead of bmpOriginal.
Dim bmpOriginal As Bitmap = New Bitmap("c:\test\test.jpg")
bmp.Save("c:\test\test 2.png")
I don`t think you are going to get the Png image compressed enough to make it as small as a Jpg image can be compressed. I also tried it in 2 different image editors i have and they would not compress a png much more than i could get doing it in VB.Net.
As far as the files you are saving, saving the image as shown here will not save the image as a true Png file, it just changes the extension of the original.
Dim img As New Bitmap("C:\testfolder\map.jpg")
img.Save("C:\testfolder\newmap1.png")
If you set the Imaging.ImageFormat as shown here, it will save it as a Png file format.
Dim img As New Bitmap("C:\testfolder\map.jpg")
img.Save("C:\testfolder\newmap1.png", Imaging.ImageFormat.Png)
When you create a new bitmap and save it like this, you still need to set the ImageFormat or it will be saved by default as a Png format.
Dim img As New Bitmap("C:\testfolder\map.jpg")
Using bm As New Bitmap(img.Width, img.Height)
Using g As Graphics = Graphics.FromImage(bm)
g.DrawImage(img, 0, 0, bm.Width, bm.Height)
End Using
bm.Save("C:\testfolder\newmap2.png")
End Using
You can identify a true Png image by looking at the first 4 bytes of the saved file. If it is saved as a true PNG file the 2nd, 3rd, and 4th byte will be the ascii values for the letters "P" "N" "G".
000: 137
001: 80 P
002: 78 N
003: 71 G
If you say it can`t be done then i`ll try it
Saturday, January 30, 2016 4:12 AM | 1 vote
Hi,
I think what you're doing is only to change a file name.
It requires to encode from bitmap to png format.
Refer to BitmapEncoder Class
[note] change
* Dim encoder As New TiffBitmapEncoder()*
to
* Dim encoder As New PngBitmapEncoder()*
Regards.
Saturday, January 30, 2016 12:15 PM | 1 vote
You could use this parameter with the bitmap.Save command : -
bmp.Save("c:\test\test 2.png", Imaging.ImageFormat.Png)
and see if it saves as 12 mb
Certain textures are better saved as Jpeg - - like scenery, people etc
Top Tip: Toothache? Cut paper towel to 2"square. Smear with olive oil. Sprinkle on Cayenne Pepper. Fold over few times to form small wad. Tuck in between wall of mouth and gum. Leave 1 - 2 hrs. You will thank me!
Saturday, January 30, 2016 1:03 PM
Hi,
I think what you're doing is only to change a file name.
It requires to encode from bitmap to png format.
Refer to BitmapEncoder Class[note] change
* Dim encoder As New TiffBitmapEncoder()*
to
* Dim encoder As New PngBitmapEncoder()*Regards.
Ash,
Thanks. That looks encouraging. I got the sample to work, I think. However, loading the jpg image from a file and saving it gave a new png file 9.6 mb (from original 2 mb file).
Also, my real problem is saving a memory image that I draw where this method reads the image from a file. I am not sure how to change the source image to use the image I have drawn. However based on the result of reading from a file it does not seem to matter.
'add ref to PresentationCore
Imports System.Windows.Media.Imaging
Dim stream As New FileStream("c:\test\test 3.png", FileMode.Create)
Dim encoder As New PngBitmapEncoder()
Dim bi As New BitmapImage()
bi.BeginInit()
bi.UriSource = New Uri("c:\test\test.jpg", UriKind.RelativeOrAbsolute)
bi.EndInit()
encoder.Frames.Add(BitmapFrame.Create(bi))
encoder.Save(stream)
Saturday, January 30, 2016 1:04 PM
You could use this parameter with the bitmap.Save command : -
bmp.Save("c:\test\test 2.png", Imaging.ImageFormat.Png)
and see if it saves as 12 mb
Certain textures are better saved as Jpeg - - like scenery, people etc
Top Tip: Toothache? Cut paper towel to 2"square. Smear with olive oil. Sprinkle on Cayenne Pepper. Fold over few times to form small wad. Tuck in between wall of mouth and gum. Leave 1 - 2 hrs. You will thank me!
Leon,
Hmmm, 11.6 mb. Recall not using Imaging.ImageFormat.Png is 12 mb.
I have been under the impression if you dont spec the image type that image.save uses the file name extension?
Saturday, January 30, 2016 1:05 PM
If I open a 2 mb PNG image from my camera and then save it like this:
Dim bmpOriginal As Bitmap = New Bitmap("c:\test\test.jpg") bmp.Save("c:\test\test 2.png")
Why is the re-drawn memory bitmap a different file size?
Based on the code you have posted, I would say it's because you are saving a different bitmap. Or is that just a typo?
Is there a way to minimize the size of the redrawn PNG file saved similar to the above?
From the PNG description, file size is affected by:
color depth
Color depth can range from 1 to 64 bits per pixel.
ancillary chunks
PNG supports metadata—this may be useful for editing, but unnecessary for viewing, as on websites.
interlacing
As each pass of the Adam7 algorithm is separately filtered, this can increase file size.
filter
As a precompression stage, each line is filtered by a predictive filter, which can change from line to line. As the ultimate DEFLATE step operates on the whole image's filtered data, one cannot optimize this row-by-row; the choice of filter for each row is thus potentially very variable, though heuristics exist.
compression
With additional computation, DEFLATE compressors can produce smaller files.
However, in this case, I would also look at the size recorded for the image, and the actual size - it is possible that the camera has the wrong size information. You should also confirm that the saved file really is PNG, and not a BMP with a PNG filename extension.
Acamar,
"Based on the code you have posted, I would say it's because you are saving a different bitmap. Or is that just a typo?"
Ummm, I am not sure what you mean I guess. In the second example the saved image is the image read from file redrawn to a memory bitmap and then saved as png.
"However, in this case, I would also look at the size recorded for the image, and the actual size - it is possible that the camera has the wrong size information. You should also confirm that the saved file really is PNG, and not a BMP with a PNG filename extension."
Yeah. Ha ha. Easy for you to say. How to I check to see if it is really BMP format?
I also dont know how to check the "size recorded".
On a hunch I opened the original 2 mb jpg in Windows Paint and saved it as a png and the saved file is 10mb. So similar to the other results.
Saturday, January 30, 2016 1:25 PM
So I tried this 640 kb jpg and saved as png and the saved file is 1.15 mb. Not the 5x increase in size but still 2x increase?
'add ref to PresentationCore
Imports System.Windows.Media.Imaging
Dim stream As New FileStream("c:\test\test 6.png", FileMode.Create)
Dim encoder As New PngBitmapEncoder()
Dim bi As New BitmapImage()
bi.BeginInit()
bi.UriSource = New Uri("c:\bitmaps\starwars\Space scene planet ship fleet.jpg", UriKind.RelativeOrAbsolute)
bi.EndInit()
encoder.Frames.Add(BitmapFrame.Create(bi))
encoder.Save(stream)
PS Opening the above jpg in Paint and saving as PNG gives 1.4 mb file.
Saturday, January 30, 2016 1:44 PM | 1 vote
Tom
I've always assumed that if you don't specify a file format then the png format is used by Image.Save
That appears to be true if you create an image and draw it yourself but if you load an image from file and then save it without specifying a file format it saves it in the original format provided that there is an encoder available for that format. It only reverts to using png if there is no encoder for the format (e.g. for wmf files).
So, for instance, if you just create an empty 1000x1000 bitmap and save it you get a 6kbyte png file. If you specify bmp format you get a 4Mbyte file. If you then open the bitmap you have just saved using Image.FromFile(filename) and save that without specifying a format you get a 4Mbyte file. Specifying png format you get the 6kbyte file again.
Saturday, January 30, 2016 2:22 PM
I opened the original 2 mb jpg in Paint and saved as .bmp for a 25 mb file.
Then I opened the .bmp and saved as png with my last sample code and get a 9.4 mb png file. So that is the same as if I redraw the jpg image and save it as png.
I guess you just get a bunch of new interpolated bits from the jpg when you draw it or save as bmp. Since the jpg was compressed the new bits are bogus but still there.
As I say I can draw the original jpg image and save it as jpg specifying 50 percent compression and get a 250 kb jpg.
Saturday, January 30, 2016 2:57 PM | 1 vote
Hey Tom,
I believe Acamar was reffering to this code you posted. It loads the image into a Bitmap named bmpOriginal but, you are saving a Bitmap named bmp instead of bmpOriginal.
Dim bmpOriginal As Bitmap = New Bitmap("c:\test\test.jpg") bmp.Save("c:\test\test 2.png")
I don`t think you are going to get the Png image compressed enough to make it as small as a Jpg image can be compressed. I also tried it in 2 different image editors i have and they would not compress a png much more than i could get doing it in VB.Net.
As far as the files you are saving, saving the image as shown here will not save the image as a true Png file, it just changes the extension of the original.
Dim img As New Bitmap("C:\testfolder\map.jpg") img.Save("C:\testfolder\newmap1.png")
If you set the Imaging.ImageFormat as shown here, it will save it as a Png file format.
Dim img As New Bitmap("C:\testfolder\map.jpg") img.Save("C:\testfolder\newmap1.png", Imaging.ImageFormat.Png)
And when you create a new bitmap and save it like this, it will use the extension and will actually save it as a Png file format.
Dim img As New Bitmap("C:\testfolder\map.jpg") Using bm As New Bitmap(img.Width, img.Height) Using g As Graphics = Graphics.FromImage(bm) g.DrawImage(img, 0, 0, bm.Width, bm.Height) End Using bm.Save("C:\testfolder\newmap2.png") End Using
You can identify a true Png image by looking at the first 4 bytes of the saved file. If it is saved as a true PNG file the 2nd, 3rd, and 4th byte will be the ascii values for the letters "P" "N" "G".
000: 137
001: 80 P
002: 78 N
003: 71 G
If you say it can`t be done then i`ll try it
Oh, I see. Doh!
Ok then I fixed it and now this:
Dim bmp3 As Bitmap = New Bitmap("c:\test\test.jpg")
bmp3.Save("c:\test\test 9.png", Imaging.ImageFormat.Png)
give an 11.8 mb png file. Same as the others.
Also saving this way I dont get a good thumbnail icon in windows file explorer but if I open the file in paint it is fine. Here is the icon I get and the original. Not sure why that is?
Well I guess the bottom line is png does not compress like jpg, and that makes sense since PNG is "lossless" compression.
I was just trying to make sense of it and see if there was any quality compression setting for PNG but I guess not.
And my error was confusing me, now it makes more sense.
So I marked Razerz (and Acamar) as the answer.
Saturday, January 30, 2016 3:14 PM | 1 vote
Razerz,
I opened the saved png in notepad and this is the start:
‰PNG
**IHDR @ **
° ÆŸ‹Ø sRGB ®Îé gAMA ±? üa pHYs 0J 0JÂ8Øã +tEXtDescription OLYMPUS DIGITAL CAMERA ”x¼ç tEXtSource E-520 E‰)§ (tEXtSoftware Version 1.1 ±’^À tIMEà%QÐTz tEXtCreationTime 2016:01:29 01:37:263!¾Ç þØIDATx^tý“%É•¥ â_u#3ƒ;çœsÎ9}îþ8'îÏYDd&H¡€êîêéšÞ?•žYÙÝ!R2]U(?*ÐM
ΓƒeÆžs?šºE$Z䈊ššêÕ«júž?SûüÚ'šên5ÔøwíõϵÕ}‡5¨ÿ\sÍ ¨ÖÞÀú¦[u/4Õ=ßXû\cÝ-﬿ÝU{«£î¨µþ“͵ÿ®©þß77|²«åv[L=ßQ»³áN[ííÖ¤ÎN{lÞn}jkx¡£évkã-¨¥évsã¶–;íw[›žoo¾ÓÙt½C?M÷¡ŽÆ{mMwÚ›ï"…ZÑðvG£ªq8mM÷Z‘¿ßÕ\ÛÝTÛQ¿£þnWãýîÆ»P—ÓýΆ{]?5PwÓƒžf¤8¼ÛÙøBWÓÎæ;2ˆ¾PÍjÞÅp¶³ñ¶Õds•ã°»ù.ÔÓr?j¾/õ¶
So I quess the %PNG means it is png?
What software would I use to see the bytes like you show them:
000: 137
001: 80 P
002: 78 N
003: 71 G
Saturday, January 30, 2016 3:32 PM | 1 vote
What software would I use to see the bytes like you show them:
I don`t use any software to do it, i just read the bytes of the file and look at the byte vales. You could do it similar to this in Vb.Net.
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim bts() As Byte = IO.File.ReadAllBytes("C:\testfolder\newmap.png")
RichTextBox1.AppendText(bts(1).ToString & " = " & ChrW(bts(1)) & vbNewLine)
RichTextBox1.AppendText(bts(2).ToString & " = " & ChrW(bts(2)) & vbNewLine)
RichTextBox1.AppendText(bts(3).ToString & " = " & ChrW(bts(3)) & vbNewLine)
End Sub
Different image formats are saved in different ways so, to test for different formats you would need to look at some documents to see how the bytes of the file are saved in order to check them.
If you say it can`t be done then i`ll try it
Saturday, January 30, 2016 5:49 PM
And when you create a new bitmap and save it like this, it will use the extension and will actually save it as a Png file format.
Dim img As New Bitmap("C:\testfolder\map.jpg") Using bm As New Bitmap(img.Width, img.Height) Using g As Graphics = Graphics.FromImage(bm) g.DrawImage(img, 0, 0, bm.Width, bm.Height) End Using bm.Save("C:\testfolder\newmap2.png") End Using
I don't think it does. If you are using an image which hasn't come from a file and don't specify a file format then it will save as a png. But it doesn't use the extension. Try changing the extension to jpg and it will still save it as a png.
Saturday, January 30, 2016 6:17 PM
And when you create a new bitmap and save it like this, it will use the extension and will actually save it as a Png file format.
Dim img As New Bitmap("C:\testfolder\map.jpg") Using bm As New Bitmap(img.Width, img.Height) Using g As Graphics = Graphics.FromImage(bm) g.DrawImage(img, 0, 0, bm.Width, bm.Height) End Using bm.Save("C:\testfolder\newmap2.png") End Using
I don't think it does. If you are using an image which hasn't come from a file and don't specify a file format then it will save as a png. But it doesn't use the extension. Try changing the extension to jpg and it will still save it as a png.
Yep, you`re right. You still need to use set the ImageFormat if you want anything other than a Png. I should have experimented with that a little more. A new bitmap appears to always be saved by default as a Png format unless, you set the ImageFormat.
If you say it can`t be done then i`ll try it
Saturday, January 30, 2016 8:01 PM | 1 vote
I opened the original 2 mb jpg in Paint and saved as .bmp for a 25 mb file.
Then I opened the .bmp and saved as png with my last sample code and get a 9.4 mb png file. So that is the same as if I redraw the jpg image and save it as png.
That would be expected. A BMP by default has no compression - the size is pretty much widthxheightxbytes per pixel. A PNG will have compression, but it is a lossless compression. It is exactly the same image as the BMP but a bit smaller file size. JPG is a lossy compression, so you can choose how much gets lost, and get much smaller file sizes. But the image is different - a lot of detail is lost. Every time you save a JPG image you lose a bit more of the original.
Saturday, January 30, 2016 11:55 PM
I opened the original 2 mb jpg in Paint and saved as .bmp for a 25 mb file.
Then I opened the .bmp and saved as png with my last sample code and get a 9.4 mb png file. So that is the same as if I redraw the jpg image and save it as png.
That would be expected. A BMP by default has no compression - the size is pretty much widthxheightxbytes per pixel. A PNG will have compression, but it is a lossless compression. It is exactly the same image as the BMP but a bit smaller file size. JPG is a lossy compression, so you can choose how much gets lost, and get much smaller file sizes. But the image is different - a lot of detail is lost. Every time you save a JPG image you lose a bit more of the original.
I see more or less.
Well I got to wondering what happens when you go the other direction ie jpg to bmp. Of course the image losses from the jpg compression have to be restored for the bmp file but what is that? Just empty pixels or some interpolation approximation of the jpg? I dont know what the words are to describe it.
And so when I had the error in my first example where I am not sure what was saved, but, it was the same 2mb as the original I got thinking the png just reproduced the jpg exactly and I wanted it to do that for my jpg instead of blowing it up x5. Of course I was making an error. I guess the x5 is just empty space?
PS I guess the extra size is the repeated pixels that were compressed out. Or whatever it does to compress ie gif, video, jpg and then restore on the screen. A bmp would be the full screen pixel by pixel and the rest are compressed however?
Sunday, January 31, 2016 1:08 AM | 1 vote
I guess the extra size is the repeated pixels that were compressed out. Or whatever it does to compress ie gif, video, jpg and then restore on the screen. A bmp would be the full screen pixel by pixel and the rest are compressed however?
To display a JPG image the file data needs to be processed and the image restored, as best it can be, given that some information has been lost. At that point it's just another image. When you save in a lossless format you save that restored image, pixel-by-pixel, which will include any artifacts created from the JPG compressing/uncompressing. That process is based on complex mathematical rules specifically designed to represent image data as efficiently as possible. It is very effective for 'scenic' images (many small colour changes) and very poor at 'drawing' images (fewer but more sudden color changes, and large areas of the same colour). Other compression algorithms tend to do the opposite.
Sunday, January 31, 2016 1:36 AM
I guess the extra size is the repeated pixels that were compressed out. Or whatever it does to compress ie gif, video, jpg and then restore on the screen. A bmp would be the full screen pixel by pixel and the rest are compressed however?
To display a JPG image the file data needs to be processed and the image restored, as best it can be, given that some information has been lost. At that point it's just another image. When you save in a lossless format you save that restored image, pixel-by-pixel, which will include any artifacts created from the JPG compressing/uncompressing. That process is based on complex mathematical rules specifically designed to represent image data as efficiently as possible. It is very effective for 'scenic' images (many small colour changes) and very poor at 'drawing' images (fewer but more sudden color changes, and large areas of the same colour). Other compression algorithms tend to do the opposite.
Acamar,
Yeah, I have noticed gif does real well for my CAD drawings which are distict lines but then not as well for other things like photo maybe. Jpg is not too good with the CAD drawings. Like you say the lines or edges are slightly blurred.
Gets into if you zoom a highly compressed jpg you see the pixelation? blocks that its makes as part of the compression scheme. A gif file does somekind of repeating of the pixels that are the same or something.
I guess the "complex mathmatics" is in the codec or encoder and the system uses that to save and restore. Each codec has its own, propriatary way.
It sure is nice now that it is so easy and we have saving the different formats built into vb.