views:

197

answers:

6

I am creating screenshots under Windows and using the LockBits function from GDI+ to extract the pixel data, which will then be written to a file.

To maximise performance I am also:

  • Using the same PixelFormat as the source bitmap, to avoid format conversion
  • Using the ImageLockModeUserInputBuf flag to extract the pixel data into a pre-allocated buffer
  • This pre-allocated buffer (pointed to by BitmapData::Scan0) is part of a memory-mapped file (to avoid copying the pixel data again.)

I will also be writing the code that reads the file, so I can use (or invent) any format I wish. However I would prefer to use a well-known format that existing programs (ideally web browsers) are able to read, because that means I can visually confirm that the images are correct before writing the code for the other program (that reads the image.)

I have implemented this successfully for the PixelFormat32bppRGB format, which matches the format of a 32bpp BMP file, so if I extract the pixel data directly into the memory-mapped BMP file and prefix it with a BMP header I get a valid BMP image file that can be opened in Paint and most browsers.

Unfortunately one of the machines I am testing on returns pixels in PixelFormat64bppPARGB format (presumably this is influenced by the video adapter driver) and there is no corresponding BMP pixel format for this.

Converting to a 16, 24 or 32bpp BMP format slows the program down considerably (as well as being lossy) so I am looking for a file format that can use this pixel format without conversion, so I can extract directly into the memory-mapped file as I have done with the 32bpp format.

What raster image file formats support 48bpp (BGR order, little-endian) and/or 64bpp (BGRA order, little-endian)?


Edit

I have ruled out these formats so far:

  • BMP: Depth limited to <=32bpp (would be a perfect match otherwise.)
  • PNG: Sample order can only be RGBA.
  • TIFF: Sample order can only be RGBA.

Possible partial solutions:

  • OpenEXR: 48bpp only. Sample order is alphabetical by channel name; BGR fits but BGRA does not.
A: 

PNG? 48 bit + alpha = 64 bit

for the compression, "It is possible to store uncompressed data by using only uncompressed deflate blocks"

Marco Mariani
I don't think PNG is suitable, because it uses RGBA order (AFAICT this is not configurable) and Windows uses BGRA order.
finnw
+1  A: 

Which bitmap color depths are supported depends on your windows version which means gdi+ version, not the graphics adapter.

You can also use TIFF or PNG (png has lots of parameters, I think you also can tell it to do uncompressed). You can also consider the RAW format.

The imaging library imagemagick which has an .net wrapper includes supports hundreds of image formats, no matter which format you decide to sue at the end, Iam sure it has support for it :)

codymanix
Which pixel formats are *supported* is irrelevant. One is chosen automatically when the bitmap is created (the contents of the window have already been rendered so I assume a driver function is called to extract it from the adapter's frame buffer?) My goal is to avoid conversion and that means using the native pixel format of the bitmap. +1 for mentioning TIFF.
finnw
It seems I cannot use TIFF after all for the same reason I cannot use PNG - The order of components (RGBA) is incompatible with that used by GDI+ (BGRA)
finnw
Why can't you change the order of the components?
codymanix
I can, but that adds an extra processing step. GDI+'s pixel format conversion already takes up too much CPU time. If I tried to implement my own it would likely be slower.
finnw
+2  A: 

Do you really want to implement and carefully test separate readers for each of the 14 different PixelFormats? I know that so far you've only encountered 2 of them, but I guarantee there are video cards out there with almost all of the other 12. As one easy example, set your monitor to 256 colors...

You say that you want to maximize performance, but writing the bitmap to a file on disk, even with memory mapping, is going to take more time on average than the time it'd take to just convert it to a device-independent bitmap in memory. Plus if you convert the 64-bit bitmap to a 32-bit bitmap, the resulting file will take half as long to write, so it could actually be faster.

dmazzoni
Unfortunately yes. If anything, an unusual pixel format like 8bpp indexed is *more* performance-critical, because the machine my program is running on is likely to be older and slower. I hope to avoid the write-to-disk completely (by using `FILE_ATTRIBUTE_TEMPORARY`), because the image will normally be read within 2 seconds after creating it, then discarded (whether or not it was read.)
finnw
A: 

Is the reading of the file just as performance critical as the writing? If you can fill a buffer easily, and then read at your convenience, this should be a cakewalk. Just have a 1byte header representing the data-format and then the raw data you got.

CERIQ
No, reading is not performance critical, but I would like to use a format for which there are already well-known programs that can view images in that format.
finnw
+2  A: 

It seems that the only reason you need a standard format is for display/testing purposes. So roll your own format, but convert to PNG or TIFF for display. And then move on...life is short.

ergosys
This is similar to what I am doing. I've rolled my own format (a variant of BMP) and written a viewer app which can read this format as well as standard BMP and PNG.
finnw
+1  A: 

When the desktop and web file formats let you down, think of reaching for the big guns: FITS (flexible image transport system) or HDF5, even DICOM perhaps.

High Performance Mark