CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 3 123 LastLast
Results 1 to 15 of 31
  1. #1
    Join Date
    May 2011
    Posts
    19

    .NET bitmap loaded from 1bpp png stored as 32bpp

    I am developing a .NET C++ application that loads PNG/TIF images into System:rawing::Bitmap.

    However, when I construct a new bitmap like this:
    Code:
    Bitmap bm = gcnew System::Drawing::Bitmap(gcnew System::String("1bpp.png"));
    the bitmap I am returned has PixelFormat::Format32bppArgb, even though the png file being loaded is stored in 1bpp format.

    However, I want the image to be loaded in the same pixel format as the png file (1bpp in this situation) because my algorithm assumes this memory layout.
    Aside from converting back to 1bpp upon loading (which is inefficient), is there any way for me to load the PNG as a 1bpp Bitmap directly? Even if I can only get a pointer to the buffer containing the pixel data, I could use this to construct a bitmap as well, so let me know if this is possible.

    I would like to avoid external (non-NET) libraries if possible.

    Thank you in advance.

  2. #2
    Join Date
    Jun 2010
    Location
    Germany
    Posts
    2,675

    Re: .NET bitmap loaded from 1bpp png stored as 32bpp

    In my experiments (only with PNG files, though) it looked like this "force conversion" of the pixel format only happens to 1 bpp files. (You may have noticed that too but that's not clear from your post.)

    I tried to convert the loaded bitmap back down to 1 bpp like this:

    Code:
      m_bmp = m_bmp->Clone(Rectangle(Point(0, 0), m_bmp->Size), PixelFormat::Format1bppIndexed);
    Unfortunately this kept throwing an OutOfMemoryException. According to MSDN it should only do that if the rectangle parameter passed to that method exceeds the bounds of the source bitmap which clearly isn't the case here. Looks like this kind of conversion is not possible using this simple method.

    Also, I didn't find an easy way to detect that the bitmap originally was 1 bpp.

    Quote Originally Posted by Amil View Post
    Even if I can only get a pointer to the buffer containing the pixel data, I could use this to construct a bitmap as well, so let me know if this is possible.
    I don't think the Bitmap class keeps a copy of the raw bitmap data read from the file. Of course you're free to access the file directly, but already determining the bit depth of the file isn't really trivial for the TIFF format (I'm not familiar enough with the PNG format's internals to state details about that).

    As the situation looks to me at the moment, doing the conversion from 32 bpp back to 1 bpp based on the .NET Bitmap class yourself is an option worth to consider. The biggest problem I see with that is to determine whether the original data was 1 bpp, but of course I don't know the details of your scenario and there may be a relatively easy way that I don't know of.

    Ah, and... Welcome to CodeGuru!
    I was thrown out of college for cheating on the metaphysics exam; I looked into the soul of the boy sitting next to me.

    This is a snakeskin jacket! And for me it's a symbol of my individuality, and my belief... in personal freedom.

  3. #3
    Join Date
    May 2011
    Posts
    19

    Re: .NET bitmap loaded from 1bpp png stored as 32bpp

    Thanks for the response.
    Hmm... yes, it only happens for 1bpp images. It seems like this is a Microsoft bug. I am using .NET 3.5
    I used this guide to convert back to 1bpp, but this process is becoming a bottleneck in my code, which I am actually trying to optimize.

    Does anybody else have any ideas?
    If not, is there a way to contact Microsoft directly?

  4. #4
    Join Date
    May 2011
    Posts
    19

    Re: .NET bitmap loaded from 1bpp png stored as 32bpp

    [It seems I cannot edit my old post]
    About detecting the color depth of the original image, I am not worried about this. The code will automatically convert any image loaded to 1bpp (or 8bpp) blindly.

  5. #5
    Join Date
    Jun 2010
    Location
    Germany
    Posts
    2,675

    Re: .NET bitmap loaded from 1bpp png stored as 32bpp

    Quote Originally Posted by Amil View Post
    Thanks for the response.
    You're welcome.

    Hmm... yes, it only happens for 1bpp images. It seems like this is a Microsoft bug. I am using .NET 3.5
    I'm using .NET 4 and it behaves the same.

    I used this guide to convert back to 1bpp, but this process is becoming a bottleneck in my code, which I am actually trying to optimize.
    I think it's not easy to beat the code you linked to since it does its conversion in a single call to BitBlt(). Well, maybe GDI doesn't make (full) use of SSE in that function which would probably leave room for significant optimizations. However, I, personally, don't really like programming the SSE features and am pretty happy if I have access to routines that do use them for me. Writing your own SSE-based conversion would certainly be a lot of work and moreover that can't be done in managed code. However, incorporating native routines isn't really that hard in C++/CLI though it at least would strcturally complicate your program.

    Does anybody else have any ideas?
    I hope so. Let's wait and see...

    If not, is there a way to contact Microsoft directly?
    I know there is one but I don't recall where at the moment, and it's too late here to really motivate me to search for it. There are certainly others who can tell you off the top of their head. In case they don't find this thread and respond I may search for that page after having some sleep.

    I'm not completely sure though that this actually is a bug. There often is a reason behind such things and they just don't tell us what it is so that it looks weird to us. (The popular idiom for this is "It's not a bug, it's a feature.", while MS seems to prefer "This is by design." )

    Quote Originally Posted by Amil View Post
    [It seems I cannot edit my old post]
    IIRC, post editing will be enabled after you made three posts. I.e. you probably can use it from now on.

    About detecting the color depth of the original image, I am not worried about this. The code will automatically convert any image loaded to 1bpp (or 8bpp) blindly.
    The real pitty is that, as I understand it, you'll actually need two conversions to be performed (the first one of which happens implicitly during Bitmap construction) which will often compensate each other and thus will be overall redundant...
    I was thrown out of college for cheating on the metaphysics exam; I looked into the soul of the boy sitting next to me.

    This is a snakeskin jacket! And for me it's a symbol of my individuality, and my belief... in personal freedom.

  6. #6
    Join Date
    Jun 2010
    Location
    Germany
    Posts
    2,675

    Re: .NET bitmap loaded from 1bpp png stored as 32bpp

    Quote Originally Posted by Amil View Post
    If not, is there a way to contact Microsoft directly?
    I found this link in the VC++ section: http://connect.microsoft.com/ It is frequently referred to in this context but I've not yet used it myself.
    Last edited by Eri523; May 31st, 2011 at 05:41 PM.
    I was thrown out of college for cheating on the metaphysics exam; I looked into the soul of the boy sitting next to me.

    This is a snakeskin jacket! And for me it's a symbol of my individuality, and my belief... in personal freedom.

  7. #7
    Join Date
    May 2011
    Posts
    19

    Re: .NET bitmap loaded from 1bpp png stored as 32bpp

    Thank you for your help Eri!

    If nobody else responds in the next few days, I'll look into contacting Microsoft.

  8. #8
    Join Date
    May 2011
    Posts
    19

    Re: .NET bitmap loaded from 1bpp png stored as 32bpp

    Okay, I have posted the bug (or feature) to Microsoft Connect.
    Here is the link: https://connect.microsoft.com/Visual...tored-as-32bpp

  9. #9
    Join Date
    Jun 2010
    Location
    Germany
    Posts
    2,675

    Re: .NET bitmap loaded from 1bpp png stored as 32bpp

    Quote Originally Posted by Amil View Post
    Okay, I have posted the bug (or feature) to Microsoft Connect.
    Here is the link: https://connect.microsoft.com/Visual...tored-as-32bpp
    Thanks for the link. You already have two comments there, though just the usual "we're working on it" stuff. (Do you get notified about any comment that comes in or just when they found a solution - or closed the subject unsolved?)

    I find it interesting that the outcome depends on the app that generated the PNG. Did you try a binary compare on your two files? That might be quite helpful in narrowing down the problem, especially if they are the same size (what you say they are). BTW, what is that size?
    I was thrown out of college for cheating on the metaphysics exam; I looked into the soul of the boy sitting next to me.

    This is a snakeskin jacket! And for me it's a symbol of my individuality, and my belief... in personal freedom.

  10. #10
    Join Date
    May 2011
    Posts
    19

    Re: .NET bitmap loaded from 1bpp png stored as 32bpp

    I attached the images that cause this problem.

    I just got one e-mail from Microsoft saying that it has been forwarded to their team.
    If nobody else has a workaround, I guess I'll wait for Microsoft's response. Luckily, I am able to convert back to 1bpp using that guide. Although there is a performance impact, I think this is okay for now.

    Thanks again for all your help!
    Attached Images Attached Images   

  11. #11
    Join Date
    Jun 2010
    Location
    Germany
    Posts
    2,675

    Re: .NET bitmap loaded from 1bpp png stored as 32bpp

    Quote Originally Posted by Amil View Post
    I attached the images that cause this problem.
    Although the two images are the same pixel size they didn't arrive as the same file size. Can you attach a ZIP containing both PNG images?

    I just got one e-mail from Microsoft saying that it has been forwarded to their team.
    Give them some time to adjust their speed to normal real-life-on-the-ground people like us. Maybe you'll still want to keep us (well, in fact it's probably mainly me) informed about the progress of that thread on the MS site.

    If nobody else has a workaround, I guess I'll wait for Microsoft's response. Luckily, I am able to convert back to 1bpp using that guide. Although there is a performance impact, I think this is okay for now.
    IMO it's fine that there's still the option of converting it back to 1 bpp yourself (though, as I pointed out above, it's likely to be a real shame if it's redundant). But view it this way: If it's actually the only option, complaining about the performance impact isn't really an option...
    I was thrown out of college for cheating on the metaphysics exam; I looked into the soul of the boy sitting next to me.

    This is a snakeskin jacket! And for me it's a symbol of my individuality, and my belief... in personal freedom.

  12. #12
    Join Date
    May 2011
    Posts
    19

    Re: .NET bitmap loaded from 1bpp png stored as 32bpp

    Sorry about the files, that was a mistake on my part. They are actually off by 10 bytes.

    I'll definitely post back if I hear of any other developments. Hopefully somebody else will see this thread and have a solution.


    ----
    PS: I can now edit my posts

  13. #13
    Join Date
    Jun 2010
    Location
    Germany
    Posts
    2,675

    Re: .NET bitmap loaded from 1bpp png stored as 32bpp

    Ok, despite the fact that the differing file size made a plain binary compare (with fc for instance) look pretty useless, I investigated the effective differences between the two files in the meantime.

    For experiments and in particular for visualization of my results I wrote a "small" PNG file dump utility, and following is its output for the two files you attached, with the (I think) essential difference highlighted in red:

    Code:
    Eri's PNG File Dump Utility Ver. 0.0.4171.6712
    
    Dumping file 1bpp.png
    
    Offset 0x00000000: File signature: 89 50 4E 47 0D 0A 1A 0A  .PNG....
    Valid PNG file
    
    Offset 0x00000008: Chunk type IHDR - Image header
    critical, public, may not be copied if unrecognized
    Chunk data size 13 bytes, CRC 0x0EA90245 (valid)
      Width: 414
      Height: 135
      Bit depth: 1
      Color type: 0 (grayscale)
      Compression method: 0
      Filter method: 0
      Interlace method: 0 (none)
    
    Offset 0x00000021: Chunk type bKGD - (unknown)
    ancillary, public, may not be copied if unrecognized
    Chunk data size 2 bytes, CRC 0xDD8A13A4 (valid)
    
    Offset 0x0000002F: Chunk type IDAT - Image data
    critical, public, may not be copied if unrecognized
    Chunk data size 203 bytes, CRC 0x3BDBB51B (valid)
    
    Offset 0x00000106: Chunk type IEND - End of image
    critical, public, may not be copied if unrecognized
    Chunk data size 0 bytes, CRC 0xAE426082 (valid)
    Code:
    Eri's PNG File Dump Utility Ver. 0.0.4171.6712
    
    Dumping file 1bpp-butOK.png
    
    Offset 0x00000000: File signature: 89 50 4E 47 0D 0A 1A 0A  .PNG....
    Valid PNG file
    
    Offset 0x00000008: Chunk type IHDR - Image header
    critical, public, may not be copied if unrecognized
    Chunk data size 13 bytes, CRC 0x1C1CADAB (valid)
      Width: 414
      Height: 135
      Bit depth: 1
      Color type: 3 (indexed)
      Compression method: 0
      Filter method: 0
      Interlace method: 0 (none)
    
    Offset 0x00000021: Chunk type PLTE - Palette
    critical, public, may not be copied if unrecognized
    Chunk data size 6 bytes, CRC 0xA5D99FDD (valid)
      0 [R=0, G=0, B=0]  1 [R=255, G=255, B=255]
    
    Offset 0x00000033: Chunk type IDAT - Image data
    critical, public, may not be copied if unrecognized
    Chunk data size 209 bytes, CRC 0x300BBF8A (valid)
    
    Offset 0x00000110: Chunk type IEND - End of image
    critical, public, may not be copied if unrecognized
    Chunk data size 0 bytes, CRC 0xAE426082 (valid)
    Is there any chance to influence this aspect of saving the file in Magick++?

    I also considered simply hacking the non-working file but that's easier said than done. Changing the color type entry in the header chunk would require to adjust the header checksum. Moreover, a palette chunk which is not present in the original non-working file would need to be added. This can't simply be done with a hex editor but can be done with a reasonably small piece of code, either inside your app or as an external tool. The PNG chunk classes in the dump utility could be used as a starting point for that though they don't support writing to a PNG file yet. However, I think this only is a viable option if the actual image data in the IDAT chunk can be reused as-is which I didn't check yet.

    This programmatic hacking approach would either require to modify the input file (would your app be allowed to do this?) or to create a temporary PNG file either on disk or as a memory stream which can be used to construct a Bitmap object as well. Is this an option?

    With more than 300 code lines (and it's not even really advanced yet) the PNG dump utility is IMO a bit too large to simply post it here in code tags, even more since it's not really the topic of this thread. So I zipped up the .cpp file and attached that to the post.

    For reference on the PNG file format see the Wikipedia article or, for really in-depth information, the official file format specification at http://www.w3.org/TR/PNG/.
    Attached Files Attached Files
    Last edited by Eri523; June 3rd, 2011 at 03:00 PM.
    I was thrown out of college for cheating on the metaphysics exam; I looked into the soul of the boy sitting next to me.

    This is a snakeskin jacket! And for me it's a symbol of my individuality, and my belief... in personal freedom.

  14. #14
    Join Date
    May 2011
    Posts
    19

    Re: .NET bitmap loaded from 1bpp png stored as 32bpp

    Woah, this is pretty cool. From what you said, it looks like the problem is due to the difference in color type (grayscale vs indexed). Still, it seems like a mistake on Microsoft's part.

    Hmm... it seems like figuring out how to modify the header data of the files would indeed be a task involving streams, etc. (I can only assume read-only access to files).
    Actually this is not really a big issue at this point in my code. In fact, I decided to just rewrite the code to write future images using .NET library instead of Magick++, so this is now just an issue for older batches of images.


    Thank you for putting so much effort into it though. I really appreciate it. Nobody else really was able to help on this.
    You seem to have very in-depth knowledge of how images are stored. I am still just beginning on the path of learning this stuff.

    I posted a follow up in the Microsoft Connect posting. This might help the VS team speed it up.

  15. #15
    Join Date
    Jun 2010
    Location
    Germany
    Posts
    2,675

    Re: .NET bitmap loaded from 1bpp png stored as 32bpp

    Quote Originally Posted by Amil View Post
    In fact, I decided to just rewrite the code to write future images using .NET library instead of Magick++, so this is now just an issue for older batches of images.
    Oh, I wasn't aware that you've got control over the code that generates the images. Now this looks like an optimal solution: I think at least the .NET framework should be compatible to itself...

    Now this looks like a perfect scenario for a console-based batch converter to fix the pre-existing images. I think that wouldn't even really need to be efficient so we may as well use a pixel-wise conversion approach based on the .NET Bitmap class if we can't get the chunk-based approach to work (or we're simply lazy and don't want to take the effort of trying that approach).
    I was thrown out of college for cheating on the metaphysics exam; I looked into the soul of the boy sitting next to me.

    This is a snakeskin jacket! And for me it's a symbol of my individuality, and my belief... in personal freedom.

Page 1 of 3 123 LastLast

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

Featured