bitmap file size vs byte[] size - c#

bmp.ToByteArray(ImageFormat.Bmp).Length 3145782 int
but file system shows as 2,25 MB (2.359.350 bytes) and Size on disk 2,25 MB (2.363.392 bytes)
Why there is difference and how can I determine correct size of bitmap in byte[]
form?
string appPath = Application.StartupPath;
var bmp = new Bitmap(Image.FromFile(appPath + "\\Images\\Penguins.bmp"));
public static byte[] ToByteArray(this Image image, ImageFormat format)
{
using (MemoryStream ms = new MemoryStream())
{
image.Save(ms, format);
return ms.ToArray();
}
}
Windows 7 / NTFS

I suspect that's because the file on disk doesn't contain an alpha channel, but in memory it does. On disk it's 3 bytes per pixel, but in memory it uses 4.
2359350*4/3 is 3145800 which is only slightly more than the value you see. I expect the slight difference is because on disk there is a header, but that's not actually part of the image.

Related

How to compress bitmap to smaller size in C#?

My bitmap is too large for uploading to the printer. I am going to compress it to smaller size so that less data will be transmit over the printer. But I don't want reduce the length and width of the bitmap. I have done some research but all of them require a stream especially as following
bitmap.compress(Bitmap.Format.jpeg,50,outputStream);
Why do I need a stream to store the file? How can I skip that and get the compressed bitmap that I want? I have tried
originalBitmap = Bitmap.decodeByteArray(imageByteData);
//Line below not working and got error
compressedBitmap = Bitmap.compress(Bitmap.Format.jpeg,50,outputStream);
In the outputStream which is my Download folder, I did see the compressed image, but how can I access the compressed image again? Unfortunately, the compress method is not that straight forward. My question is how can I compress a bitmap and use the compressed bitmap in another action? Thank you.
You can compress it to an in-memory stream:
//Compress to a stream in memory
byte[] compressedData = null;
using(var stream = new MemoryStream())
{
bitmap.Compress(Bitmap.Format.Jpeg, 50, stream);
compressedData = stream.ToArray();
}
//load compressed bitmap from memory
using(var stream = new MemoryStream(compressedData))
{
var compressedBitmap = BitmapFactory.DecodeStream(stream);
}

Storing BMP in icon file

I have a program to combine graphics files in an icon. Sizes include 16,24,32,48,256 32bit. These use PNG and works. I have correct header and directory/index record list.
However, for 8 bit I am using BMP with the first 14 bytes of the header of a BMP stripped off. This part of the icon file does not work. Having looked at a MS icon they have BMP stored again with the 14 byte header removed. Looking at their BMP data they have the second header as I do but for 16x16 the second header (BITMAPINFOHEADER) says 16x32. The BMP seams to be twice the width. Why? Is the image twice the width with a bit mask or something?
Here's my code: (Note image is 32x32 bitmap 32bit when passed.)
using (Bitmap imageAsBitmap = new Bitmap(image))
{
int colorCount = 0;
using (Bitmap bitmap = imageAsBitmap.ColourReduction256(out colorCount))
{
byte[] imageBytes = new byte[] { };
using (MemoryStream ms = new MemoryStream())
{
bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
imageBytes = ms.ToArray();
}
byte[] data = new byte[] { };
Array.Resize(ref data, imageBytes.Length - 14);
Array.Copy(imageBytes, 14, data, 0, data.Length);
enteries.Add(new IconEntry(data, image.Width, image.Height, 8));
}
}
Yes, you are right:
Images with less than 32 bits of color depth follow a particular
format: the image is encoded as a single image consisting of a color
mask (the "XOR mask") together with an opacity mask (the "AND mask")[..]
What results in:
[..] the masks must each be of the same dimensions, and the height
specified in the BMP header must be exactly twice the height specified
in the ICONDIRENTRY structure
Take a look here: https://en.wikipedia.org/wiki/ICO_(file_format)

how do i know my byte array containing blank .tif file or not

i have a application where i need to check my scanner generates blank tif file or not.
here i share my example code
private void button1_Click(object sender, EventArgs e)
{
string path2 = #"F:\3333.tif";
string path = #"F:\Document Scanned # 1-blank.tif";
System.Drawing.Image img = System.Drawing.Image.FromFile(path);
byte[] bytes;
using (MemoryStream ms = new MemoryStream())
{
img.Save(ms, System.Drawing.Imaging.ImageFormat.Tiff);
bytes = ms.ToArray();
}
System.Drawing.Image img2 = System.Drawing.Image.FromFile(path2);
byte[] bytes2;
using (MemoryStream ms3 = new MemoryStream())
{
img2.Save(ms3, System.Drawing.Imaging.ImageFormat.Tiff);
bytes2 = ms3.ToArray();
}
bool t = false;
t = bytes.SequenceEqual(bytes2);
}
Note: Blank tif image meance white page .
In above bool t always returns true why ? i used two diff images solved
Essentially, you are comparing the bytes of two TIF files (with the indirection of using Image). This can fail for various reasons:
Dimension: If the two images do not have the exact same height and width, the byte sequences will -of course- be different even if both are completely white.
Metadata: As far as I know, the TIF format contains various metadata. Therefore, two files may be different even if they have the same pixels. I would recommend manually checking all pixel values (e.g. Bitmap.GetPixel) and comparing them to white (Color.FromArgb(255,255,255,255)).
Noise: Are you sure that a blank file is always pure white (255,255,255)? Maybe some random pixels have slightly different values such as (255,254,255)...

Base64Encoded bitmap - convert to bitmap manually

I know I can use
string base64Encoded = ...;
byte[] byteArray = Convert.FromBase64String(this.base64Encoded); // array size [31591]
var memoryStream = new MemoryStream(byteArray);
var bitmap = new Bitmap(memoryStream);
//byte[,] im = new byte[a.Width*a.Height,3];
// array size [891998, 3] - why this array is 90 times bigger?
but I want to do it manually.
What I really need is to know how from byteArray I can create 3dim pixel array [bitmap.width * bitmap.hight, 3 {Red,Green,Blue}]
1- size of byteArray is different from size of bitmap since bitmap is actually an uncompressed 24 bit image without a header, but byteArray is a compressed (RLE most likely) bitmap file.
2- you can use libbmp or another image processing library to load and manipulate pixels. These libraries are much better at handling that kind of stuff.
3- most bitmaps are compressed using RLE compression and bitmap is a very simple format. You can actually write a bitmap reader to read it to a byte array intead of Bitmap object.

C# Image: To preserve image's checksum

I have the following codes to convert an image(bitmap) to byte array:
public byte[] ConvertImageToByteArray(Image imageToConvert, ImageFormat formatOfImage)
{
byte[] Ret;
try
{
using (MemoryStream ms = new MemoryStream())
{
imageToConvert.Save(ms, formatOfImage);
Ret = ms.ToArray();
}
}
catch (Exception)
{
throw;
}
return Ret;
}
and Convert byte array back to image(bitmap):
public Bitmap ConvertByteArrayToImage(byte[] myByteArray)
{
Image newImage;
using (MemoryStream ms = new MemoryStream(myByteArray, 0, myByteArray.Length))
{
ms.Write(myByteArray, 0, myByteArray.Length);
newImage = Image.FromStream(ms, true);
}
return newImage;
}
Here's my Main Program:
byte[] test = ConvertImageToByteArray(Image.FromFile("oldImage.bmp"), ImageFormat.Bmp);
Bitmap bmp = ConvertByteArrayToImage(test);
bmp.Save("newImage.bmp");
But when I compare both of the image files(old & new bitmap images), their checksum appeared to be different. Any reason for that happening? How to fix it to maintain its integrity?
Basically, there are many ways an identical image can be encoded in a BMP file. If I try your example on a random image I found, I see the .NET Bitmap class saves the file without filling the biSizeImage field in the BITMAPINFOHEADER structure in the BMP header (but the original image produced by IrfanView has it filled), which is a completely correct and documented possibility. (“This may be set to zero for BI_RGB bitmaps.”)
And this is definitely not the only variable thing in the BMP format. For instance, there are multiple possible orderings of pixel data in the image (top-to-bottom, bottom-to-top), specified in the header. (“If biHeight is positive, the bitmap is a bottom-up DIB and its origin is the lower-left corner. If biHeight is negative, the bitmap is a top-down DIB and its origin is the upper-left corner.”)
So, if you receive any BMP file from a source not under your control and really need to produce an image using exactly the same BMP variant, you have a lot work to do, and I don’t think you could use the standard .NET helper classes for that.
See also this question: Save bitmap to file has zero in image size field
After chatting a bit, you solution comes down to reading and writing bytes, take the image object out the equation and just deal with the raw bytes.
To read the file:
MemoryStream ms = new MemoryStream(File.ReadAllBytes("filename"));
To write the file:
File.WriteAllBytes("outputfile", ms.ToArray());

Categories

Resources