Click here to Skip to main content
16,018,318 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
[Solved - Kinda] I've created 2 images, 1 is 48bpp and the other is 64bpp. Reading these images with ffmpeg, ffmpeg output is.

Here is output from the 48bpp png file.
Stream #0:0: Video: png, rgb48be(pc, gbr/bt709/iec61966-2-1), 1920x1200 [SAR 3779:3779 DAR 8:5], 25 fps, 25 tbr, 25 tbn

Here is output from the 64bpp png file.
Stream #0:0: Video: png, rgba64be(pc, gbr/bt709/iec61966-2-1), 1027x742 [SAR 3779:3779 DAR 1027:742], 25 fps, 25 tbr, 25 tbn

When I load the png files with the code below, I always recieve output that the PixelFormat is Format32bppArgb.

This is the code used to load the images.
C#
using Stream stream = File.OpenRead(imagePath);
Bitmap bitmap = (Bitmap)Image.FromStream(stream);
Console.WriteLine(bitmap.PixelFormat);


Why are the images not not being read correctly?

Update : The images were created using the bitmap class, If the bitmap class saved these images, shouldn't it be able to read the images that it created?

I've created a work-around (less than ideal because it produces larger files since it stores the actual pixel Data). First, we write the Width, Height and PixelFormat(as an int value). I call this the header(12 bytes) then the pixelData. When we read this byte array back we read the header info then seperate the header from the pixelData. Below is the two methods to read and write the image back and forth.

C#
public static void WriteImageDataToFile(Bitmap bitmap, string filePath)
{
    int width = bitmap.Width;
    int height = bitmap.Height;
    PixelFormat pixelFormat = bitmap.PixelFormat;
    ImageLockMode lockMode = ImageLockMode.ReadOnly;
    Rectangle rect = new(0, 0, width, height);
    BitmapData bitmapData = bitmap.LockBits(rect, lockMode, pixelFormat);
    int pixelDataSize = bitmapData.Stride * bitmapData.Height;
    byte[] pixelData = new byte[pixelDataSize];
    Marshal.Copy(bitmapData.Scan0, pixelData, 0, pixelDataSize);
    bitmap.UnlockBits(bitmapData);
    using Stream stream = File.Create(filePath);
    stream.Write(BitConverter.GetBytes(width));
    stream.Write(BitConverter.GetBytes(height));
    stream.Write(BitConverter.GetBytes((int)pixelFormat));
    stream.Write(pixelData);            
}


C#
public static Bitmap ReadImageDataFromFile(string filePath)
{
    int headerSize = 12;
    byte[] rawData = File.ReadAllBytes(filePath);
    int pixelSize = rawData.Length - headerSize;
    int width = BitConverter.ToInt32(rawData, 0);
    int height = BitConverter.ToInt32(rawData, 4);
    int pixelFormat = BitConverter.ToInt32(rawData, 8);
    byte[] pixelData = new byte[pixelSize];
    Array.Copy(rawData, headerSize, pixelData, 0, pixelSize);
    Bitmap bitmap = new(width, height, (PixelFormat)pixelFormat);
    Rectangle rect = new(0, 0, bitmap.Width, bitmap.Height);
    ImageLockMode lockMode = ImageLockMode.WriteOnly;
    BitmapData bitmapData = bitmap.LockBits(rect, lockMode, (PixelFormat)pixelFormat);
    Marshal.Copy(rawData, 0, bitmapData.Scan0, pixelSize);
    bitmap.UnlockBits(bitmapData);
    return bitmap;
}


What I have tried:

Have tried loading the images from stream and from file.
Posted
Updated 30-Aug-24 9:02am
v3
Comments
Peter_in_2780 30-Aug-24 0:50am    
My guess is that the Bitmap class forces 32bpp.
charles henington 30-Aug-24 4:25am    
I've successfully loaded other bitmaps that were in PixelFormats other than 32bpp so I would assume not

1 solution

From the PixelFormat documentation, found here[^].
Quote:
PixelFormat48bppRGB, PixelFormat64bppARGB, and PixelFormat64bppPARGB use 16 bits per color component (channel). GDI+ version 1.0 and 1.1 can read 16-bits-per-channel images, but such images are converted to an 8-bits-per-channel format for processing, displaying, and saving. Each 16-bit color channel can hold a value in the range 0 through 2^13.
 
Share this answer
 
Comments
charles henington 30-Aug-24 4:15am    
The 48bpp and 64bpp images that were created, were created using the bitmap class. If they were created using the bitmap class, shouldn't it be able to read back the images it created?
I've updated the question to include this.
Dave Kreskowiak 31-Aug-24 10:10am    
You're not getting it. Internally, in memory, every image is loaded and represented as a 32bpp ARGB image. It is converted to that when loaded from disk and can be converted to any other format when written.
charles henington 31-Aug-24 14:58pm    
It reads all other image formats appropriately, indexed,32bpp, 24bpp and 16bpp. It's only the 48bpp and 64bpp that it doesn't load correctly
Dave Kreskowiak 31-Aug-24 15:27pm    
And those are 16-bits per pixel images. Again, they are converted to 8-bpp when loaded JUST LIKE THE DOCUMENTATION SAYS.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900