PDA

View Full Version : QImage and 4 bits per pixel (bpp) implementation



bob2oneil
24th February 2014, 23:41
I need to generate images files from a pixel map, with file size and browser decoding being the premium at a rate of 20 frames per second. I am currently using a monochromatic approach to generate the smallest file size, but really need more color information, and was looking to change to either 2 bits per pixel to support 4 colors, or 4 bits per pixel implementations to support 8 colors in the color table. Qt supports monochromatic file generation at 1 bpp using format "Format_mono", but then jumps to 8 bits per pixel via "Format_indexed8", providing no format enumeration for 2 bpp or 4 bpp. This type of indexed encoding is theoretically possible, and various file formats including BMP and GIF are supposed to support 2 and 4 bpp. However, I can get neither QImage nor something like Photoshop to generate indexed images with a color table that has at least 4 colors as anything but 8 bpp.

Does this suggest that 4 bpp file formats have gone out of style and are perhaps not support for rendering in most common browsers. It seems that perhaps Qt had this support sometime in the distant past. Is there a way to get QImage to save content into either 2 bpp or 4 bpp formats?

Scorp2us
25th February 2014, 17:06
What?

It sounds like you are going video, you might want to use a YUV format. Which is 8-8-8 but UV are half-sampled. So the data size is x*y+2(x/2*y/2), (ig. 640x480 = 640x480+ 2(320x200) = 307200 + 2(64000) = 435,200 bytes, vs 921,600 for 24bit color.
If sticking with QImage, there is QImage::Format_RGB444 and QImage::Format_ARGB4444_Premultiplied

One trick we do in the embedded world is only store the MSB, and left shift on read out. You don't really notice a loss of 2 bits (0xFF & 0xFC then -xFC >> 2; store and << 2 on read.

bob2oneil
25th February 2014, 17:41
Thanks for the input. There are two characteristics that I am dealing with for this problem. I need to have a file generated that is quickly decoded in the browser, and I want to reduce the network loading. The images that need to be generated on the fly are 3 displays of up to 320 x 240 pixels, but I might use something like CSS Sprites to composite a single image of 320x(240*3) pixels to allow a single HTTP request and response. In my profiling with various browsers, I have discovered that browsers typically take several milliseconds longer to decode a compressed image file format (e.g. PNG or GIF) relative to an uncompressed format (e.g. BMP) on the Windows platform, which is the target client platform for the browser. We are willing to give up some network bandwidth to allow for support for a lower powered client workstation, using uncompressed files with greater network footprints.

Whatever image file format that is generated, it has to be quickly decoded by the common browsers (Firefox, Chrome, IE). The formats you described are 16 bpp, I was looking to minimize this as much as possible. I have an implementation in place now that uses monochromatic at 1 bpp, but I am having to draw certain content on the browser via <canvas> APIs since only two colors are supported by the 1 bpp file format. If I could get say 2 bpp, or 4 bpp, while the file size would be either 2/4 greater in size relative to 1 bpp, I would not have to perform the drawing in <canvas> in the browser (which take approximately 100 microseconds). Any of the 8 bpp formats would work, but 8 times the network loading is undesired. Those are my goals.

Scorp2us
25th February 2014, 19:04
Well PNG has heavy compression. So much so, that when I do it, I do it in another thread in Qt. If you can use a run-length encoded BMP yo may be able to compress it at near zero compression/decompression cost.

You either spend your budget on bandwidth or CPU. My recommendation is spend it on the CPU, on the client, where it is distributed, because the bandwidth cannot be.

Other things you can do is scale on the client. If you use a good scaling algorithm, like bi-linear or better you can scale without noticeable degradation.

If you are dealing with a HTTP 1.0 server then the sprite trick makes sense, but if you are dealing with 1.1, it does not. You're also putting more processing on the client.

I wonder what kind of image is ok at 1,2 or 4 BPP in today's world?

bob2oneil
25th February 2014, 19:24
Thanks for the input, some good insight. PNG uses zlib compression under the covers, do not know how that corresponds to the compression in GIF in terms of performance. I will look into RLE BMP to see what the client side cost is. In my configuration, I can assume a 100BaseT network, but it will be at various customer sites, so I can not upgrade them. Same thing with the client side processing, while at best we can specify a minimum platform, to get the broadest support, we want to be able to support as many older PC's as possible. The server side is the s/w that I will write and I have a Qt based web server that is HTTP 1.1 complaint that executes on an embedded Linux platform and supports real time Linux threads and CPU shielding for performance (CPU isolation and pinning).

The current image is monochromatic, 175 x 175, and at that resolution it looks fine. It is eye patterns/diagrams for communications systems. But I also need to add a text signal strength and a horizontal grid in different colors, hence the need for 4 colors, black background, primary color, grid color, signal strength text color, which is why 2 bpp would be sufficient while minimizing network bandwidth.

From what I can tell, 2 bpp BMP, while theoretical, I know of no manner to produce them at this moment using something like Qt, perhaps the Windows SDK. I do not know if 2 bpp and 4 bpp is considered viable anymore, certainly they are not very popular. There seems to be some historic support for these formats in Qt, but no longer, and I don't know what that means in terms of industry support and best practices.

Scorp2us
25th February 2014, 19:39
If you want to ass text signal strength and horizontal grid to the images in color, I would do that on the client in JS. Those thigns are very easily drawn and do not need to be part of the image data.

If you are doing diagrams, the BMP RLE should be very effective.

bob2oneil
25th February 2014, 20:22
Certainly is a viable design prospect. In my testing on a reasonable platform, a single horizontal grid line takes 0.1ms to draw, and if the line is dashed, it blossoms up to 7 ms (must consider it to be a bunch of separate line segments). I have not profilied what it takes to draw the text. By contrast, it take about 1 ms for the HTTP request/response cycle with the updated image data to transpire on a 100 Mbps network. The question then comes down to the benefit in time of having this composited into the file itself, making it bigger, or doing the drawing on the client side, where the resource is not constrained and can therefore vary on a slow platform. I also need to create some bar graphs in different colors with an update rate of 10 Hz, was pondering bringing this content into the larger eye pattern diagram, or draw these client side as well. Profiling will resolve the best approach.