Results 1 to 14 of 14

Thread: [RESOLVED] Write a bordered text by GDIplus

  1. #1

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    373

    Resolved [RESOLVED] Write a bordered text by GDIplus

    This question is likely to be answered by LaVolpe, or someone who knows his potatoe and is really proficient in GDIplus text writing. Hence it is possible that without the pain of GDIplus declarations and constants we may still discuss/address the points arising.

    When we use GDIplus to write a text, we often engage a bounding box. and we may even transform the text by making certain calls supplying RECTF and nodes. We can have solid, outline or bordered texts, gradient ones too However, the question here does not concern these. The question is to explore whether without a bounding box and RECTF, we can draw a bordered text or not. On the web many said that GDIplus' bordered text writing is an "unmanaged" one.

    The following is a testing example. Using the code we can draw a solid text or an outline text without any problem. However, if we draw both to form a bordered text, then the problem would surface -- the outline may not always be enough to cover up the solid text at edges. This makes me wonder and raise the subject question. Or, have I omitted something?

    (Remarks: GdipGetPathWorldBoundsI is not called in the testing subroutine, this would not affect the result. Path warping calls are not made as no text transformation is involved).

    Code:
    Private Function Draw_Text_Testing(inDIB As clsDIB, ByVal inText As String) As Boolean
        Dim typRectF As RECTF
        Dim typRect As RECT
        Dim mFontStyle As fontStyle
        Dim hImg As Long
        Dim hFontFamily As Long
        Dim hStringFormat As Long
        Dim hPath As Long
        Dim hBrush As Long
        Dim hPen As Long
        Dim mFontName As String
        Dim mFontSize As Single
        Dim w As Long, h As Long
        Dim mText As String
        Dim mTextColor As Long
        Dim mBorderColor As Long
        Dim mBorderThickness As Single
        
        mText = "BB CC"      'Fixed, all upper case for testing
        mFontName = "Tiems New Roman"      'Selected font for testing
        mFontSize = 120               'Selected font size for testing
        mFontStyle = FontStyleBoldItalic     'Must be Bold and Italic
        
        w = inDIB.DIBWidth
        h = inDIB.DIBHeight
        
        If GdipCreateFontFamilyFromName(StrPtr(mFontName), 0&, hFontFamily) <> 0 Then
             GoTo earlyExit
        End If
        
        If GdipStringFormatGetGenericTypographic(hStringFormat) <> 0 Then
             GoTo earlyExit
        End If
    
          'Set StringAlignmentCenter to overcome, e.g. font "Cambria Math" which has
          'lot of void/space above and below text.
        GdipSetStringFormatLineAlign hStringFormat, StringAlignmentCenter
        
        If GdipCreatePath(FillModeWinding, hPath) <> 0 Then
             GoTo earlyExit
        End If
        
          'Use margin to avoid "left leg" clipping in first "A" when Times New Roman, font size 120,
          'Bold & Italic, with string "AAA"
          'Set height to overcome, e.g. font "Cambria Math" which has lot of void/space
          'above and below text.
        With typRectF
             .Left = 10
             .Top = 2
             .Width = w
             .Height = h
        End With
        
        If GdipAddPathString(hPath, StrPtr(mText), Len(mText), _
                hFontFamily, mFontStyle, mFontSize, typRectF, hStringFormat) <> 0 Then
             GoTo earlyExit
        End If
          
        mTextColor = RGB(255, 255, 0)
        mBorderColor = RGB(255, 0, 0)
        
        mBorderThickness = 2
        
        If GdipCreateFromHDC(inDIB.DIBhDC, hImg) <> 0 Then
             GoTo earlyExit
        End If
    
        GdipSetSmoothingMode hImg, SmoothingModeHighQuality
          'Wouldn't affect result
        'GdipSetInterpolationMode hImg, InterpolationModeHighQualityBicubic
        'GdipSetPixelOffsetMode hImg, PixelOffsetModeHighQuality
        GdipSetTextRenderingHint hImg, TextRenderingHintAntiAliasGridFit
    
        If GdipCreateSolidFill(ColorValue(mTextColor, 255), hBrush) = 0 Then
            GdipFillPath hImg, hBrush, hPath
            GdipDeleteBrush hBrush
        End If
             
        If GdipCreatePen1(ColorValue(mBorderColor, 255), mBorderThickness, UnitPixel, hPen) = 0 Then
            GdipSetPenMode hPen, PenAlignmentInset        'PenAlignmentCenter wouldn't help
            GdipDrawPath hImg, hPen, hPath
            GdipDeletePen hPen
        End If
        
        Draw_Text_Texting = True
        
    earlyExit:
        If hPath Then GdipDeletePath hPath
        If hStringFormat Then GdipDeleteStringFormat hStringFormat
        If hFontFamily Then GdipDeleteFontFamily hFontFamily
        If hImg Then GdipDeleteGraphics hImg
    End Function
    Attached Images Attached Images  

  2. #2

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    373

    Re: Write a bordered text by GDIplus

    For good order sake, to arrive at the character size shown, I should mention that there should have been a line immediately below the existing

    mFontSize = ....

    mFontSize = MulDiv(mFontSize, GetDeviceCaps(inDIB.hDC, LOGPIXELSY), 72)

    (The original intention of the said line is to bring the character size similar to that of the font size when GDI is used, not GDIplus)

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

    Re: Write a bordered text by GDIplus

    Out of curiosity, do you get the same results using an odd-sized pens, i.e., 1, 3, 5? Does this only occur with even-sized pens? I'm currently messing with other stuff else I'd play along. If not the same issue, maybe just offsetting the pen 1/2 pixel or setting the GDI+ pixel mode to PixelOffsetModeHalf? Guessing without playing.
    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}

  4. #4
    Fanatic Member
    Join Date
    Aug 2013
    Posts
    806

    Re: Write a bordered text by GDIplus

    If you can produce a sample project that demonstrates the problem, you're more likely to receive help. This is especially relevant for a complex API like GDI+, as the problem's as likely to appear in your function and constant declarations as in the actual code.

    GdipSetPenMode hPen, PenAlignmentInset 'PenAlignmentCenter wouldn't help
    The comment "PenAlignmentCenter wouldn't help" doesn't make sense. Inset vs Center alignment results in totally different pen behavior, and if you don't see different output between the two modes, there may be a problem with your Enum declaration.

    If you can share a before/after image with that line commented out (not changed - actually commented out or deleted to remove the possibility of an incorrect enum), it might help us track down the problem.
    Check out PhotoDemon, a pro-grade photo editor written completely in VB6. (Full source available at GitHub.)

  5. #5
    Fanatic Member
    Join Date
    Aug 2013
    Posts
    806

    Re: Write a bordered text by GDIplus

    Quote Originally Posted by LaVolpe View Post
    Out of curiosity, do you get the same results using an odd-sized pens, i.e., 1, 3, 5? Does this only occur with even-sized pens? I'm currently messing with other stuff else I'd play along. If not the same issue, maybe just offsetting the pen 1/2 pixel or setting the GDI+ pixel mode to PixelOffsetModeHalf? Guessing without playing.
    All good guesses IMO, but I don't see a problem after a quick round of testing. Inset pen does, however, cause noticeable fringing.

    (As always, the forum has re-encoded these images, so apologies for the quality aaargh)

    Name:  text_half_offset.png
Views: 466
Size:  8.8 KB

    Name:  text_half_offset_inset_pen.png
Views: 451
Size:  15.2 KB

    Name:  text_normal_offset.png
Views: 443
Size:  8.8 KB

    Name:  text_normal_offset_inset_pen.png
Views: 477
Size:  15.3 KB
    Check out PhotoDemon, a pro-grade photo editor written completely in VB6. (Full source available at GitHub.)

  6. #6

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    373

    Re: Write a bordered text by GDIplus

    Of course there must be a difference between PenAlignmentCenter and PenAlignmentInset, otherwise why they are there? Obviously what I meant is that the problem would still exist whichever is ueed, i.e. outline doesn't cover up solid text, the center issue of my question.

    My other tries even included getting rid of the diluted pixels at the edges, and restore them to the original base pixels, before applying the pen for outline.

    Out of the many variations I tried, the only time that the subject problem would go was to forgo SmoothingModeHighQuality. But then, antialiasing would go as well.

    Please don't always take a discussion/exploration as asking for help. Actually I am not. I can draw bordered text through other means alright, and warp it as well. I raise the question in a narrower context purely for discussion/exploration purposes, or one may just call it "to satisfy curiosity", given the specified Font, Font Size and Font Style (Bold and Italic).

    If an old hand in this area, such as LaVolpe can spot something from the code, it would be great. Otherwise it would just be fine for me.

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

    Re: Write a bordered text by GDIplus

    The only time I really played with GDI+ strings to paths was a project I created quite some time ago. But the program had a different scope similar to MS Word's WordArt: break the characters down to individual paths, warp the paths then recombine. I did not experience the issue you are describing, regardless of the pen size or font (assuming TTF). Could be due to the way I recombined the paths? FYI: Matter of coincidence, but that project I designed also used Times New Roman.

    However, I do not recall using these APIs in my project:
    GdipStringFormatGetGenericTypographic
    GdipSetTextRenderingHint

    You mentioned you weren't looking for any significant assistance, but if you give up then posting a sample project as Tanner suggested would be a good idea
    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
    373

    Re: Write a bordered text by GDIplus

    However, I do not recall using these APIs in my project:
    GdipStringFormatGetGenericTypographic
    GdipSetTextRenderingHint
    I will do a small project putting togeather relevant declarations/constants. I will come back.

    You mentioned your WordArt, indeed it is a great code. Incidentally a little while back I asked someone to send me a copy of it when I got stuck at some point doing my arch text (because I remembered you once wrote that), and I got my problem revolved right away. I haven't got a chance to say thank you for that.

    Whilst we are here, should you get a chance to touch it up a little bit still, perhaps you would like to call an "undo premultiplied" before saving the text image to PNG (to jack up the colors to fully opaque. while alpha values remain intact). Just a thought.

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

    Re: Write a bordered text by GDIplus

    Quote Originally Posted by Brenker View Post
    Whilst we are here, should you get a chance to touch it up a little bit still, perhaps you would like to call an "undo premultiplied" before saving the text image to PNG (to jack up the colors to fully opaque. while alpha values remain intact). Just a thought.
    Thanks for the bug report. But PSC was the only place I remember posting that code and with PSC being down (maybe forever), the code is nowhere to post it that I have control over (other than my hard drive). I never did finalize it to my satisfaction
    Last edited by LaVolpe; Jun 28th, 2015 at 01:43 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
    Fanatic Member
    Join Date
    Aug 2013
    Posts
    806

    Re: Write a bordered text by GDIplus

    Quote Originally Posted by Brenker View Post
    Of course there must be a difference between PenAlignmentCenter and PenAlignmentInset, otherwise why they are there? Obviously what I meant is that the problem would still exist whichever is ueed, i.e. outline doesn't cover up solid text, the center issue of my question.
    That's operating from the assumption that a single line of code is problematic. If you've tried toggling various settings without success, it's possible that multiple settings are interacting to cause the problem.

    If we can strip out ones we know are incorrect for the task you've described, we can start to reduce the number of potentially problematic spots.

    Quote Originally Posted by LaVolpe
    The only time I really played with GDI+ strings to paths was a project I created quite some time ago. But the program had a different scope similar to MS Word's WordArt: break the characters down to individual paths, warp the paths then recombine. I did not experience the issue you are describing, regardless of the pen size or font (assuming TTF). Could be due to the way I recombined the paths?
    I also have no trouble with filled/stroked GDI+ text on XP or Win 8, so I doubt the problem is endemic to GDI+.

    Another reason I'm leery of the problem being caused by text-specific settings: in the posted code, the same path object is used for both fill and outline. Because of this, it seems more likely that a path-specific, brush-specific, pen-specific or graphics-container-specific setting is at play, rather than the way the text is assembled (because GdipDrawPath should always trace the edges rendered by GdipFillPath, regardless of how the path is created, unless of course a setting like PenAlignmentInset is specified). My $0.02.
    Check out PhotoDemon, a pro-grade photo editor written completely in VB6. (Full source available at GitHub.)

  11. #11

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    373

    Re: Write a bordered text by GDIplus

    It turns out that the subroutine itself is perfectly fine; the problem occured after that only. After the subroutine there are two more steps I have to go through: (i) trim down the DIB to ged rid of some unused spaces and (ii) undo premultiplied, even if the opacity is set at 100%

    The Form is originally used for either a solid text or an outline text, in both cases I don't call an undo premultiplied subroutine which had been established since long, instead I just loop through the DIB and change those pixels which are non-white to the selected text color (no change needed for those equal to the selected text color), as directly using the text color is suposedly more accurate (than working back from alpha values). This is fine.

    After modifying the subroutine to write a bordered text, I forgot that the undo premultiplied subroutine is not in force (an alternative action is being taken instead, as described in last paragraph). For the bordered text I must call the undo premultiplied subroutine, because more than one text colors are involved now. Once I realize my carelessness, everything is in place again.

    So now I can consider the thread as closed. Thanks to LaVolpe and Tanner for participating in the discussion/exploration, and I apologize for my carelessness.
    Last edited by Brenker; Jun 28th, 2015 at 09:00 PM. Reason: Correct the word "BitBlt" to "render"

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

    Re: [RESOLVED] Write a bordered text by GDIplus

    Just out of curiosity, the inDIB object is a class/object that holds a 32 bpp DIB? You mentioned the DIB was transferred to the calling form? Via BitBlt? The reason I'm asking these questions is a test I performed way back & you may want to perform a similar test on your 32 bpp DIB...

    1. I loaded a PNG with GDI+ which I knew used the alpha channel and had plenty of alpha values > 0 and < 255 (not just simple transparency)
    2. I used GdipBitmapLockBits and retrieved the pixels in RGB+Alpha format (&H26200A)
    3. I looped thru them to ensure some of the alpha values were less than any of its R,G,B components
    4. Then I created a 32 bpp DIB section, selected it into a DC & had GDI+ render the PNG to that DIB
    5. I looped thru the bits of the DIB. Result: not one alpha value less than its R,G,B component. Premultiplied

    Maybe what you are seeing is an artifact of GDI+ rendering the DIB and modifying the R,G,B components (premultiplying them). If so, and you simply used BitBlt to transfer the DIB to form's hDC, then that could explain why the semi-transparent edges look the way they do.

    Ok, maybe none of the above applies. But GDI+ definitely appears to draw differently to 32 bpp DIBs
    Last edited by LaVolpe; Jun 28th, 2015 at 08:19 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}

  13. #13

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    373

    Re: [RESOLVED] Write a bordered text by GDIplus

    LaVolpe,

    I have re-written my immediate previous posting. When I came back from the earlier sample project, I found that the problem came back again in my original project. I then realized the cause must be subsequent to the subject subroutine. Once this is determined, the rest becomes easy, as explained in the revised text.

    In my case, each MDI child window holds a DIB. When the written text region is transferred to the said Form, it is an independant region until user fixes it to position. Before then, user may drag the text around in the Viewport. As and when user drags, a "blend in" operation is in action (text region DIB "blend in" with base DIB). Because there is a constant "blend in", user doesn't feel it is an independent region. The text region is visually enclosed by a rectangle of dotted lines. BTW, blend in a 32-BPP on a 32-BPP is interesting enough.

    Before user fixes the text to position, he can right click on the text region to revise the text and/or its settings any time.

    Since DIB of viewport always holds the original 32-BPP (if not 24-BPP), therefore, GdipBitmapLockBits as you mentioned becomes inevitable.
    Last edited by Brenker; Jun 28th, 2015 at 10:32 PM.

  14. #14

    Thread Starter
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    373

    Re: [RESOLVED] Write a bordered text by GDIplus

    LaVolpe,

    In my previous posting, I mentioned "....GdipBitmapLockBits as you mentioned becomes inevitable.". It occurs to me that perhaps I should clarify WHEN I would do it.

    Unless I need to load a PNG using my own PNG class (e.g. to store away 16-bit data when user wants to view/manipulate it), I would just call GDIplus. However, in order to obtain RGB before premultiplied, I still make a quick pass of PNG class in order to ascertain BitDepth and ColorType. On two conditions I would call GdipBitmapLockBits on loading PNG with GDIplus: (i) (the ones indicating it is 32-BPP) and (ii) BitDepth 8 and ColorType 3, with tRNS entry(ies) > 0 and < 255 (what I call "quasi alpha" -- there are some softwares doing this type of files for web use).

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