Results 1 to 8 of 8

Thread: [RESOLVED] Using GDIplus, how to find out the designated transparent color in an 8-BPP PNG file?

  1. #1

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    373

    Resolved [RESOLVED] Using GDIplus, how to find out the designated transparent color in an 8-BPP PNG file?

    The attached ZIP contains an 8-BPP PNG file which has a designated transparent color. If I use GDIplus, how can I ascertain (i) whether the file has a designated transparent color; and (ii) if affirmative, what is that designated transparent color in file?

    If I load the file with GDIplus, supplying a DIB or PictureBox with a chessboard background, I get a returned DIB/PictureBox per screenshot below:
    Attached Images Attached Images  
    Attached Files Attached Files

  2. #2
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Using GDIplus, how to find out the designated transparent color in an 8-BPP PNG f

    The PNG file has a tRNS chunk as seen via parsing the file. That should contain the index you are looking for.

    Per PNG specs
    For color type 0 (grayscale), the tRNS chunk contains a single gray level value, stored in the format:
    Gray: 2 bytes, range 0 .. (2^bitdepth)-1

    Note: when dealing with 16-bit grayscale or truecolor data, it is important to compare both bytes of the sample values to determine whether a pixel is transparent. Although decoders may drop the low-order byte of the samples for display, this must not occur until after the data has been tested for transparency. For example, if the grayscale level 0x0001 is specified to be transparent, it would be incorrect to compare only the high-order byte and decide that 0x0002 is also transparent.
    This may be the constant you want, retrieved via: GdipGetPropertyItem... PropertyTagIndexTransparent (&H5104). Worth a shot

    Edited: That property only exists for GIF files, not PNG. You can get all properties exposed by the metadata that GDI+ provides and maybe one of them offers what you are looking for?

    Otherwise, short of parsing the PNG file/stream manually and extracting the tRNS tag, another solution would be to iterate thru the pixel data. I don't think the tRNS tag is going to do you much good because GDI+ should load these as 32bpp because there is no palette in the PNG & transparency exists. This means GDI+ will report the image as 32bpp not paletted/indexed. In this case, you'll probably need to build the palette manually (if wanted). Of course there will only be one 32bpp pixel color with a zero alpha-byte. I doubt GDI+ will save such an image other than 32bpp.

    FYI: That PNG only contains a few colors: &HFF000000, &HFF808080, &HFFFFFFFF, &H00808080 (transparent).
    Last edited by LaVolpe; Jul 29th, 2018 at 03:23 PM.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  3. #3

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    373

    Re: Using GDIplus, how to find out the designated transparent color in an 8-BPP PNG f

    LaVolpe,

    Thanks. Including "Edited" and "FYI", your answer is exhaustive.

    That property only exists for GIF files, not PNG. So, short of parsing the PNG file/stream manually and extracting the tRNS tag .....
    You have given me the answer. I was wondering how does a GDIplus user establish the designated transparent color in a case like this one. (It is a practice of my program that when no chessboard background is in use, the designated transparent color should be availed on the screen, so that if the program user wants to designate a different color, he/she is not deprived of any color in the original file.)

    For PNG, I don't use GDIplus; I only use my own class, because I need to obtain/process data that GDIplus cannot afford me, e.g. (i) to view the original 16-bit pixel color values of a 16-bit PNG file (in this case, I maintain the decompressed, defiltered and deinterlaced IDAT, show 8-bit pixel colors on screen, then basing on the user's mouse pointer [x, y] position retrieve the original 16-bit color value in IDAT and monitor it on screen), (ii) to save a PNG file at a specific Color Type and Bit Depth.

    I doubt GDI+ will save such an image other than 32bpp.
    GDIplus would save it as 8-BPP, if we pass an 8-BPP DIB. GDIplus would save the subject file as BitDepth 8 and ColorType 3, not ColorType 0. Actually, if the image is a 4-BPP one, and we pass a 4-BPP DIB, GDIplus would save it as BitDepth 4 and ColorType 3.

    --------------------
    Whilst we are here, what really prompted me to ask the captioned question is that the subject PNG file has something unusual - color RGB(128, 128, 128) is being used for both the designated transparent color and one of the three colors in the painted area. If a GDIPlus user loads the file, it looks alright (per image shown in my previous posting), however, if he/she saves the file back to a PNG file, chances are that he/she would have some trouble re-designating a transparent color, because there are now only 3 colors, not four as one would expect.

    Remarks: In my PNG class, I conduct a data vet on loading, on detecing the above-said unusual arrangement, I maintain the RGB(128, 128, 128) as the designated transparent color, but modify the one in the painted area to RGB(127, 127, 127), per screenshot below. I saw some others doing this differently, for example, a FreeImage user changed the designated transparent color to RGB(4, 4, 4) - FreeImage defaults RGB(0, 0, 0) as the screen color, now when it found that there was already a RGB(0, 0, 0) in the paint area, it changed the color in the transparent area (the screen color seen through) to RGB(4, 4, 4) - I don't like it of course.

    Brenker
    Attached Images Attached Images  
    Last edited by Brenker; Jul 29th, 2018 at 04:48 PM.

  4. #4
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Using GDIplus, how to find out the designated transparent color in an 8-BPP PNG f

    The reason 128,128,128 can be used as both transparent and opaque is because the format is 16bit. The opaque and transparent 16 bit color values will not be the same value when all 16 bits are compared.

    Note: 8bpp grayscale has max color range of 256 colors (2^8) whereas 16bpp grayscale is 65535 (2^16)

    As for saving as 8 bit grayscale, only if there is no transparency and a palette chunk may be added. I don't know if setting the palette's Flags property to grayscale will prevent adding the palette chunk. If transparency exists, then GDI+ will save as 32bpp.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  5. #5

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    373

    Re: Using GDIplus, how to find out the designated transparent color in an 8-BPP PNG f

    LaVolpe,

    You're right, the one for the transparent color is 0x8001 and the other is 0x8000. If ours is a 16-bit program this would be perfect. The trouble is that our programs are always on a 8-bit basis and GDIplus would process it only on a 8-bit basis, it ends up we have two identical colors. That is why I said a GDIplus user would have a problem with this one.

    Re our discussion on "Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF?", I had been using the following to save to an 8-BPP TIFF (the resultiing TIFF with PhotometricInterpretation 3 and a ColorMap). The code lines that I used excluded those shown as blocked here.
    Code:
       ' If inTranspColor >= 0 And inTranspColor <= &HFFFFFF Then
       '        'Only GIF and PNG has simple transparency
       '      If inEncoder = [imageGIF] Or inEncoder = [ImagePNG] Then
                  K = GetDIBColorTable(inDIB.DIBhDC, 0, 256, mPalette.Entries(0))
                     ' If mimageBPP is 8 and there is a palette table, then k whould be 256
                     
       '           r = inTranspColor And &HFF&
       '           g = (inTranspColor And &HFF00&) / &H100
       '           b = (inTranspColor And &HFF0000) / &H10000
    
       '           For i = 0 To 255
       '                If mPalette.Entries(i).r = r And mPalette.Entries(i).g = g And mPalette.Entries(i).b = b Then
       '                     mIndex = i
       '                     mIndexFound = True
       '                     Exit For
       '                End If
       '           Next i
       '           If mIndexFound Then
                       mPalette.flags = PaletteFlagsHasAlpha
                       mPalette.count = 256
       '                For i = 0 To 255
       '                     If mPalette.Entries(i).r = r And mPalette.Entries(i).g = g And mPalette.Entries(i).b = b Then
       '                          mPalette.Entries(i).a = 0
       '                     Else
       '                          mPalette.Entries(i).a = 255
       '                     End If
       '                Next i
                         
                       ret = GdipCreateBitmapFromScan0(w, h, 0, PixelFormat8bppIndexed, ByVal inDIB.DIBBitsPtr, hImg)
                       If hImg = 0& Then GoTo earlyExit
                       
                       With typBD
                           .Width = w
                           .Height = h
                           .stride = ((w * 8 + 31) \ 32) * 4
                           .PixelFormat = PixelFormat8bppIndexed
                           .Scan0 = inDIB.DIBBitsPtr
                       End With
                          
                       With typRectL
                           .Left = 0
                           .Top = 0
                           .Right = w
                           .Bottom = h
                       End With
                        
                       ret = GdipBitmapLockBits(hImg, typRectL, ImageLockModeUserInputBuf Or ImageLockModeRead, _
                                     PixelFormat8bppIndexed, typBD)
                       If ret <> 0 Then GoTo earlyExit
                       
                       ret = GdipSetImagePalette(hImg, VarPtr(mPalette))
                       
                       ret = GdipBitmapUnlockBits(hImg, typBD)
                       If ret <> 0 Then GoTo earlyExit
        '          End If
        '     End If
        'End If
    BTW, TIFF ColorMap is supposed to show values between 0 to 65535, but have you noticed, the actual bytes in each two-byte unit are with values in this pattern: "00 00", "01 01", "02 02" ...... "FF FF". My wild guess is that GDIplus just conveniences itself a bit here - it doesn't need to take care whether "II" or "MM" of the TIFF file, either section of the unit would be right, given that it only processes on a 8-bit basis.

    Brenker
    Last edited by Brenker; Jul 29th, 2018 at 05:54 PM.

  6. #6
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Using GDIplus, how to find out the designated transparent color in an 8-BPP PNG f

    You're right, the one for the transparent color is 0x8001 and the other is 0x8000. If ours is a 16-bit program this would be perfect. The trouble is that our programs are always on a 8-bit basis and GDIplus would process it only on a 8-bit basis, it ends up we have two identical colors. That is why I said a GDIplus user would have a problem with this one.
    ^^ But a GDI+ user would never know because GDI+ will force a format into one it supports, i.e., 32bpp in that case, 64bpp converted to 32bpp, etc.

    BTW, TIFF ColorMap is supposed to show values between 0 to 65535, but have you noticed, the actual bytes in each two-byte unit are with values in this pattern: "00 00", "01 01", "02 02" ...... "FF FF". My wild guess is that GDIplus just conveniences itself a bit here - it doesn't need to take care whether "II" or "MM" of the TIFF file, either section of the unit would be right, given that it only processes on a 8-bit basis
    ^^ Yep did notice and I think your guess is right on target.

    Regarding PNG 16bpp grayscale. Trying to force this into an 8bpp palette can fail. Suppose all 256 shades of grayscale were used and were opaque and one additional shade was made transparent. That would mean you'd need a 257 color palette, not 256. Can't fit each of the 257 possible values in a single byte. Besides, PNG grayscale do not use palettes and only are restricted by bit depth. Can't really compare PNG grayscale to GDI paletted grayscale as "apples to apples". GDI+ forcing this format w/tRNS chunk to 32bpp, internally, makes sense to me.

    Also do note that this "problem" can occur with 16bpp (per channel/component) true color (6 bytes/48 bits per pixel) where a tRNS chunk identifies one color as transparent -- therefore all 48bits need to be compared against that chunk's value. GDI+ forcing this format w/tRNS chunk to 32bpp, internally, makes sense to me.
    Last edited by LaVolpe; Jul 29th, 2018 at 06:38 PM. Reason: typo
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  7. #7

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    373

    Re: Using GDIplus, how to find out the designated transparent color in an 8-BPP PNG f

    LaVolpe,

    But a GDI+ user would never know because GDI+ will force a format into one it supports, i.e., 32bpp in that case, 64bpp converted to 32bpp, etc.
    I meant that using GDIplus the user would get a returned image as shown in my posting #1. If the screen color used is &HFFFFFF or &H0 (these are commonly so), then on saving to a PNG file, he/she has only 3 colors in hand.

    There are lots of 16-bit file around, especially TIFF, it is a fact of life. We might say that the subject PNG is an exception, as the file is downloaded from a test suite site.

    Anyway, my curiosity about GDIplus in transparent color is satisfied now, thank you.

    Brenker

  8. #8

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    373

    Re: [RESOLVED] Using GDIplus, how to find out the designated transparent color in an

    Someone asks, in my Posting #3 how did I modify pixels in the painted area from RGB(128, 128, 128) to RGB(127, 127, 127)?

    Whenever a 16-bit PNG has a tRNS chunk, a smart program should check possible duplicate colors after conversion to 8-bit - one being the converted transparent color, the other in the painted area. Before conversion, with reference to the original 16-bit tRNS color, establish which part of image is transparent and which part is not. Then after conversion, check whether the painted area has a color which is identical to the converted transparent color; if yes, modify it in a way comparable to what is exemplified in my Posting #3.

    Edited:
    The principle applies to a 16-bit RGB image (i.e. 48-BPP) as well, if it has to be converted to 8-bit.
    Last edited by Brenker; Aug 6th, 2018 at 12:55 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width