Results 1 to 6 of 6

Thread: 10 - 12 bit grayscale QImage format display

  1. #1
    Join Date
    Jan 2020
    Posts
    3
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Question 10 - 12 bit grayscale QImage format display

    Greetings,

    Some scientific camera capture grayscale images at 10, 12 and 16 bits in addition to the common 8 bit format.
    Such formats are little-endian and encode each pixels into 2 Bytes - the unused bits are set to zero.
    Of course the 8bit grayscale pixel only requires 1 Byte.

    The problem is that even with the newly introduced Grayscale 16 QImage format (>=Qt5.14), 10 and 12 bits per pixels grayscale images can't be properly displayed within QPainter without first processing the whole image.

    The 8bit image is displayed just fine:
    Qt Code:
    1. painter->drawImage(
    2. transformedRect,
    3. (const unsigned char*) _image.memory,
    4. _image.width,
    5. _image.height,
    6. QImage::Format_Grayscale8));
    To copy to clipboard, switch view to plain text mode 

    Even the 16bit shows no problems, decoding the char memory 2 Bytes per pixel:
    Qt Code:
    1. painter->drawImage(
    2. transformedRect,
    3. (const unsigned char*) _image.memory,
    4. _image.width,
    5. _image.height,
    6. QImage::Format_Grayscale16));
    To copy to clipboard, switch view to plain text mode 

    However I have no solution for what is in between. As expected, the Grayscale16 format loads the QImage just fine, but since the expected maximum brightness value of 2^16 is much higher than 2^12 and more so than 2^10, the displayed image is very dark.
    Working on the image pixels is not an option because it is more time consuming than the Grayscale16 format.

    The QImage pixelColor method clearly shows how this decoding is done (but it is highly unlikely that this is the exact method used by QPainter as it is not optimized at all):
    Qt Code:
    1. QColor QImage::pixelColor(int x, int y) const
    2. {
    3. if (!d || x < 0 || x >= d->width || y < 0 || y >= height()) {
    4. qWarning("QImage::pixelColor: coordinate (%d,%d) out of range", x, y);
    5. return QColor();
    6. }
    7. QRgba64 c;
    8. const uchar * s = constScanLine(y);
    9. switch (d->format) {
    10. case Format_BGR30:
    11. case Format_A2BGR30_Premultiplied:
    12. c = qConvertA2rgb30ToRgb64<PixelOrderBGR>(reinterpret_cast<const quint32 *>(s)[x]);
    13. break;
    14. case Format_RGB30:
    15. case Format_A2RGB30_Premultiplied:
    16. c = qConvertA2rgb30ToRgb64<PixelOrderRGB>(reinterpret_cast<const quint32 *>(s)[x]);
    17. break;
    18. case Format_RGBX64:
    19. case Format_RGBA64:
    20. case Format_RGBA64_Premultiplied:
    21. c = reinterpret_cast<const QRgba64 *>(s)[x];
    22. break;
    23. case Format_Grayscale16: {
    24. quint16 v = reinterpret_cast<const quint16 *>(s)[x];
    25. return QColor(qRgba64(v, v, v, 0xffff));
    26. }
    27. default:
    28. c = QRgba64::fromArgb32(pixel(x, y));
    29. break;
    30. }
    31. // QColor is always unpremultiplied
    32. if (hasAlphaChannel() && qPixelLayouts[d->format].premultiplied)
    33. c = c.unpremultiplied();
    34. return QColor(c);
    35. }
    To copy to clipboard, switch view to plain text mode 

    It's just how data is reinterpreted.
    However, I don't really want to tamper with the built-in Qt classes.

    The other idea I had is to alter the on-screen pixel with some sort of QPainter color-space transformation. I have tried composition to enhance brightness and contrast but failed. It was acceptable computationally-wise though, so maybe it is the right path to follow.

    I feel like I'm missing something obvious since 10 and 12bits images are commonly used in medical appliances.
    What should I do to correctly display such images at the same speed as 16bits images?

    Thanks

  2. #2
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: 10 - 12 bit grayscale QImage format display

    Are these static images or a video stream?

    If they are static, can't you simply shift each 16-bit word by 4 or 6 bits before constructing the QImage? You will still never get to full brightness unless you also set the low-order bits to 1, but then in that case you'd never get full black either. Another option would be to multiply every word by the ratio of 16 / n, where n is 10 or 12. This would expand the word values to cover the full range and you would get both true white and black.

    If you really need speed, this transformation is something you could do in parallel, either through multiple threads that each work on part of the image or using a CUDA transformation on a video card to do the entire array in one operation.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  3. #3
    Join Date
    Jan 2020
    Posts
    3
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: 10 - 12 bit grayscale QImage format display

    d_stranz,

    The camera transfers the captured image into the allocated read-only image memory.
    Since I didn't implement any buffering technique, the new image simply overwrites the old one. Nonetheless, the computing part of the program reads the image fast enough for it not to be a problem.
    The GUI process lives in another thread and displays the image asynchronously. Obviously this leads to flickering (the memory is constantly getting updated) but this does not represent a problem.

    Rescaling the brightness dynamic range of the image into the right one was the first thing I tried. This solved the problem but the computational expense was unjustifiable, especially considering that QPainter manages to display the 16bit format much faster.

    I also thought of bit shifting the memory but this still requires to touch the image or copying it, unless I can instruct QImage to parse the image memory in a different way.

    Associating a different QColorSpace to the QImage seems to have no effect in how QPainter shows the image.

    The question is: how to let QPainter display full-range grayscale 10 (or 12) bpp images without editing the image memory?


    Added after 9 minutes:


    I forgot to mention that I also tried other formats:

    - QImage::Format_RGB555 uniquely maps the 10bit grayscale into the full dynamic range of red and green components;
    - QImage::Format_RGB444 uniquely maps the 12bit grayscale into the full dynamic range of red, green and blue components.

    Even if such formats lead to unavoidable color banding, this definitely proves that Qt is perfectly capable to handle "uncommon" formats. Such formats are as fast as grayscale16.
    Last edited by moccij; 30th January 2020 at 11:27.

  4. #4
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: 10 - 12 bit grayscale QImage format display

    The question is: how to let QPainter display full-range grayscale 10 (or 12) bpp images without editing the image memory?
    Can't give you much advice here, since I have never had to deal with such problems. A QImage constructed via a pointer to a data buffer does not make a copy of the buffer, so there is no copy overhead.

    You could look into the Qt source code to see what is happening with the two RGB formats you have tried. That might give you some insight into how to map the images using greyscale alone.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  5. #5
    Join Date
    Jan 2006
    Location
    Sta. Eugènia de Berga (Vic - Barcelona - Spain)
    Posts
    869
    Thanks
    70
    Thanked 59 Times in 57 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: 10 - 12 bit grayscale QImage format display

    Hi,

    You could try VTK library. It supports 10 and 12 bit images and there is also a QVTKWidget.
    Òscar Llarch i Galán

  6. #6
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: 10 - 12 bit grayscale QImage format display

    You could try VTK library.
    Oh, but what a headache. VTK is as big as Qt and even harder to learn.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  7. The following user says thank you to d_stranz for this useful post:

    ^NyAw^ (1st February 2020)

Similar Threads

  1. const char* QImage Format?
    By grabalon in forum Newbie
    Replies: 2
    Last Post: 13th May 2010, 01:44
  2. QImage Non-Standard Format Probem
    By photo_tom in forum Qt Programming
    Replies: 3
    Last Post: 19th February 2010, 09:06
  3. QImage, get file format
    By greenvirag in forum Qt Programming
    Replies: 6
    Last Post: 29th December 2008, 14:13
  4. How to display 16 bit grayscale pictures?
    By reimer in forum Qt Programming
    Replies: 5
    Last Post: 20th August 2008, 20:55
  5. QImage Format Issue
    By vishal.chauhan in forum Qt Programming
    Replies: 7
    Last Post: 9th March 2007, 11:14

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.