Page 1 of 2 12 LastLast
Results 1 to 40 of 41

Thread: [RESOLVED] Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF?

  1. #1

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    362

    Resolved [RESOLVED] Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF?

    Using the newer version of GDIplus on Win 7/Win 10, is there a way to save a grayscale JPEG/TIFF to an 8-BPP grayscale JPEG/TIFF?
    There is no problem saving a grayscale JPEG/TIFF in grayscale image, but to be recognized as 8-BPP (by softwares), it must meet the respective criteria:

    For JPG, "No. of components" in SOF0 (Baseline DCT) is 1, not 3.
    For TIFF, "PhotoMetricInterpretation" (tag 262) is 0/1, not 3.

    Any one knows the method or trick?

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

    Re: Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF?

    If you look at the TIFF 6.0 specifications on line, building a grayscale TIFF manually wouldn't be that difficult. There were a few other requirements for grayscale:

    Required Fields for Grayscale Images
    These are the required fields for grayscale images (in numerical order):
    TagName, Decimal, Type, Value
    ImageWidth, 256, SHORT or LONG, ...
    ImageLength, 257,SHORT or LONG, ...
    BitsPerSample, 258, SHORT, 4 or 8
    Compression, 259, SHORT, 1 or 32773
    PhotometricInterpretation, 262, SHORT, 0 or 1
    StripOffsets, 273, SHORT or LONG, ...
    RowsPerStrip, 278, SHORT or LONG, ...
    StripByteCounts, 279, LONG or SHORT, ...
    XResolution, 282, RATIONAL, ...
    YResolution, 283, RATIONAL, ...
    ResolutionUnit, 296, SHORT, 1 or 2 or 3

    In Baseline TIFF, grayscale images can either be stored as uncompressed data or compressed with the PackBits algorithm. Caution: PackBits is often ineffective on continuous tone images, including many grayscale images. In such cases, it is better to leave the image uncompressed
    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
    362

    Re: Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF?

    LaVolpe,

    On "Save As ...", of the few common file formats, viz. BMP, JPG, GIF, PNG, TIFF, ICO, CUR, ANI, TGA and PCX, "TIFF" is the only one that I am unable to "do it manually".

    On Save As TIFF, compression is a key issue, apart from color model. Here my program allows only "CCITT4" or "LZW" compression, the former is for B/W images and the latter RGB ones. Currently, zLIB is the only external DLL that my program uses (for PNG CRC and compression); since zLIB doesn't cover LZW, so I will be stuck with both of the above-said compressions if I don't use GDIplus on "Save As TIFF".

    Why not Packbits as you suggested (or RLE)? Inefficient in compression ratio and very slow in speed [image(s) of a TIFF file are usually of a monster size]. If for my own use, this might nevertheless be a solution under special circumstances - the related issue will be discussed a bit later. However, since the program is for public use, I have to maintain a consistency in program quality; hence an invariable use of Packbits won't be suitable.

    What is the program quality on "Save As ..."? On the whole, it always auto-selects the most appropriate color depth on "Save As ...", 32, 24, 8, 4, 2 or 1 BPP unless a particular file format doesn't have that BPP, and assorted essential options are provided for user to choose from. The screenshots of SaveAsPNG, SaveAsJPG and SaveAsTIFF are appended below as an example, with some explanation given on salient points.

    Save As PNG: Preview is updated as and when user changes the options, e.g. if "Preserve ICC" is opted, Preview reflects that. Unlike libPNG which indiscriminately fixes IDAT size split to 8192 bytes, my program lets user to determine it (with a default at 409600 bytes). Saving to 8 BPP Grayscale PNG would never be a problem here.

    Save As JPG: Proforma file size is shown on screen as a reference on user's selection of a "% Quality", besides the update of Preview image (button for a full screen view is also provided for user's inspection of image quality at the selected % quality). Except when "Preserve ICC" is opted (you know why of course), user is allowed to choose whether 8 BPP or 24 BPP Grayscale. Saving to 8 BPP Grayscale is also not a problem here, without GDIplus.

    Save As TIFF: Saving to 8 BPP Grayscale would be a problem, if GDIplus is incapable of doing it. Currently I am using FreeImage to do the job, but I really want to shake it off - it is silly to have FreeImage just for this tiny part. On this screenshot you see that "CCITT4 compression" is ticked, but checkbox is dimmed because user is not supposed to change it.

    Earlier on I said that "... the related issue will be discussed a bit later", I was thinking of the ICC Conversion for a Grayscale TIFF. Presently I have to convert a 16-bit or 8-bit PNG to JPG first (at the background) on converting PNG grayscale ICC, your Packbits suggestion makes me ponder whether I could do something here (in lieu of the said "via JPG" approach). Because it would be a "behind the scene" operation here, Packbits or LZW doesn't matter (once ICC conversion is done, it doesn't leave a Packbits record behind), speed might be a problem though.

    Brenker
    Attached Images Attached Images    
    Last edited by Brenker; Jul 20th, 2018 at 12:17 AM.

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

    Re: Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF?

    Out of curiosity, I created a grayscale image and formatted it as TIFF, both uncompressed & LZW. As you stated, the PhotometricInterpretation property value is not correct, but I changed that value manually. Because GDI+ wouldn't do grayscale on its own, it also included a ColorTable property, so I changed that to a "private" property thereby preventing GDI+ from reading it as an actual baseline TIFF property. This was done simply so I didn't have to remove that property & rewrite the entire TIFF manually.

    Here's the result: GDI+ will read the TIFF without problems, but it treats it as B&W only, regardless of the compression mode. Toggling the PhotometricInterpretation value from 1 to 0 displayed it B&W color-inverted. When I get home I'll repeat this test and bring up the modified TIFF in another viewer (which I don't have access to at this time) other than MS products.

    GDI+ will save 8 bit TIFF if source is 8 bit. Will save uncompressed TIFF if requested.

    Even if this works in other viewers, as grayscale, not B&W, then GDI+ is limited in not only saving, but displaying true TIFF grayscale images. Tweaking the TIFF data after converting image to TIFF is pretty easy, but that doesn't matter if GDI+ can't display it properly.

    P.S. GDI+ saving an 8-bit grayscale as an 8-bit color image should be easy to overcome in most cases. Since GDI+ will require a palette, any bogus palette will work because you are going to remove it from the TIFF/JPG after GDI+ creates the image format. Tweaking that data for true grayscale might be a simple matter of adding/removing a JPG block/property or two and/or modifying a block/property value. As mentioned above, the only question is, "will GDI+ display it properly"?

    Edited: GDI+ has no problem displaying proper grayscale TIF. B&W issue noted above was result of 8bit palette not being sorted. A workaround for saving in that format is outlined in post #7 below.
    Last edited by LaVolpe; Jul 20th, 2018 at 09: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}

  5. #5

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    362

    Re: Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF?

    In case you are interested, attached ZIP contains a multi-page TIFF file, encompassing different compressions in different pages, altogather 11 pages, all sized 600x75:

    1 -- No compression
    2 -- No compression CMYK
    3 -- JP2000
    4 -- JPEG
    5 -- JBIG
    6 -- PackBits
    7 -- PackBits CMYK
    8 -- PackBits YCbCr
    9 -- LZW
    10 -- CCITT4
    11 -- CCITT3

    GDIplus newer version can't handle 3, 5 & 8 (older version can't handle 4 also).

    Edited:
    Remarks: GDIplus newer version can display 3, but with all black.
    Attached Files Attached Files
    Last edited by Brenker; Jul 20th, 2018 at 12:43 PM.

  6. #6

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    362

    Re: Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF?

    In case someone is interested in the Tag Listing of Page 6 which compression is PackBits, for your ready reference below is the screenshot of it.
    Attached Images Attached Images  

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

    Re: Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF?

    Here's the workaround for TIF. The comments below assume you are building 8-bit grayscales vs 4-bit. But 4-bit grayscale is allowed in a TIF.

    1. Pass an 8-bit GDI+ bitmap for saving as TIF

    - The GDI+ grayscale palette must be sorted, 256 colors (0 to 255) & include the alpha byte
    note: an unsorted palette may result in B&W image as was the case in my previous post if creating a bitmap via Scan0.
    alternatively. Pass a valid GDI 8-bit bitmap (sorted palette) to GDI+ bitmap creation routine and convert that GDI+ bitmap to TIFF

    - Either use no compression, LZW or packbits when building the TIF

    - Also must use 8-bit color depth when building the TIF: EncoderColorDepth, GUID: 66087055-AD66-4C7C-9A18-38A2310B8337

    2. After the TIF is created, return the data in a stream/array so you can update it manually

    3. Parse the TIF (easy to do), starting from 4-byte offset located at the 4th byte in stream/array (zero-bound)
    - When parsing the IFDs (Image File Directory), when Tag 262 (PhotometricInterpretation) occurs, change its value to 1. It will be 3.

    4. Save the bytes/stream or send the stream back to GDIpLoadImageFromStream and create the updated TIF

    Edited: The 8-bit palette (1536 bytes, tag 320, ColorMap) will still exist in the TIF. In order to get rid of it, you will have to completely parse the TIF to rewrite all the tags except the ColorMap. Doing this will require you to modify some of the tag offsets for any that have data located after the ColorMap data in the array/stream. Writing a TIF manually like this is not that difficult because GDI+ did 99% of it for you. You are simply updating the data. Your new stream/array size will be 1536+12 bytes (IFD) smaller when done. Note: IFDs must be written in numerical tag order, per TIF specs. And tag 320 should be the last IFD, numerically, but I wouldn't bet the farm that it will always be in all situations.

    Note: If the ColorMap data is the last data block to be written in the array/stream, then you can simplify rewriting because you truncate the stream, remove the tag 320 IFD, and shift any remaining tags. The stream will have just 12 extra bytes when compared to rewriting the entire stream the proper way.

    The TIF specifications 6.0 is not that hard to follow. I think it is maybe a bit easier than PNG.

    And just FYI: The LZW algorithm is no longer a recommended compression option due to questionable copyright claims. This is explained well in the 6.0 specs. I'm actually a bit surprised that GDI+ includes it, but maybe Microsoft has a standing license?
    Last edited by LaVolpe; Jul 20th, 2018 at 09:07 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}

  8. #8

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    362

    Re: Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF?

    LaVolpe,

    Thank you for the pursuit. I will try what you've described in the next couple of days. I understand what are entailed and they don't seem to be overly complicated.

    I will come back to let you know the result in due course.

    Brenker

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

    Re: Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF?

    Yep, the hardest part will be to rewrite the TIF if offsets need to be modified -- shifting & removing blocks of bytes into a contiguous group can be challenging depending on complexity.

    GDI+ seems to write the ColorMap as the last data block. But relying on that may break your app in the future if GDI+ decides to write it closer to the beginning of the stream.

    Edited: If a multi-page TIFF and the ColorMap(s) data isn't at the end of the stream, I think the only way to solve this would be to rewrite the entire TIF to remove the 1+ kb data blocks

    If you are not familiar with parsing TIFs, here's a little routine to help get your feet wet. It simply scans an entire TIF (multipage also) and returns a listing of which pages (as offsets) have a ColorMap entry. Load the TIF into a byte array and send that to the routine...

    Assumption: You are passing TIF data that was created by GDI+ on a Windows system. Otherwise, you'll need to handle potential of big-endian entries also. Additionally, many safety checks are not made because GDI+ doesn't break the rules, i.e., tags not sorted, unrecognized data-type values, invalid offsets causing buffer overflows, etc.
    Code:
    Private Function pvHasColorMap(TIFbits() As Byte) As Collection
    
        ' Return values:
        '   Nothing: not little endian data (GDI+ creation on Windows will be little endian)
        '   Listing of offsets to IFDs where directory contains ColorMap data
    
        Dim IFDoffset As Long, IFDcount As Long
        Dim IFDtag As Long, colRtn As Collection
        Dim n As Long, lPos As Long
    
        If (TIFbits(0) Or TIFbits(1) * &H100&) <> &H4949& Then Exit Function ' not little-endian or not tif
        
        ' IFD (TIF Page) structure as a UDT
        
        ' Private Type IFDentryStruct
        '   Tag As Integer              ' unsigned 2 bytes ("private" tag has high bit set)
        '   DataType As Integer         ' unsigned 2 bytes (valid: 1 to 12 inclusively, as of 6.0 specs)
        '   NrTypes As Long             ' unsigned 4 bytes
        '   ValueOrOffset As Long       ' unsgined 4 bytes
        ' End Type
        
        ' Private Type IFDstruct
        '   NrEntries As Integer        ' unsigned 2 bytes
        '   Entry() As IFDentryStruct   ' collection of IFD entries, sorted on Entry.Tag
        '   NextIFDoffset As Long       ' unsigned 4 bytes (0 indicates end of directories)
        ' End Type
        
        Set colRtn = New Collection
        CopyMemory IFDoffset, TIFbits(4), 4& ' get offset to 1st IFD
        
        Do Until IFDoffset = 0
            IFDcount = TIFbits(IFDoffset) Or TIFbits(IFDoffset + 1) * &H100& ' nr of entries in IFD
            lPos = IFDoffset + IFDcount * 12 - 10 ' position of last entry in this IFD
            For n = 1 To IFDcount
                IFDtag = TIFbits(lPos) Or TIFbits(lPos + 1) * &H100& ' entry Tag
                If IFDtag = 320 Then            ' color map
                    colRtn.Add IFDoffset        ' add offset to collection
                    Exit For                    ' done with this IFD
                ElseIf IFDtag < 320 Then
                    Exit For                    ' this IFD has no color map (multi-page TIF?)
                End If
                lPos = lPos - 12                ' move to previous IFD entry
            Next
            lPos = IFDoffset + IFDcount * 12 + 2 ' locate next IFD & get its offset
            CopyMemory IFDoffset, TIFbits(lPos), 4&
        Loop
        Set pvHasColorMap = colRtn              ' return offsets where ColorMap entries found
    
    End Function
    Last edited by LaVolpe; Jul 21st, 2018 at 01:36 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}

  10. #10

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    362

    Re: Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF?

    LaVolpe,

    Thanks for being considerate.

    (A)

    Occasionally I do have to manipulate TIFF tags a bit, e.g. I allow user to insert/replace/delete an ICC Profile to a TIFF file when it is single-paged. From the comments below you can sense out how troublesome the job could be:

    Code:
    ' To delete, e.g. ICC Profile (34675) or Software (305) in file.  After deletion of a tag, some
    ' offsets need to be adjusted. As some TIFF files may not be coded properly, e.g. in Units, to
    ' ensure correct offset adjustments, it is advisable to call "Resave_TIFF_CYMK_via_GDI()" or
    ' "Resave_TIFF_CMYKorRGB_via_GDI()" (both required gOS64bit) before calling Delete_Tag.
    Code:
     'Delete ICC Profile tag, reduce entry of tag count by 1
    Code:
    'Split file into two sections, abandon the tag to be deleted
    Code:
    'Adjust offsets of some tags if required (for one tag removed)
    Code:
    'An Offset?
    .........
    .........
    (1) For the "Value" field, I have to test whether it is value or an offset:

    If BytesPerTagType(mTagType) * mUnits > 4 Then
    .......

    (2) Ascertain whether a Tag is before or after the Tag to be deleted.


    If the original file is properly coded, then things would be alright still, but the trouble is that sometimes there is some regularity in the original file - it could screw up whatever you have done. That is why I have the remarks in the first comment above.


    (B)

    On File Open, if the file selected is a multi-page TIFF (or a multi-item ICO for that matter), a screen similar to the screenshot below will materialize itself, to let user select a page to load.

    (1) You see "ICC Profile: Yes" -- If user selects the subject page, its original grayscale & BPP status would remain, and its original ICC profile would be automatically included in the loaded Page file.

    (2) You see a "Tag Listing" button -- User can invoke a Tag Listing of that selected page, similar to what you see in my Posting #6.


    (C)

    We don't have to do much in a multi-page TIFF handling, as briefly mentioned in "B" above.

    We can just call GdipImageSelectActiveFrame and GdipSaveImageToFile

    However, we have to detect whether PixelFormat32bppCMYK or PixelFormat32bppARGB in calling GdipBitmapLockBits


    (D)

    The problem we are talking occurs only when an image is already loaded, user may or may not have edited it, and he/she clicks "Save As TIFF" menu.


    BTW, I haven't really started my day yet today, because I fell sick last night. Yesterday afternoon on our way home from somewhere my wife asked me to pull over at the car park of a grocery, she told me "I need very little time because I am only to get 2 or 3 items". When she re-appeared it was an hour later and meanwhile I had dozed off inside the car, in such a hot and sunny day.


    Brenker
    Attached Images Attached Images  
    Last edited by Brenker; Jul 22nd, 2018 at 08:35 AM. Reason: Add "D"

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

    Re: Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF?

    If being forced to rewrite a TIF (whether GDI+ created it or not), here are what I think are the biggest issues

    1. Handling private tags. Is the Value field an offset to a value or a value? Almost impossible to know because the custom value can literally mean anything. It seems the only safe solution is to not carry over private tags.

    2. Handling unknown non-private tags (except zero). Are these errors in the file or new tags introduced in a TIF specs revision? This is a similar problem to private tags, except that the new/unknown tag could be critical for proper TIF display/parsing. The key question: Is the value field an offset or value? You may not know and if you don't know, how can you move the binary data when rewriting?

    3. Dealing with offset-related fields where the data type is SHORT and count is two. Both offsets are stored in the 4-byte Value field. When rewriting the TIF, you may have to change the data type to LONG, depending on the new offsets, and store the offsets in the binary section of the file vs. the Value field of the IFD entry. Note: I don't know if GDI+ will default to LONG data types when count is two, in these cases?

    4. Invalid data types. In future revisions of TIF, if more data types are offered, how could your compiled code possibly know? Is the Value field an offset or a value? Opting to not carry these over in the rewrite is likely not an option because the tag may be important for rendering/parsing the image data.

    Thinking out loud, I think I'd tend to not carry over private tags. And if unknown data types were found (new revisions), maybe opt not to rewrite the file. Editing TIFs is easier the rewriting. Editing can result in file size increases due to "dead/unknown" data remaining in the file after edits.
    Last edited by LaVolpe; Jul 21st, 2018 at 03:54 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}

  12. #12

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    362

    Re: Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF?

    LaVolpe,

    Yes, I see your points.

    A bit earlier when we were talking of "multi-page" TIFF, I said something in my first "comment" (e.g. Resave_......). Actually I sometimes would also "Resave" a file, despite it is single-paged. That is when I found that the file has an irregularity screwing up my adjustments. GDIplus has done a good job in this; I found that the marjor part is preserved by GDIplus, but not necessarily all tags. I can't recall what is/are being dropped by GDIplus - it could well be the "private tag(s)".

    TIFF "offsets" could be spread in a spaghetti manner, that would be difficult to tackle. Lucky that in our discussion on "Save As TIFF", I don't deal with private/custom stuff.

    Brenker
    Last edited by Brenker; Jul 21st, 2018 at 03:42 PM.

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

    Re: Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF?

    Quote Originally Posted by Brenker View Post
    I can't recall what is/are being dropped by GDIplus - it could well be the "private tag(s)".
    Only way to know is to test, but any future update of GDI+ could introduce new "drops". Similar with PNG. Simply adding a new metadata tag to GDI+ PNG via GdipSetPropertyItem doesn't guarantee it will be persisted if the image is saved via GDI+

    FYI: For PNG I did post a routine in the codebank to append user-defined metadata to PNGs. Maybe someone would want to tackle something similar for TIF?
    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}

  14. #14

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    362

    Re: Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF?

    LaVolpe,

    I basically don't use GDIplus except sometimes for convenience, reading or writing PNG I use my own class. It is because of this, I have kind of a full control about PNG files, down to the byte, and this enables me doing a lot of things that using GDIplus doesn't do or difficult to do.

    In "Win10 1803 - Any VB6 impacts to report?" thread, posting #8, you see a loaded PNG of 4128 x 2960 pixels. The file was from a programmer friend. Its original has 961 chunk tags, because the coder is using libPNG which enforces a IDAT split size at 8192 bytes, ending up 959 IDAT chunks in a single PNG file. Since there is a "PNG Chunk Tag Operations" menu in my PNGsupp program, so I made use of it and consolidated the individual IDAT chunks into a single IDAT chunk, memory RAM permitting (I check it first). The result is, my "PNG Chunk Tags Listing" screen now shows the same file with only 3 chunks, 3 v 961. (Screenshot of "PNG Chunk Tag Operations" screen is appended below, there are a few other operations available, e.g. "Reset IDAT Split Size", "Import/Export/Delete Chunk Tag".)

    There had been a funny encounter of PropertyTagGps.... stuff of GDIplus a few years ago. I already had my code on JPEG EXIF lising and JPEG markers listing, but I wanted to try out GDIPlus, so I used the GPS part of EXIF as an experiment. As you know, EXIF GPS Endianness may be "II" or "MM", but for GDIplus we should just process on "II" basis - as this is not specified/explained on MSDN, I learnt it in a hard way when I tried to figure out why I got some figures discrepant (because I still went according to "II" or "MM").

    Brenker

    Edited:

    I use GDIplus in Animated PNG, e.g. I even use AlphaBlend as an alternative in processing DisposalOp. I also use GDIplus a lot in image edit, e.g. antialiased paint brush, bezier curve, rotated oval shade, etc.
    Attached Images Attached Images  
    Last edited by Brenker; Jul 23rd, 2018 at 11:31 AM.

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

    Re: Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF?

    FYI: With GDI+ v1.1 came a couple more encoder options, but can't find documentation on how to use them and for which image formats that apply:

    EncoderColorSpace: Is this for JPG, PNG, TIF? What are valid parameter values?
    - {AE7A62A0-EE2C-49D8-9D07-1BA8A927596E}
    EncoderSaveAsCMYK: Probably for JPG, but what are valid parameter values?
    - {A219BBC9-0A9D-4005-A3EE-3A421B8BB06C}

    And here are two new encoder enum values with v1.1
    EncoderValueColorTypeGray = 24
    EncoderValueColorTypeRGB = 25
    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}

  16. #16

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    362

    Re: Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF?

    LaVolpe,

    Thanks for the info.

    Yes it is vague about "ColorSpace". "ColorSpace" is loosely referred by people, e.g. when I refer the color model in the original image of a file, I call it "ColorModel"; and when I refer the color model in ICC in that file, I call it "ColorSpace".

    I allow user to load a CMYK file, superimpose some text or image on it, then save the image back to a CMYK file, changing only the affected pixels (unaffected pixels remain the same as the original CMYK). In this case, I just set PixelFormat32bppCMYK.

    Frankly I don't plunge into using whatever newest available indiscriminately, in order to safeguard users who are still on an older system.

    EncoderValueColorTypeGray = 24
    EncoderValueColorTypeRGB = 25
    Would that be a nice coincidence, the above are pertinent to our "Save as 8-BPP grayscale" discussion? I will try it out later on.


    Brenker

  17. #17

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    362

    Re: Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF?

    LaVolpe,

    In my last posting, I said
    Would that be a nice coincidence, the above are pertinent to our "Save as 8-BPP grayscale" discussion? I will try it out later on.
    Just to let you know that I've now tried it on a grayscale JPG, no luck, the returned image is still 24-BPP. I passed an 8-BPP DIB containing the grayscale image, and added the following code block in my GDIplus subroutine:

    Code:
        mColorType = EncoderValueColorTypeGray           'Win 7 onwards only
        With uEncParams.Parameter(1)                         '....(0) is used for qulity
             .NumberOfValues = 1
             .Type = [EncoderParameterValueTypeLong]
             .GUID = DEFINE_GUID(EncoderSaveFlag)
             .value = VarPtr(mColorType)
        End With
    Brenker

  18. #18

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    362

    Re: Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF?

    LaVolpe,

    Here is my test result of the "Save As 8-BPP Grayscale TIFF" experiment that you put forward the day before.

    The thumbnail image in the screenshot of "TIFF Tag Listing" is after the first round of the processes, i.e. passed an 8-BPP grayscale DIB in calling GDIplus.

    After the above said first round, I removed tag 320 (ColorMap). I found that the image was still okay after the removal of ColorMap. However, Windows Explorer no longer recognizes the file, as reflected by its thumbnail (not showing our image).

    Following what is said in the above paragraph, I proceeded to change the value of tag 262 (PhotoMetricInterpretation) from 3 to 1 (at byte position 162515, 1-based). Windows Explorer then recognizes the file again. Alas, the final product is not of an acceptable quailty.

    Brenker
    Attached Images Attached Images   

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

    Re: Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF?

    Gotta stress that the 8-bit palette associated with the image, after grayscaling it, must be sorted. When I failed to sort the palette, I got unexpected results also. You could verify that if you parse out the ColorMap.

    P.S. Of those v1.1 new encoder options, I did find that EncoderSaveAsCMYK applies to TIFF and only 1 parameter value recognized is 1.
    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}

  20. #20

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    362

    Re: Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF?

    LaVolpe,

    I now found that (i) value of tag 262 is automatically changed back to "3" by the system; and (ii) the final image looked so different because it is just a negative (if I invert it, it looks okay). I guess our experiment has gone wild, it is not safe to pursue along this line. But it is an interesting experiment.

    Brenker
    Last edited by Brenker; Jul 22nd, 2018 at 03:31 PM. Reason: To correct name

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

    Re: Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF?

    Not sure how you say it's not safe. I've done it dozens of times already and get exactly what I expect. Nothing can be automatically set back to "3" by the system. If you are saying that GDI+ will convert the "1" to a 3 and add a color table, then that is what GDI+ does and I have not tested that at all. But the question, I thought was how to save a TIFF as true grayscale and the solution is there: manually modify the TIFF. GDI+ won't do it on its own.
    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}

  22. #22

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    362

    Re: Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF?

    The physical file remains of the changed value of "1" (examined by Hex Editor), but on retrieving the file to display image and getting a tag listing, the tag 262 entry remains "3".

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

    Re: Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF?

    Quote Originally Posted by Brenker View Post
    The physical file remains of the changed value of "1" (examined by Hex Editor), but on retrieving the file to display image and getting a tag listing, the tag 262 entry remains "3".
    If you are loading the image via GDI+, then that doesn't surprise me. I think that GDI+ needs to create a palette for its bitmap class if the image is grayscale and no palette exists. Probably does this for true grayscale PNG also. An image of less than 16 bits will always have a palette within GDI+. And if that is the case, then I can see where you would have trouble identifying the source as a true grayscale TIFF if tag 262 is rewritten internally by GDI+, without manually scanning the source.
    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}

  24. #24

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    362

    Re: Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF?

    Another discovery, for the same file I got two different images as per screenshot below: left side is by GDIplus (an inverted image), right side FreeImage.
    Attached Images Attached Images  

  25. #25

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    362

    Re: Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF?

    Until one day GDIplus updates itself, a smooth answer seems unlikely. With a big thank you to LaVolpe for such a bold and intuitive attempt/experiment, I close this thread.

    Brenker

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

    Re: [RESOLVED] Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF

    Just proof of concept. In the attached zip are:
    1. Source image: _Forest.bmp
    2. That source was converted to Grayscale, then the grayscale bitmap sent to GDI+ to be saved as a TIFF: sample2.tif
    3. The TIFF tweaked to make tag 262 = 1 and hiding tag 320 by rewriting its tag number to a private number. GDI+ does not see a tag 320: sampleMod2.tif
    - note: just didn't feel like whipping up code to remove the palette; just hid it instead.

    Here are the tags and values before and after tweaking them
    Code:
    --- Before (sample2.tif)
    Tag: 254 Value:  0 
    Tag: 256 Value:  256 
    Tag: 257 Value:  256 
    Tag: 258 Value:  8 
    Tag: 259 Value:  5 
    Tag: 262 Value:  3 
    Tag: 273 Value:  8 
    Tag: 277 Value:  1 
    Tag: 278 Value:  256 
    Tag: 279 Value:  45345 
    Tag: 282 Value:  45540 
    Tag: 283 Value:  45548 
    Tag: 296 Value:  2 
    Tag: 317 Value:  1 
    Tag: 320 Value:  45556 
    
    --- After (sampleMod2.tif)
    Tag: 254 Value:  0 
    Tag: 256 Value:  256 
    Tag: 257 Value:  256 
    Tag: 258 Value:  8 
    Tag: 259 Value:  5 
    Tag: 262 Value:  1 
    Tag: 273 Value:  8 
    Tag: 277 Value:  1 
    Tag: 278 Value:  256 
    Tag: 279 Value:  45345 
    Tag: 282 Value:  45540 
    Tag: 283 Value:  45548 
    Tag: 296 Value:  2 
    Tag: 317 Value:  1 
    Tag: 17998 Value:  45556
    Again, key points: Ensure GDI+ creates the grayscale bitmap using a sorted palette. Then pass that GDI+ bitmap for saving as TIFF. I get expected results every time in those cases.
    Attached Files Attached Files
    Last edited by LaVolpe; Jul 24th, 2018 at 05:35 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}

  27. #27

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    362

    Re: [RESOLVED] Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF

    LaVolpe,

    Thanks, I will follow up, and will revert.

    Regarding the grayscale, please be rest assured that the image in the 8-BPP grayscale DIB passed to GDIplus has been dithered from a sorted grayscale palette [RGB(0, 0, 0), RGB(1, 1, 1), .... RGB(255, 255, 255)].

    Brenker

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

    Re: [RESOLVED] Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF

    In my case, I create the bitmap using GdipCreateBitmapFromScan0, assign the palette, then transfer the grayscale pixels/indexes via GdipBitmapLockBits. I have experienced problems in the past if I assign a palette after the indexes are set. Here is an extract of the problem I faced with my Alpha Image Control:
    Problem: I have an issue that is very strange. I have a particular 8-bit BMP graphic I am trying to use on a form in my project, and I am using the latest version of your control with everything as default, I've changed nothing...

    The image appears GREAT on Windows XP, however when loaded on a Windows 7 PC, the image is distorted with a lot of extra black that shouldn't be there. See the attached pic for a side-by-side comparison.

    Solution: Ok, took a bit to figure it out. The issue is order of code. When I create a sourceless GDI+ image, I copy the bits from one handle to the other, then copy the palette. On Vista & earlier, no problem, but on Win7, a problem. So, by copying the palette first, then the image bits, problem goes away.
    It would be crazy, but is there any chance that the palette you give to GDI+ when creating a bitmap is being rewritten? If so, that means your pixel/indexes are rewritten too and could explain the loss of quality you are seeing when you remove tag 320? You can always test that by retrieving the palette from the GDI+ image, at any time, and iterating through its colors. Just a thought
    Code:
    Private Declare Function GdipGetImagePalette Lib "GdiPlus.dll" (ByVal pImage As Long, ByRef Palette As ColorPalette, ByVal pSize As Long) As Long
    Private Declare Function GdipGetImagePaletteSize Lib "GdiPlus.dll" (ByVal pImage As Long, ByRef pSize As Long) As Long
    Private Type ColorPalette            ' GDI+ palette object
       flags As Long
       Count As Long
       Entries(1 To 256) As Long
    End Type
    
    Function ImportRemotePalette(ImageHandle As Long) As Boolean
        ' extracts a bitmap's palette to our class palette
        If ImageHandle Then
            Dim pPalette As ColorPalette, p As Long
            Dim pSize As Long
            If GdipGetImagePaletteSize(ImageHandle, pSize) = 0& Then
                ImportRemotePalette = (GdipGetImagePalette(ImageHandle, pPalette, pSize) = 0&)
                ' debugging....
                For p = 1 To pPalette.Count
                    Debug.Print p, Hex(pPalette.Entries(p))
                Next
            End If
        End If
    
    End Function
    Edited: If you post your actual tiff files, uncompressed (before & after), I can take a look-see and maybe a second set of eyes can help pinpoint the problem?
    Last edited by LaVolpe; Jul 24th, 2018 at 06:04 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}

  29. #29

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    362

    Re: [RESOLVED] Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF

    LaVolpe,

    Re your
    ...... and could explain the loss of quality you are seeing when you remove tag 320?
    In my posting #18, I said
    After the above said first round, I removed tag 320 (ColorMap). I found that the image was still okay after the removal of ColorMap. However, Windows Explorer no longer recognizes the file, as reflected by its thumbnail (not showing our image).
    so the change of colors didn't occur after removing ColorMap (albeit Windows Explorer no longer recognized the file because it didn't show the image, as I mentioned).

    I've just taken a look of my code (see Remarks in next paragraph), I don't see any chance that my "mPalette.Entries" could be re-written in and after the process of GdipCreateBitmapFromScan0()

    Remarks: I already had an existing GDIplus "save 8-BPP" subroutine, it was just that for the subject experiment I blocked some code lines and added/modified a few other lines, e.g. mPalette.flags = PaletteFlagsHasAlpha remained the same, but mPalette.Entries(i).a were all 255 because TIFF wouldn't have a chance of some 0's.

    I was rather prudent in the test, (i) before I passed my 8-BPP grayscale DIB, it had been dithered with a sorted grayscale palette; and (ii) within the GDIplus subroutine, the grayscale palette was an ascending sorted one, naturally so.

    Actually it was not the qualiy of image that changed (see #24, same file by FreeImage), it was that the image was inverted (to a negative of the original) by GDIplus. If it occurs again, I will try to change tag 262 to "0", not "1" as an experiment.

    I will see what I can do.

    Brenker
    Last edited by Brenker; Jul 24th, 2018 at 06:41 PM.

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

    Re: [RESOLVED] Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF

    Regarding Windows not recognizing it when you removed tag 320, that makes perfect sense -- poorly formatted TIFF, tag 262=3 but not ColorMap. When you changed tag 262 to 1, and the image did not display correctly, thinking the only possible reason is that the image was not written with the color indexes in the proper grayscale order.

    Still would be good to see the TIFF, uncompressed. That will likely explain everything.
    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}

  31. #31

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    362

    Re: [RESOLVED] Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF

    LaVolpe,

    Attached 2 ZIPs contain 3 resultant TIFF files obtained at different stages, as indicated in their file names. TIFF images are uncompressed as you requested. Two ZIPs due to the site's size limit per ZIP.

    The final result is basically the same as that of last test.

    Below are some screenshots which should be self-explanatory.

    What is peculiar? While Windows Explorer doesn't display the TIFF file after the removal of ColorMap, FreeImage has no problem with it.

    What is interesting? The simple Hex Editor is also part of my program (PNGsupp) - you see that I actually have a lot of fun.

    Brenker
    Attached Images Attached Images    
    Attached Files Attached Files

  32. #32

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    362

    Re: [RESOLVED] Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF

    Owing to the site's limit on size and on No. of attachments, I have to (1) attach the ZIP for the source grayscale JPG separately and (2) append another screenshot showing the "come back" of PhotoMetricInterpretation = 3, despite the physical file has a "1" value.
    Attached Images Attached Images  
    Attached Files Attached Files
    Last edited by Brenker; Jul 24th, 2018 at 09:57 PM.

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

    Re: [RESOLVED] Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF

    @Brenker. Look more closely at your TIF files, specifically tag 262.

    You accidentally changed the tag's "Type" field not its "Value" field: Tag: 262 Type: 1 Value: 3
    When I corrected that, your image displayed properly: Tag: 262 Type: 3 Value: 1

    Thanx for giving us your tiff uncompressed. I was able to verify pixel data simply by looping through the data and PSet() to a picturebox. Also and just FYI. The image you showed us in post 32 above is your grayscale color inverted: Xor &HFFFFFF

    Edited: And last paragraph above makes perfect sense. Since the TYPE field was 1, not 3, for tag 262, it is an invalid field value: Type must be 3 (SHORT) for tag 262. GDI+ must have rejected the tag & defaulted it's value to zero. Tag 262 value of zero = WhiteIsZero; therefore, your image was color inverted. This was a good puzzle.
    Last edited by LaVolpe; Jul 25th, 2018 at 06:07 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}

  34. #34

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    362

    Re: [RESOLVED] Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF

    LaVolpe,

    You are right, in my posting #32, I red-circled "3" in Value entry; if I had moved my eyesight towards the left just a little bit, then I would have spotted that.

    This is laughable, while all attention was drawn to a sorted grayscale palette, it turned out that a slip of pen elsewhere in the last touch was the culprit. It shouldn't have happened, because the TIFF Tag Listing was written by myself, the Hex Editor was written by myself, so I should know every detail of them. However, goblin still got in - see the attached screenshot below, in my Hex Editor I came straight to the position directed by the "Pos" column of my TIFF Tag Listing, I saw a "03" value, then just changed it right away, whereas the other "03" entry a few bytes away should be the target.

    Great, your attempt is now proved to be a workable one and I can vouch that! Attached herewith is a ZIP containing "FinalProduct.tif".

    Brenker
    Attached Images Attached Images  
    Attached Files Attached Files
    Last edited by Brenker; Jul 25th, 2018 at 08:12 PM.

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

    Re: [RESOLVED] Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF

    Quote Originally Posted by Brenker View Post
    This is laughable, while all attention was drawn to a sorted grayscale palette, it turned out that a slip of pen elsewhere in the last touch was the culprit.
    Well, we did learn something in the process of troubleshooting... If we ever see a grayscale/BW image unintentionally color-inverted, we can pretty much go right to tag 262 as the first possible reason: either its value is zero or tag 262 may be otherwise invalid. Also re-learned that GDI+ can be pretty finicky when deciding which specifications it wants to enforce and when it can be a bit flexible. Even the TIFF specs suggests parsers accept byte, integer or long types even when a tag may specify a specific type.
    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}

  36. #36

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    362

    Re: [RESOLVED] Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF

    LaVolpe,

    Yes, I found that GDIplus can be as lovely as you like, but can also be very unforgiving at times.

    Having established the "work around", the first thing I will do is, in Grayscale ICC conversion (i) shake away FreeImage when converting a 16-bit TIFF to a 8-bit TIFF and (ii) switch from "via JPG" to "convert to 8-bit TIFF" when the source file is a 8-bit or a 16-bit PNG. I need to deal with "16-bit TIFF", "8-bit PNG" and "16-bit PNG", in order to have the image color modal matching ICC color space in the eye of GDIplus during grayscale ICC conversion. (Remarks: In ICC conversion, I can't use my normal subroutine if the source image is a grayscale, grayscale ICC is subject to a different set of rules, I found.) The only additional code I need is to programmatically reach the byte position of PhotoMetricInterpretation's Value field and change it to "01" (since I can't use a Hex Editor).

    Brenker

    Edited:
    In my normal subroutine, I let GDIplus read whatever BPP source into a 32 BPP DIB, then I have only
    Code:
        If mIsCMYK = False Then
             mSrcFormat = BM_xRGBQUADS
        Else
             mSrcFormat = BM_KYMCQUADS
        End If
        mDestFormat = BM_xRGBQUADS
    Edited 2:
    Just for info, I found that because I pass an 8-BPP grayscale DIB (dithered with a grayscale palette), I don't have to do anything extra regarding GDIplus palette, just keep the existing code line in the GDIplus subroutine
    Code:
     GetDIBColorTable(inDIB.hDC, 0, 256, mPalette.Entries(0))
    Edited 3:
    Just to crudely address the point raised in my posting #31, I said
    What is peculiar? While Windows Explorer doesn't display the TIFF file after the removal of ColorMap, FreeImage has no problem with it.
    FreeImage has embodied libTIFF, handling TIFF, 8-BPP or otherwise, in a different way vis-a-vis GDIplus.
    Last edited by Brenker; Jul 26th, 2018 at 07:37 AM.

  37. #37

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    362

    Re: [RESOLVED] Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF

    Conclusion of thread:

    Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF? The answer is "For TIFF, yes.", per LaVolpe's "work around" which entails the following:

    -- Pass an 8-BPP grayscale DIB which has been dithered with a 256-entry grayscale palette (not the palette obtained through Octree), or similar.

    -- Obtain ColorPalette256 in the GDIplus subroutine as you anyhow have to do.

    -- Modify the resulting TIFF by deleting bytes pertaining to ColorMap tag. This involves (i) reduce the tag count by one; (ii) if necessary, adjust the relevant offsets of the remaining tags which would be affected by the said deletion; and (iii) delete bytes of ColorMap tag.

    -- Change the value in Value field of PhotoMetricInterpretation from "3" to "1".

    This thread is satisfactorily concluded, and I thank LaVolpe once again.

    Brenker
    Last edited by Brenker; Jul 26th, 2018 at 10:21 PM. Reason: Change "Yes." to "For TIFF, yes."

  38. #38

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    362

    Re: [RESOLVED] Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF

    Further testings have now shown that the same "work around" mentioned in the previous posting is applicable to a 4-bit grayscale TIFF as well, not only 8-bit. Similar steps are required:

    -- Pass a 4-BPP grayscale DIB which has been dithered with a 16-entry grayscale palette.

    -- Obtain ColorPalette016 in the GDIplus subroutine that you anyhow have to do when you save a image to 4-BPP TIFF, i.e.
    Code:
    Private Type ColorPalette016
        flags As PaletteFlags
        count As Long
        Entries(0 To 15) As RGBQUAD  
    End Type
    -- Modify the resulting TIFF by deleting bytes pertaining to ColorMap tag (reduce tag count by 1; if necessary, adjust offsets of remaining tags; and remove ColorMap bytes).

    -- Change the value in Value field of PhotoMetricInterpretation from "3" to "1".

    The result is a 4-BPP Grayscale TIFF with PhotometricInterpretation = 1.

    What about 1-bit TIFF? You don't need to involve a "work around"; just pass a 1-BPP DIB as you would on saving a 1-BPP image - GDIplus would return a 1-BPP B/W TIFF and its ColormetricInterpretation = 0.
    Last edited by Brenker; Aug 8th, 2018 at 06:41 PM.

  39. #39

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    362

    Re: [RESOLVED] Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF

    This is an "epilogue".

    A thought popped up in my mind this morning: Can we dispense with the step "Obtain ColorPalette256/ColorPalette016 in the GDIplus subroutine ...."? My subsequent tests have given me an afformative answer. This means we don't have to call GetDIBColorTable, GdipCreateBitmapFromScan0, GdipBitmapLockBits and GdipSetImagePalette (i.e. none of these is required).

    Thus, the steps required are now shortened to:

    -- Pass an 8-BPP/4-BPP grayscale DIB which has been dithered with a 256-entry/16-entry grayscale palette.

    -- Modify the resulting TIFF by deleting bytes pertaining to ColorMap tag. This involves (i) reduce the tag count by one; (ii) if necessary, adjust the relevant offsets of some of the remaining tags which would be affected by the said deletion, if any; and (iii) delete bytes of ColorMap tag.

    -- Change the value in Value field of PhotoMetricInterpretation from "3" to "1".

    Brenker

  40. #40

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    362

    Re: [RESOLVED] Can GDIplus save grayscale JPEG &/or TIFF as 8-BPP grayscale JPEG/TIFF

    After an "epilogue" in the previous posting, we need an "addendum" still.

    There is a specific issue hitherto not addressed. When we extract a page from a multi-page TIFF, we don't pass an 8-BPP/4-BPP DIB; we call GdipImageGetFrameCount and GdipImageSelectActiveFrame instead. The returned TIFF file containing the extracted page will be of PhotometricInterpretation = 3, despite the original page in the multi-page file is of PhotometricInterpretation = 1. And, this time there is a significant difference comparing to all the previous postings - although the returned TIFF has PhotometricInterpretation = 3, there is no ColorMap in existence. Such weird arramgements of GDIplus'.

    In this case, the steps summarized in the previous posting are no longer applicable. To handle the above-said, we have to:

    -- Ascertain (i) whether the image pixels are of grayscale and (ii) whether the image BPP is either 8 or 4. (Please be reminded that a grayscale palette is such that its color values are at fixed intervals according to BPP. We can't reply on color count alone to ascertain its BPP.)

    -- If both the above (i) and (ii) are positive, then change the value in Value field of PhotometricInterpretation from "3" to "1".

    With this "Addendum", I believe the subject matter is now exhaustively covered.

    Brenker
    Last edited by Brenker; Aug 13th, 2018 at 06:22 PM.

Page 1 of 2 12 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