Page 1 of 2 12 LastLast
Results 1 to 20 of 21

Thread: Problems working with 8bpp and 24bpp images

  1. #1
    Join Date
    Jan 2006
    Location
    Catalonia
    Posts
    266
    Thanks
    44
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Thumbs up Problems working with 8bpp and 24bpp images

    Hi all, I am programming a simple photo editor program in Qt4.1 with winXp. Well, one of the utilities of the editor is to paint with a given color a selected rectangular area of the image. The code to paint this area is as follows:

    Qt Code:
    1. void FotoEditorFotos::paintRect(const QColor &color, const QRect &rectAPintar)
    2. {
    3. int xMin = rectAPintar.x();
    4. int xMax = xMin + rectAPintar.width() - 1;
    5. int yMin = rectAPintar.y();
    6. int yMax = yMin + rectAPintar.height() - 1;
    7.  
    8. if ( !imatge.valid(xMin, yMin) || !imatge.valid(xMax, yMax)) return;
    9.  
    10. QRgb *pixelsLiniaFoto;
    11. QRgb valorColor = color.rgb();
    12.  
    13. for (int j = yMin; j <= yMax; j++)
    14. {
    15. pixelsLiniaFoto = ((QRgb *) imatge.scanLine(j)) + xMin;
    16.  
    17. for (int i = xMin; i <= xMax; i++)
    18. {
    19. *pixelsLiniaFoto = valorColor;
    20. pixelsLiniaFoto++;
    21. }
    22. }
    23.  
    24. update();
    25. }
    To copy to clipboard, switch view to plain text mode 

    The photo (imatge) is part of the class. Well the problem with the code above is that only works with images with 24 bits/pixel, but on the images with 8bpp it give me invalid results. The problem, I guess, is the cast to QRgb*. Anybody knows how to solve it? Thanks.
    Last edited by SkripT; 13th February 2006 at 14:33.

  2. #2
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,714
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: Problems working with 8bpp and 24bpp images

    you will have to add an if statment and see if the painting is for 24 or 8bpp.
    If the 24bpp then use the code you have, if its 8bpp, you have only 255 possible colors, so you will have to deal with that somewhere in your probgram, i.e limmiting the users to choose a color only from the 255 you use.

  3. #3
    Join Date
    Jan 2006
    Location
    Catalonia
    Posts
    266
    Thanks
    44
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Problems working with 8bpp and 24bpp images

    Quote Originally Posted by high_flyer
    ... if its 8bpp, you have only 255 possible colors, so you will have to deal with that somewhere in your probgram, i.e limmiting the users to choose a color only from the 255 you use.
    Exactly, the problem is that with the code that I have posted, although I pass it a valid color from the 255 (in my case a greyscale), it dosen't works

  4. #4
    Join Date
    Jan 2006
    Location
    Catalonia
    Posts
    266
    Thanks
    44
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Problems working with 8bpp and 24bpp images

    Anybody knows how could I modify the code above to support 8bpp images?

  5. #5
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,714
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: Problems working with 8bpp and 24bpp images

    Quote Originally Posted by SkripT
    Anybody knows how could I modify the code above to support 8bpp images?
    I answered you, do you expect code?
    You should think a bit your self...
    In a case of gray scale you should use qGray().

  6. #6
    Join Date
    Jan 2006
    Location
    Catalonia
    Posts
    266
    Thanks
    44
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Problems working with 8bpp and 24bpp images

    Quote Originally Posted by high_flyer
    ... if its 8bpp, you have only 255 possible colors, so you will have to deal with that somewhere in your probgram, i.e limmiting the users to choose a color only from the 255 you use.
    Sorry high flyer I didn't undestand what you meant. Thanks.

  7. #7
    Join Date
    Feb 2006
    Location
    Kirovohrad, Ukraine
    Posts
    72
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Problems working with 8bpp and 24bpp images

    Take a look at $QTDIR/src/gui/painting/qrgb.h.
    Qt Code:
    1. typedef unsigned int QRgb; // RGB triplet
    To copy to clipboard, switch view to plain text mode 
    That means sizeof(QRgb) == 4 on 32bit machines and 8 on 64bit ones. In case you have a 8bpp image, the sizeof(pixel) == 1 on any machine!!!
    You may try this...
    Qt Code:
    1. void FotoEditorFotos::paintRect(const QColor &color, const QRect &rectAPintar)
    2. {
    3. int xMin = rectAPintar.x();
    4. int xMax = xMin + rectAPintar.width() - 1;
    5. int yMin = rectAPintar.y();
    6. int yMax = yMin + rectAPintar.height() - 1;
    7.  
    8. if ( !imatge.valid(xMin, yMin) || !imatge.valid(xMax, yMax)) return;
    9.  
    10. QRgb valorColor = color.rgb();
    11.  
    12. quint8 *pixelsLiniaFoto;
    13. quint8 bpp8Color;
    14.  
    15. if (8 == imatge.bpp())
    16. bpp8Color = (imatge.isGrayScale()) ? qGray(valorColor) : getColorIndex(valorColor);
    17.  
    18. for (int j = yMin; j <= yMax; j++)
    19. {
    20. pixelsLiniaFoto = static_cast<quit8 *>(imatge.scanLine(j)) + xMin * (imatge.bpp() / 8);
    21. for (int i = xMin; i <= xMax; i++)
    22. {
    23. switch (imatge.bpp())
    24. {
    25. case 8:
    26. *(pixelsLiniaFoto++) = colorToSet;
    27. break;
    28. // Other BPP formats
    29. case 24:
    30. *(pixelsLiniaFoto++) = qRed(valorColor);
    31. *(pixelsLiniaFoto++) = qGreen(valorColor);
    32. *(pixelsLiniaFoto++) = qBlue(valorColor);
    33. break;
    34. }
    35. }
    36. }
    37.  
    38. update();
    39. }
    To copy to clipboard, switch view to plain text mode 
    Notes:
    There're some functions with obvious names. I guess you understand what they mean. The 8bpp image is a special case. Each byte describes either grayscale value or index in the palette. qGrey(const QRgb &) is a native QT function, whilst getIndexColor(const QRgb &) should be implemented on your own.

  8. #8
    Join Date
    Jan 2006
    Location
    Catalonia
    Posts
    266
    Thanks
    44
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Problems working with 8bpp and 24bpp images

    Thanks a lot Cesar, I think I will have to modify some lines but I think it will work

  9. #9
    Join Date
    Feb 2006
    Location
    Kirovohrad, Ukraine
    Posts
    72
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Wink Re: Problems working with 8bpp and 24bpp images

    You're always welcome, SkripT Feel free to ask anything. I've got some ideas on how to approximate any opaque QColor to index of a given palette.

  10. #10
    Join Date
    Jan 2006
    Location
    Catalonia
    Posts
    266
    Thanks
    44
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Problems working with 8bpp and 24bpp images

    Hi. First, I post the code that finally I have implemented using the code by Cesar. After I comment a problem with this code:

    Qt Code:
    1. void FotoEditorFotos::paintRect(const QColor &color, const QRect &rectAPintar)
    2. {
    3. int xMin = rectAPintar.x();
    4. int xMax = xMin + rectAPintar.width() - 1;
    5. int yMin = rectAPintar.y();
    6. int yMax = yMin + rectAPintar.height() - 1;
    7.  
    8. if (!imatge.valid(xMin, yMin) || !imatge.valid(xMax, yMax)) return;
    9.  
    10. QRgb colorRgb = color.rgba();
    11.  
    12. quint8 *pixelsLiniaFoto;
    13. quint8 color8, colorVermell, colorVerd, colorBlau, colorAlpha;
    14.  
    15. int bytesPixel = (imatge.depth()) >> 3;
    16.  
    17. if (bytesPixel == 1)
    18. color8 = (imatge.isGrayScale()) ? qGray(colorRgb) : obtenirIndexColor(valorColor);
    19. else
    20. {
    21. colorVermell = qRed(colorRgb);
    22. colorVerd = qGreen(colorRgb);
    23. colorBlau = qBlue(colorRgb);
    24. colorAlpha = qAlpha(colorRgb);
    25. }
    26.  
    27. for (int j = yMin; j <= yMax; j++)
    28. {
    29. pixelsLiniaFoto = static_cast<quint8 *>(imatge.scanLine(j)) + (xMin * bytesPixel);
    30.  
    31. for (int i = xMin; i <= xMax; i++)
    32. {
    33. switch (bytesPixel)
    34. {
    35. // Qt only manages 1, 8 or 32bpp
    36. case 1:
    37. *(pixelsLiniaFoto++) = color8;
    38. break;
    39.  
    40. case 4:
    41. *(pixelsLiniaFoto++) = colorVermell;
    42. *(pixelsLiniaFoto++) = colorVerd;
    43. *(pixelsLiniaFoto++) = colorBlau;
    44. *(pixelsLiniaFoto++) = colorAlpha;
    45. break;
    46. }
    47. }
    48. }
    49.  
    50. update();
    51. }
    To copy to clipboard, switch view to plain text mode 

    The problem is that with images with 32bpp it paints the area that I want but with an invalid color, different from the color that I pass to the function. Anoybody could explain where's the mistake?

  11. #11
    Join Date
    Feb 2006
    Location
    Kirovohrad, Ukraine
    Posts
    72
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Problems working with 8bpp and 24bpp images

    The only problem I could imagine is the following: your imatge object uses the different places for colours, rather then RGBA. I suggest you to temporarily the code to
    Qt Code:
    1. //[SKIP]
    2. case 4:
    3. *(pixelsLiniaFoto++) = 0xff;
    4. *(pixelsLiniaFoto++) = 0x00;
    5. *(pixelsLiniaFoto++) = 0x00;
    6. *(pixelsLiniaFoto++) = 0x00;
    7. //[SKIP]
    To copy to clipboard, switch view to plain text mode 
    and watch for the results. This way you will fill the QRect with the pure color. Let's pretend you have got blue QRect. Then your first line should be changed to
    Qt Code:
    1. *(pixelsLiniaFoto++) = colorBlau;
    To copy to clipboard, switch view to plain text mode 
    This way you can check, which colour is the first, which is the second and what is the place of alpha channel

  12. #12
    Join Date
    Jan 2006
    Location
    Catalonia
    Posts
    266
    Thanks
    44
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Problems working with 8bpp and 24bpp images

    Thanks again Cesar, it's really strange if I try to put the value 255 in one posistion and the rest at 0, the result is always the same. It paints the selection with the same gray color. I attach an image of the result.
    Attached Images Attached Images
    Last edited by SkripT; 14th February 2006 at 15:05.

  13. #13
    Join Date
    Feb 2006
    Location
    Kirovohrad, Ukraine
    Posts
    72
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Exclamation Re: Problems working with 8bpp and 24bpp images

    Is imatge an instance of QImage class? Then why are you trying to invent your own bicycle??? This is the modified version of your initial code:
    Qt Code:
    1. void FotoEditorFotos::paintRect(const QColor &color, const QRect &rectAPintar)
    2. {
    3. int xMin = rectAPintar.x();
    4. int xMax = xMin + rectAPintar.width() - 1;
    5. int yMin = rectAPintar.y();
    6. int yMax = yMin + rectAPintar.height() - 1;
    7.  
    8. if ( !imatge.valid(xMin, yMin) || !imatge.valid(xMax, yMax)) return;
    9.  
    10. QRgb valorColor = (QImage::Format_Indexed8 == imatge.format()) ? obtenirIndexColor(color) : color.rgb();
    11.  
    12. for (int y = yMin; y <= yMax; ++y)
    13. {
    14. for (int x = xMin; x <= xMax; ++x)
    15. {
    16. imatge.setPixel(x, y, valorColor);
    17. }
    18. }
    19.  
    20. update();
    21. }
    To copy to clipboard, switch view to plain text mode 
    Last edited by Cesar; 14th February 2006 at 15:49.

  14. #14
    Join Date
    Jan 2006
    Location
    Catalonia
    Posts
    266
    Thanks
    44
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Problems working with 8bpp and 24bpp images

    Hi, finally it works!!! . The order of the color of the pixels was the inverse. Here's the final code:

    Qt Code:
    1. void FotoEditorFotos::paintRect(const QColor &color, const QRect &rectAPintar)
    2. {
    3. int xMin = rectAPintar.x();
    4. int xMax = xMin + rectAPintar.width() - 1;
    5. int yMin = rectAPintar.y();
    6. int yMax = yMin + rectAPintar.height() - 1;
    7.  
    8. if (!imatge.valid(xMin, yMin) || !imatge.valid(xMax, yMax)) return;
    9.  
    10. QRgb colorRgb = color.rgba();
    11.  
    12. quint8 *pixelsLiniaFoto;
    13. quint8 color8 = 0;
    14. quint8 colorVermell = 0;
    15. quint8 colorVerd = 0;
    16. quint8 colorBlau = 0;
    17. quint8 colorAlpha = 0;
    18.  
    19. int bytesPixel = (imatge.depth()) >> 3;
    20.  
    21. if (bytesPixel == 1)
    22. color8 = (imatge.isGrayscale()) ? qGray(colorRgb) : obtenirIndexColor(colorRgb);
    23. else
    24. {
    25. colorVermell = qRed(colorRgb);
    26. colorVerd = qGreen(colorRgb);
    27. colorBlau = qBlue(colorRgb);
    28. colorAlpha = qAlpha(colorRgb);
    29. }
    30.  
    31. for (int j = yMin; j <= yMax; j++)
    32. {
    33. pixelsLiniaFoto = static_cast<quint8 *>(imatge.scanLine(j)) + (xMin * bytesPixel);
    34.  
    35. for (int i = xMin; i <= xMax; i++)
    36. {
    37. switch (bytesPixel)
    38. {
    39. case 1:
    40. *(pixelsLiniaFoto++) = color8;
    41. break;
    42.  
    43. case 4:
    44. *(pixelsLiniaFoto++) = colorBlau;
    45. *(pixelsLiniaFoto++) = colorVerd;
    46. *(pixelsLiniaFoto++) = colorVermell;
    47. *(pixelsLiniaFoto++) = colorAlpha;
    48. break;
    49. }
    50. }
    51. }
    52.  
    53. update();
    54. }
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. int FotoEditorFotos::obtenirIndexColor(const QRgb &colorRgb)
    2. {
    3. QVector<QRgb> taulaColor = imatge.colorTable();
    4.  
    5. int indexRgb = taulaColor.indexOf(colorRgb);
    6.  
    7. if (indexRgb < 0)
    8. {
    9. // Search for a similar color in the color table...
    10. int n = taulaColor.count();
    11.  
    12. int verd = qGreen(colorRgb);
    13. int vermell = qRed(colorRgb);
    14. int blau = qBlue(colorRgb);
    15. int alpha = qAlpha(colorRgb);
    16. int diffMin = 1021; // 255*4 + 1
    17. int diff;
    18. QRgb rgb;
    19.  
    20. for (int i = 0; i < n; i++)
    21. {
    22. rgb = taulaColor[i];
    23. diff = qAbs(qGreen(rgb) - verd) + qAbs(qRed(rgb) - vermell) + qAbs(qBlue(rgb) - blau) + qAbs(qAlpha(rgb) - alpha);
    24.  
    25. if (diff < diffMin)
    26. {
    27. diffMin = diff;
    28. indexRgb = i;
    29. }
    30. }
    31. }
    32.  
    33. return indexRgb;
    34. }
    To copy to clipboard, switch view to plain text mode 


    Cesar I will try your last version. Thanks

  15. #15
    Join Date
    Feb 2006
    Location
    Kirovohrad, Ukraine
    Posts
    72
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Problems working with 8bpp and 24bpp images

    I'm glad you managed with that . Anyway I suggest you to use QT api, where it is possible to avoid code duplication.
    And here's my suggestion of the second function. I suppose it's a bit more precise
    First of all, let me explain, why is it so. Pretend QRgb is a point with coordinates (r, g, b). Then imatge.colorTable() is a series of points you have to choose from, when approximating random QRgb.
    Let's pretend you have to approximate point QRgb(R', G', B'). The best point to choose from imatge.colorTable() is the one, which is the most close to (R', G', B'). As you know, the distance betwean two points is calculated this way:
    Qt Code:
    1. double distance(const QRgb &x, const QRgb &y)
    2. {
    3. int dRed = qRed(x) - qRed(y);
    4. int dGreen = qGreen(x) - qGreen(y);
    5. int dBlue = qBlue(x) - qBlue(y);
    6.  
    7. return sqrt(dRed * dRed + dGreen * dGreen + dBlue * dBlue);
    8. }
    To copy to clipboard, switch view to plain text mode 
    Now your task is to find such an i, for which distance(color, imatge.colorTable()[i]) is the least. You present algorythm fits well .
    Qt Code:
    1. int FotoEditorFotos::obtenirIndexColor(const QRgb &colorRgb)
    2. {
    3. QVector<QRgb> taulaColor = imatge.colorTable();
    4. /*
    5. int indexRgb = taulaColor.indexOf(colorRgb);
    6.  
    7. if (indexRgb < 0)
    8. {
    9. */
    10. int indexRgb;
    11. // Search for a similar color in the color table...
    12. int n = taulaColor.count();
    13.  
    14. int verd = qGreen(colorRgb);
    15. int vermell = qRed(colorRgb);
    16. int blau = qBlue(colorRgb);
    17. int alpha = qAlpha(colorRgb);
    18. int diffMin = 3 * 255 * 255 + 1;
    19. int diff;
    20. QRgb rgb;
    21.  
    22. for (int i = 0; i < n; ++i)
    23. {
    24. rgb = taulaColor[i];
    25. int dR = vermell - qRed(rgb);
    26. int dG = verd - qGreen(rgb);
    27. int dB = blau - qBlue(rgb);
    28. diff = dR * dR + dG * dG + dB * dB;
    29.  
    30. if (diff < diffMin)
    31. {
    32. diffMin = diff;
    33. indexRgb = i;
    34. if (0 == diffMin) break;
    35. }
    36. }
    37. // }
    38.  
    39. return indexRgb;
    40. }
    To copy to clipboard, switch view to plain text mode 
    Notes:
    • For performance reasons it's better to compare squares of distances rather then distances themselves.
    • There's no need to do indexRgb = taulaColor.indexOf(colorRgb) Guess why.

  16. #16
    Join Date
    Feb 2006
    Location
    Kirovohrad, Ukraine
    Posts
    72
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Problems working with 8bpp and 24bpp images

    Oops, it seems I've forgotten to take alpha channel in account. I suppose you can do it youself.

  17. #17
    Join Date
    Jan 2006
    Location
    Catalonia
    Posts
    266
    Thanks
    44
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Problems working with 8bpp and 24bpp images

    Another time thanks a lot Cesar, your suggestions are very helpfully It's a great idea to calculate a similar color in the table using the distance between two points, I didn't remember that function . I will try it and I comment the results.

    PD: did you forget to calculate the distance using squares in the function 'obtenirIndexColor'?
    Qt Code:
    1. diff = dR * dR + dG * dG + dB * dB;
    To copy to clipboard, switch view to plain text mode 
    The results of calculating the distance multiplying each term with itself are the same that calculating it as I did with the absolute value, no?
    Last edited by SkripT; 15th February 2006 at 15:36.

  18. #18
    Join Date
    Feb 2006
    Location
    Kirovohrad, Ukraine
    Posts
    72
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Problems working with 8bpp and 24bpp images

    Quote Originally Posted by SkripT
    Another time thanks a lot Cesar, your suggestions are very helpfully It's a great idea to calculate a similar color in the table using the distance between two points, I didn't remember that function . I will try it and I comment the results.
    You are always welcome
    Quote Originally Posted by SkripT
    The results of calculating the distance multiplying each term with itself are the same that calculating it as I did with the absolute value, no?
    No I didn't. Consider the example:
    The point to approximate: P(100, 100, 100).
    Two points to choose betwean: A1(75, 125, 100) and A2(100, 51, 100)
    Qt Code:
    1. diffSkript(P, A1) = |100 - 75| + |100 - 125| + |100 - 100| = 25 + 25 = 50
    2. diffSkript(P, A2) = |100 - 100| + |100 - 51| + |100 - 100| = 49
    3. diffCesar(P, A1) = (100 - 75)*(100 - 75) + (100 - 125)*(100 - 125) + (100 - 100)*(100 - 100) = 625 + 625 = 1250
    4. diffCesar(P, A2) = (100 - 100)*(100 - 100) + (100 - 51)*(100 - 51) + (100 - 100)*(100 - 100) = 49*49 = 2401
    To copy to clipboard, switch view to plain text mode 
    As you can see, the results differ. Which one is the best? You choose

  19. #19
    Join Date
    Jan 2006
    Location
    Catalonia
    Posts
    266
    Thanks
    44
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Problems working with 8bpp and 24bpp images

    You' re right Cesar, the results differ!! I will try some colors and see which one is more aproximated.

  20. #20
    Join Date
    Feb 2006
    Location
    Kirovohrad, Ukraine
    Posts
    72
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Talking Re: Problems working with 8bpp and 24bpp images

    Go ahead! And please, post the results, 'cos I'm too curious

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.