how can a 512x512 bmp image have 1MB of size - vb.net

my code to save bmp format:
ImgResult.Save(dlgSavePicture.FileName, System.Drawing.Imaging.ImageFormat.Bmp)
I have tried the code and the output is a 512x512 bmp image with 1 megabyte size
if i use ms paint to create a 515x512 bmp image, the size is 768kb
i have tried to open the image and resave as bmp and the size still 1MB
can a 512x512 bmp image size upto 1mb in 512x512? or there are something wrong with my code?

BMP is a very simple image file format. Just a little header that describes the image (size, pixel format, resolution, color table), followed by a blob of pixel data. Technically it can be compressed with RLE but encoders don't bother anymore. The pixel data depends on the pixel format, ancient ones are 1bpp, 4bpp and 8bpp, they require a color table. 16bpp can happen, unusual, normal ones are 24bpp (RGB) and 32bpp (ARGB). In other words, 3 or 4 bytes per pixel.
So yes, 512 x 512 x 4 ~= 1 megabyte. MSPaint is pretty explicit about the pixel format it uses. It is a very simple painting program without support for alpha blending effects. So uses 24bpp (no alpha), 512 x 512 x 3 ~= 786 kilobytes. You could use Paint.NET to create 32bpp BMPs.
Which one you get in your own program depends on how you created the Bitmap object. The simple version uses the same pixel format as the video adapter. On all modern machines that's 32bpp. 16bpp can happen, it is very unusual. If you want another format then you have to use the Bitmap constructor that takes a PixelFormat argument.
There's otherwise a pretty good reason to do this, the default pixel format is not usually the most optimal one. The best one by a factor of 10 is the format that matches the pixel format of the video adapter exactly. Choice is between 32bppArgb and 32bppPArgb. The P means "pre-multiplied", the alpha value is applied to the RGB values up front. Argb is most efficient if you do a lot of drawing into the bitmap yourself with Graphics.FromImage(). PArgb is most efficient for painting, the pixel data can be blitted to the video frame buffer directly without having to be converted. Ten times faster. You usually care about painting speed, the most visible artifact of a program.
If you care about image file size then there is no better choice than PNG. It compresses the pixel data with LZW compression, typical compression rates are 50% or better. JPEG is a decent choice as well, much higher compression rates, but it is lossy. It achieves high rates by throwing away image details. Suitable for photos, in general images without text or line art, that don't otherwise have to be compressed multiple times.

i have tried this code
Public Function ConvertTo24bpp(img As Image) As Bitmap
Dim bmp = New Bitmap(img.Width, img.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb)
Using gr = Graphics.FromImage(bmp)
gr.DrawImage(img, New Rectangle(0, 0, img.Width, img.Height))
End Using
Return bmp
End Function
ImgResult = New Bitmap(Original)
For j = 0 To Original.Height - 1
For i = 0 To Original.Width - 1
ImgResult.SetPixel(i, j, Color.FromArgb(resultArray2(j, i, 0), originalArray(j, i, 1), resultArray2(j, i, 2)))
Next
Next
Dim clone As Bitmap
clone = ConvertTo24bpp(ImgResult)
clone.Save(dlgSavePicture.FileName)
the output is 24bit 512x512 bmp image but it size is ~640 KB not ~678 KB
i think the output is png format with bmp extension
is my code gone wrong?

Related

Animated GIF larger than source images

I'm using imagemagick to create an animated GIF out of ~60 JPG 640x427px photos. The combined size of the JPGs is about 4MB.
However, the output GIF is ~12MB. Is there a reason why the GIF is considerably bigger? Can I conceivably achieve a GIF size of ~4MB?
The command I'm using is:
convert -channel RGB # no improvement in size
-delay 2x10 \
-size 640 \
-loop 0 \
-dispose Background # no improvement in size
-layers Optimize # about 2MB improvement
portrait/*.jpg portrait.gif
Using gifsicle didn't seem to improve either.
JPG is lossy compression.
GIF is lossless compression.
A better comparison would be to convert all the source images to GIF first, then combine them..
First google hit for GIF compression is http://ezgif.com/optimize which claims lossy GIF compresion, might work for you but I offer no warranty as I haven't tried it.
JPEG achieves it's compression through a (lossy) transform, where an 16x16 / 8x8 block of pixels is transformed to frequency representation and then quantized. Instead of selecting e.g. 256 levels (i.e. 8 bits) of red/green/blue per component, JPEG can ignore some frequency components, or use just 1 or 2 bits to represent them.
GIF on the other hand works by identifying repeated patterns from a paletted image (upto 256 entries), which occur exactly in the previously encoded/decoded stream. Both because of the JPEG compression, and the source of the images typically encoded by JPEG (natural full color), the probability of (long) exact matches is quite low.
60 RGB images with the size 640x427 is about 16 million pixels. To represent that much in 4 MB, requires a compression of 2 bits per pixel. To achieve this with GIF would require a very lossy algorithm, that would select (vector) quantization of true color pixels not to the closest pixel in the target GIF palette, but based also on the fact how good dictionary of code words this particular selection will make. The dictionary builds slowly and to achieve 2 bits/pixel, the average length of the decoded code word would have to map to 5.5 matching pixels in the close neighborhood.
By contrast, imagemagick has been able to compress the 16 million pixels (each selected from a palette of 256 elements) to 75% already!

How to convert 32 bit PNG to RGB565?

How can I accomplish this? A programmatic solution (Objective-c) is great, but even a non-progarmmatic one is good.
I have pixelmator -> But that doesn't give you the option. I can't seem to do it with Preview either.
I have tried googling, but haven't been able to find a solution so far. The only tool I have been able to use to do this is TexturePacker, but that creates a sprite sheet.
You can use libpng to convert the PNG image to three-byte (8:8:8) RGB. Then you can downsample to the 5:6:5 16-bit color values of RGB565. If r, g, and b are the respective 8-bit colors (stored in an unsigned char type), then the 16-bit RGB565 value is:
((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3)
You can improve a tad on this by rounding instead of chopping, being careful to not overflow the values. You can also force the green value to be equal to the blue and red values when they are all equal in the original 8-bit values. Otherwise it is possible to have colors that were originally gray inadvertently take on color after conversion.
Create Bitmap Context with color RGB565 using Quartz, paint your PNG on this context, save this bitmap context to file.
PNG does not support a RGB565 packing. You can always apply a posterize to the image (programatically or with ImageMagick or with any image editor), which amounts to discard the lower significant bits in each channel. When saving to PNG, you will still be saving 8 bits per channel (unless you use a palette), but even then you will get an appreciable reduction in size, because of the PNG compression.
A quick example: original:
after a simple posterize with 32 levels (equivalent to a RGB555) applied with XnView
The size goes from 89KB to 47KB, with a small quality loss.
In case of synthetic images with gradients, the quality loss could be much more noticiable (banding).
I received this answer from the creator of texture packer:
you can do it from command line - see
http://www.texturepacker.com/uncategorized/batch-converting-images-to-pvr-or-pvr-ccz/
Just adjust the opt and set output to .png instead of pvr.ccz
Make sure that you do not overwrite your source images.
According to Wikipedia, which is always right, the only 16-bit PNG is a greyscale PNG. http://en.wikipedia.org/wiki/Portable_Network_Graphics
If you just add your 32-bit (alpha) or 24-bit (no alpha) PNG to your project as normal, and then set the texture format in Cocos2D, all should be fine. The code for that is:
[CCTexture2D setDefaultAlphaPixelFormat:kCCTexture2DPixelFormat_RGB565];

how to calculate how much data can be embeded into an image

I want to know how much data can be embedded into an image of different sizes.
For example in 30kb image file how much data can be stored without distortion of the image.
it depends on the image type , algoridum , if i take a example as a 24bitmap image to store ASCII character
To store a one ASCII Character = Number of Pixels / 8 (one ASCII = 8bits )
It depends on two points:
How much bits per pixel in your image.
How much bits you will embed in one pixel .
O.K lets suppose that your color model is RGB and each pixel = 8*3 bits (one byte for each color), and you want embed 3 bits in one pixel.
data that can be embedded into an image = (number of pixels * 3) bits
If you would use the LSB to hide your information this would give 30000Bits of available space to use. 3750 bytes.
As the LSB represents 1 or 0 into a byte that gets values from 0-256 this gives you in the worst case scenario that you are going to modify all the LSBs distortion of 1/256 that equals 0,4%.
In the statistical average scenario you would get 0,2% distortion.
So depends on which bit of the byte you are going to change.

Comparing two images - Detect egg in a nest

I have a webcam directly over a chicken nest. This camera takes images and uploads them to a folder on a server. I'd like to detect if an egg has been laid from this image.
I'm thinking the best method would be to compare the contrast as the egg will be much more reflective than the straw nest. (The camera has Infrared so the image is partly grey scale)
I'd like to do this in .NET if possible.
Try to resize your image to a smaller size, maybe 10 x 10 pixel. This averages out any small disturbing details.
Const N As Integer = 10
Dim newImage As New Bitmap(N, N)
Dim fromCamera As Image = Nothing ' Get image from camera here
Using gr As Graphics = Graphics.FromImage(newImage)
gr.SmoothingMode = SmoothingMode.HighSpeed
gr.InterpolationMode = InterpolationMode.Bilinear
gr.PixelOffsetMode = PixelOffsetMode.HighSpeed
gr.DrawImage(fromCamera, New Rectangle(0, 0, N, N))
End Using
Note: you do not need a high quality, but you need a good averaging. Maybe you will have to test different quality settings.
Since now, a pixel covers a large area of your original image, a bright pixel is very likely part of an egg. It might also be a good idea to compare the brightness of the brightest pixel to the average image brightness, since that would reduce problems due to global illumination changes.
EDIT (in response to comment):
Your code is well structured and makes sense. Here some thoughts:
Calculate the gray value from the color value with:
Dim grayValue = c.R * 0.3 + c.G * 0.59 + c.B * 0.11
... instead of comparing the three color components separately. The different weights are due to the fact, that we perceive green stronger than red and red stronger than blue. Again, we do not want a beautiful thumbnail we want a good contrast. Therefore, you might want to do some experiments here as well. May be it is sufficient to use only the red component. Dependent on lighting conditions one color component might yield a better contrast than others. I would recommend, to make the gray conversion part of the thumbnail creation and to write the thumbnails to a file or to the screen. This would allow you to play with the different settings (size of the thumbnail, resizing parameters, color to gray conversion, etc.) and to compare the (intermediate) results visually. Creating a bitmap (bmp) with the (end-)result is a very good idea.
The Using statement does the Dispose() for you. It does it even if an exception should occur before End Using (There is a hidden Try Finally involved).

Get resolution of bitmap from file vb .net

I have a filename that leads to a picture. It is not an embedded resource. My bitmap object always tells me the resolution is 96x96 no matter what, how can I get the actual resolution. Thanks
96 sounds pretty accurate to me. I think you're confusing pixel dimension with resolution.
Resolution is the number of dots per inch* (DPI), and 96 is a common number for graphics targeted at monitor display.
As mentioned, the Height and Width properties are probably what you're looking for.
*Note: technically, I should have said PPI, as dots and pixels aren't necessarily interchangeable.
The methods you are looking for are those :
Dim bmp as Bitmap = new Bitmap(IMAGE_NAME_LOCATION)
bmp.HorizontalResolution ' --> Horizontal PPI (points per inch)
bmp.VerticalResolution ' --> Vertical PPI
bmp.SetResolution ' --> Define both Horizontal and Vertical PPI
try this (its in C#):
Bitmap b = new Bitmap(IMAGE_NAME_LOCATION);
Size s = b.Size;
s.Height;
s.Width;
Height & width are in pixels. The Height & width are the original pic's size.
If you're loading a file using Bitmap.FromFile("C:\whatever.jpg"), and the resulting Bitmap has a .Width of 96 and a .Height of 96, then that is the actual resolution of that image.
If what you're doing is loading a file into a PictureBox control by setting its Image property in the designer (and browsing for the file), then it may be that your PictureBox just happens to be 96x96 and the SizeMode is set to Stretch, which would make any file you load appear to be 96x96.
It's simple:
Bitmaps don't contain resolution information. They are only an ordered collection of pixels. They're device-independent. You can show the same bitmap at different resolutions (pixels per inch) on two different devices.
The fact that your bitmap object has a resolution property is misleading.