Announcement

Collapse
No announcement yet.

How to Create Dim Background Images?

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • How to Create Dim Background Images?

    In gbPrintPreview I've added the ability to show background images, sort of like in the picture below. However, images that are suitably dim/light and of the right size are hard to come by. So I'd like to convert normal colored images within my app.

    Does anyone know what the technique is to take a normal image and dim it, similar to what is in this picture? Using the Graphic Get Bits statement gives me access to each pixel, but I'm not clear on what the algorithm is to produce such pictures.



    gbPrintPreview can also do grayscale images, using code like this to modify the color in each pixel.
    Code:
    Color = 0.299*R + 0.587*G + 0.114*B  'or this: iColor = (R+G+B)/3
    But this approach can result in very harsh results - nothing as soft as I'd like to see.

    If anyone has insight on how to create the dim/light backgrounds (colored and grayscale), please let me know!

    I'll keep looking/experimenting, and post anything I find.

  • #2
    I don't have code but I would say it is an adjustment to the HSL (HSV) values, specifically a decrease in Saturation and an increase in Lightness.

    If you can find an algorithm for RGB to HSL you can tweak those two values then convert back to RGB.

    This may help: http://www.efg2.com/Lab/Graphics/Colors/HSV.htm
    Last edited by George Bleck; 4 Sep 2013, 02:33 PM.
    <b>George W. Bleck</b>
    <img src='http://www.blecktech.com/myemail.gif'>

    Comment


    • #3
      Well, I looked last night and didn't find much. But now, just after posting, I ran across some code that gives these results:



      Code:
      'Compilable Example:
      'from here:  http://www.pvladov.com/2012/09/make-color-lighter-or-darker.html
      #Compile Exe
      #Dim All
      %Unicode=1
      #Include "Win32API.inc"
      #Resource Bitmap cowgirl "cowgirl.bmp"
      Global hDlg As Dword, hBMP As Dword
      %ID_Graphic1 = 500
      %ID_Graphic2 = 501
      
      Function PBMain() As Long
         Dialog New Pixels, 0, "Lighten Image",600,300,250,150, %WS_SysMenu, 0 To hDlg
         Control Add Button, hDlg, 100, "Lighten", 10,10,50,20
         Control Add Graphic, hDlg, %ID_Graphic1,"", 10,40,100,100, %WS_Visible ' Or %SS_Sunken
         Control Add Graphic, hDlg, %ID_Graphic2,"", 130,40,100,100, %WS_Visible 'Or %SS_Sunken
         Graphic Attach hDlg, %ID_Graphic1 : Graphic Color %Black,%White : Graphic Clear
         Graphic Render "cowgirl", (0,0)-(99,99)
         Dialog Show Modal hDlg Call DlgProc
      End Function
      
      CallBack Function DlgProc() As Long
         If Cb.Msg = %WM_Command And Cb.Ctl = 100 Then GrayScale
      End Function
      
      Sub GrayScale   'uses Long pointer/CVL solution
         Local w As Long, h As Long, p As Long Ptr, i As Long
         Local iColor As Long, R,G,B As Single, bmp$
         Local correctionfactor As Single
      
         'get the string from ID_Graphic1
         Graphic Attach hDlg, %ID_Graphic1
         Graphic Get Bits To bmp$
      
         'get width/height of image
         w = Cvl(bmp$,1)
         h = Cvl(bmp$,5)
         p = StrPtr(bmp$)+8    'position of starting position for bits in string
      
         'get string position of coordinates and modify the string at that position
         correctionfactor = 0.7
         For i = 1 To w*h
            iColor = @p                           'result is a BGR color value 0-R-G-B
            B = iColor Mod 256                    'or this: iColor AND &HFF&
            G = (iColor\256) Mod 256              'or this: (iColor AND &HFF00&) \ &H100
            R = (iColor\256\256) Mod 256          'or this: (iColor AND &HFF0000&) \ &H10000&
            If (correctionFactor < 0) Then
               R *= (1+correctionFactor)
               G *= (1+correctionFactor)
               B *= (1+correctionFactor)
            Else
               R = (255 - R) * correctionFactor + R
               G = (255 - G) * correctionFactor + G
               B = (255 - B) * correctionFactor + B
            End If
            @p = Bgr(R,G,B)           'modify string at that position
            Incr p
         Next i
      
         'put the modified string into ID_Graphic2
         Graphic Attach hDlg, %ID_Graphic2
         Graphic Set Bits bmp$
      End Sub
      Last edited by Gary Beene; 6 Sep 2013, 09:26 AM. Reason: code correction per Dave's post below

      Comment


      • #4
        George,
        Thanks for the comments. The code I just posted works entirely with RGB, so the conversion to HSB might be necessary. I've only played with it a few minutes, so I'll test it some more to see what I can do with it.

        If it fails to live up to the early promised, I'll go check out the link you gave.

        Comment


        • #5
          Using that algorithm and applying gray scale seems to work well, too.




          Code:
          'Compilable Example:
          'from here:  http://www.pvladov.com/2012/09/make-color-lighter-or-darker.html
          #Compile Exe
          #Dim All
          %Unicode=1
          #Include "Win32API.inc"
          #Resource Bitmap cowgirl "cowgirl.bmp"
          Global hDlg As Dword, hBMP As Dword
          %ID_Graphic1 = 500
          %ID_Graphic2 = 501
          
          Function PBMain() As Long
             Dialog New Pixels, 0, "Lighten+Grayscale Image",600,300,250,150, %WS_SysMenu, 0 To hDlg
             Control Add Button, hDlg, 100, "Lighten+Grayscale", 10,10,150,20
             Control Add Graphic, hDlg, %ID_Graphic1,"", 10,40,100,100, %WS_Visible ' Or %SS_Sunken
             Control Add Graphic, hDlg, %ID_Graphic2,"", 130,40,100,100, %WS_Visible 'Or %SS_Sunken
             Graphic Attach hDlg, %ID_Graphic1 : Graphic Color %Black,%White : Graphic Clear
             Graphic Render "cowgirl", (0,0)-(99,99)
             Dialog Show Modal hDlg Call DlgProc
          End Function
          
          CallBack Function DlgProc() As Long
             If Cb.Msg = %WM_Command And Cb.Ctl = 100 Then GrayScale
          End Function
          
          Sub GrayScale   'uses Long pointer/CVL solution
             Local w As Long, h As Long, p As Long Ptr, i As Long
             Local iColor As Long, R,G,B As Single, bmp$
             Local correctionfactor As Single
          
             'get the string from ID_Graphic1
             Graphic Attach hDlg, %ID_Graphic1
             Graphic Get Bits To bmp$
          
             'get width/height of image
             w = Cvl(bmp$,1)
             h = Cvl(bmp$,5)
             p = StrPtr(bmp$)+8    'position of starting position for bits in string
          
             'get string position of coordinates and modify the string at that position
             correctionfactor = 0.7
             For i = 1 To w*h
                iColor = @p                           'result is a BGR color value 0-R-G-B
                B = iColor Mod 256                    'or this: iColor AND &HFF&
                G = (iColor\256) Mod 256              'or this: (iColor AND &HFF00&) \ &H100
                R = (iColor\256\256) Mod 256          'or this: (iColor AND &HFF0000&) \ &H10000&
          
                'lighten/darken
                If (correctionFactor < 0) Then
                   correctionFactor = 1 + correctionFactor
                   R *= correctionFactor
                   G *= correctionFactor
                   B *= correctionFactor
                Else
                   R = (255 - R) * correctionFactor + R
                   G = (255 - G) * correctionFactor + G
                   B = (255 - B) * correctionFactor + B
                End If
          '      @p = Bgr(R,G,B)           'modify string at that position
          
                'grayscale
                iColor = 0.299*R + 0.587*G + 0.114*B
                @p = Bgr(iColor, iColor, iColor)
          
                Incr p
             Next i
          
             'put the modified string into ID_Graphic2
             Graphic Attach hDlg, %ID_Graphic2
             Graphic Set Bits bmp$
          End Sub

          Comment


          • #6
            Side by side images:



            Code:
            'Compilable Example:
            'from here:  http://www.pvladov.com/2012/09/make-color-lighter-or-darker.html
            #Compile Exe
            #Dim All
            %Unicode=1
            #Include "Win32API.inc"
            #Resource Bitmap cowgirl "cowgirl.bmp"
            Global hDlg As Dword, hBMP As Dword
            %ID_Graphic1 = 500
            %ID_Graphic2 = 501
            %ID_Graphic3 = 502
            
            Function PBMain() As Long
               Dialog New Pixels, 0, "Lighten+Grayscale Image",600,300,375,150, %WS_SysMenu, 0 To hDlg
               Control Add Button, hDlg, 100, "Lighten+Grayscale", 10,10,150,20
               Control Add Graphic, hDlg, %ID_Graphic1,"", 10,40,100,100, %WS_Visible ' Or %SS_Sunken
               Control Add Graphic, hDlg, %ID_Graphic2,"", 130,40,100,100, %WS_Visible 'Or %SS_Sunken
               Control Add Graphic, hDlg, %ID_Graphic3,"", 250,40,100,100, %WS_Visible 'Or %SS_Sunken
               Graphic Attach hDlg, %ID_Graphic1 : Graphic Color %Black,%White : Graphic Clear
               Graphic Render "cowgirl", (0,0)-(99,99)
               Dialog Show Modal hDlg Call DlgProc
            End Function
            
            CallBack Function DlgProc() As Long
               If Cb.Msg = %WM_Command And Cb.Ctl = 100 Then GrayScale
            End Function
            
            Sub GrayScale   'uses Long pointer/CVL solution
               Local w As Long, h As Long, p,p2 As Long Ptr, i As Long
               Local iColor As Long, R,G,B As Single, bmp$, bmp2$
               Local correctionfactor As Single
            
               'get the string from ID_Graphic1
               Graphic Attach hDlg, %ID_Graphic1
               Graphic Get Bits To bmp$
            
               'get width/height of image
               w = Cvl(bmp$,1)
               h = Cvl(bmp$,5)
               bmp2$ = bmp$
               p = StrPtr(bmp$)+8    'position of starting position for bits in string
               p2 = StrPtr(bmp2$)+8    'position of starting position for bits in string
            
               'get string position of coordinates and modify the string at that position
               correctionfactor = 0.7
               For i = 1 To w*h
                  iColor = @p                           'result is a BGR color value 0-R-G-B
                  B = iColor Mod 256                    'or this: iColor AND &HFF&
                  G = (iColor\256) Mod 256              'or this: (iColor AND &HFF00&) \ &H100
                  R = (iColor\256\256) Mod 256          'or this: (iColor AND &HFF0000&) \ &H10000&
            
                  'lighten/darken
                  If (correctionFactor < 0) Then
                     correctionFactor = 1 + correctionFactor
                     R *= correctionFactor
                     G *= correctionFactor
                     B *= correctionFactor
                  Else
                     R = (255 - R) * correctionFactor + R
                     G = (255 - G) * correctionFactor + G
                     B = (255 - B) * correctionFactor + B
                  End If
                  @p = Bgr(R,G,B)           'modify string at that position
            
                  'grayscale
                  iColor = 0.299*R + 0.587*G + 0.114*B
                  @p2 = Bgr(iColor, iColor, iColor)
            
                  Incr p : Incr p2
               Next i
            
               'put the modified string into ID_Graphic2
               Graphic Attach hDlg, %ID_Graphic2 : Graphic Set Bits bmp$
               Graphic Attach hDlg, %ID_Graphic3 : Graphic Set Bits bmp2$
            End Sub

            Comment


            • #7
              Hey George,
              If you can find an algorithm for RGB to HSL...
              The link you posted has conversion code for both directions.

              What I posted above is hardly the final/best answer, so I'll take a closer look at the link you gave.

              Comment


              • #8
                Gary,

                I have written some image filters and I find that of the three colors (RGB), the Green should be treated a little differently.

                Treat the Red and Blue parts the same (divide by same number) or close to it. The green not only provides part of the tint of the color, but it appears green has the greatest effect on the lightness of the color. By using a different value for dividing the green, when lightening you can have better control of the overall effect.

                To do some testing, use the same division value for the red and blue. Then experiment with different values for the green until you get the optimal look you want. Then go back and tweak the division numbers for the red and blue. The red has a slightly greater effect on lightness than blue, but not a lot.

                Experiment with different values to create different filters.

                Here is some image filter code from a code sample that comes with my GUI library, using pointers to the pixels. It is not directly portable to DDT, but the part where it manipulates the RBG values may be useful to you. In particular notice the tinting filters, which lighten the image and also add a slight color tint (imagine grayscaled and then tinted):

                Code:
                ' this is the format for 32 bit RGB pixels
                TYPE EZ_RGB32
                    B   AS BYTE
                    G   AS BYTE
                    R   AS BYTE
                    Reserved AS BYTE
                END TYPE
                                                ' Best      Good        Low     Poor
                %GreenShift       =   4&        ' 4         8           8       16
                %RedShift       =     16&        ' 4         8           16      16
                %BlueShift       =    16&        ' 4         8           16      32
                SUB UseFilterOnBitmap(BYVAL Mode&)
                    LOCAL CW&, CH&, FirstPixel&, YB&, X&,Y&,PY&, V&, VT&
                    LOCAL P AS EZ_RGB32 PTR, BitMask?, BitMul?
                    EZ_GetCanvasSize "Form1", 100, CW&, CH&
                    EZ_StartDraw "Form1", 100, CW&, CH&, ""
                    ' copt buffer 2 to buffer 1 to get original to work with
                    EZ_CCopyBuffer 2,1,0
                    FirstPixel& = EZ_StartDrawByPtr("Form1", 100, 0)
                    IF FirstPixel&<>0 THEN
                        YB&=CW&*4
                        FOR Y&=0 TO (CH&-1)
                            PY&=FirstPixel&+(Y&*YB&)
                            FOR X&=0 TO (CW&-1)
                                P=PY&+(X&*4)
                                BitMask?=240
                                BitMul?=1
                                SELECT CASE Mode&
                                    CASE 1
                                        @P.R=(@P.R AND BitMask?)*BitMul?
                                        @P.B=0
                                        @P.G=0
                                    CASE 2
                                        @P.B=(@P.B AND BitMask?)*BitMul?
                                        @P.G=0
                                        @P.R=0
                                    CASE 3
                                        @P.G=(@P.G AND BitMask?)*BitMul?
                                        @P.R=0
                                        @P.B=0
                                    CASE 4
                                        ' high 4 bits
                                        @[email protected] AND 240
                                        @[email protected] AND 240
                                        @[email protected] AND 240
                                    CASE 5
                                        ' low 4 bits
                                        @P.R=((@P.R AND 15)*16)
                                        @P.G=((@P.G AND 15)*16)
                                        @P.B=((@P.B AND 15)*16)
                                    CASE 6
                                        ' 18 bit color shows little or no loss
                                        @P.R=0
                                        @P.G=0
                                        @P.B=(@P.B\%BlueShift)*%BlueShift
                                    CASE 7
                                        ' 18 bit color shows little or no loss
                                        @P.R=0
                                        @P.G=(@P.G\%GreenShift)*%GreenShift
                                        @P.B=0
                                    CASE 8
                                        ' GrayScale
                                        V&=(@[email protected][email protected][email protected][email protected][email protected])\6
                                        ' V&=(V&\2)*2
                                        @P.R=V&
                                        @P.G=V&
                                        @P.B=V&
                                    CASE 9
                                        ' Red Tinted
                                        V&=(@[email protected][email protected])\3
                                        @P.G=V&
                                        @P.B=V&
                                        V&=V&+164:IF V&>255 THEN V&=255
                                        @P.R=V&
                                    CASE 11
                                        ' Blue Tinted
                                        V&=(@[email protected][email protected])\3
                                        @P.G=V&
                                        @P.R=V&
                                        V&=V&+128:IF V&>255 THEN V&=255
                                        @P.B=V&
                                    CASE 10
                                        ' Green Tinted
                                        V&=(@[email protected][email protected])\3
                                        @P.R=V&
                                        @P.B=V&
                                        V&=V&+80:IF V&>255 THEN V&=255
                                        @P.G=V&
                                    CASE ELSE
                                END SELECT
                            NEXT X&
                        NEXT Y&
                    END IF
                    EZ_EndDrawByPtr
                    EZ_EndDraw
                END SUB
                I use the BGRA structure at the top of the code to access the the pixels. It should be easy to see what I am doing with each color part (R,G,B) in the code. The code assumes 32 bit DIB format.
                Last edited by Chris Boss; 4 Sep 2013, 03:11 PM.
                Chris Boss
                Computer Workshop
                Developer of "EZGUI"
                http://cwsof.com
                http://twitter.com/EZGUIProGuy

                Comment


                • #9
                  Hi Chris(B)!
                  Here's the grayscale code I posted vs the greyscale part of what you just posted. They're pretty similar.
                  Code:
                        iColor = 0.299*R + 0.587*G + 0.114*B   'Beene
                        iColor = 0.330*R + 0.500*G + 0.160*B   'ChrisBoss
                  When I use compares images with the two, my eyes can't see any difference.

                  But for the code that lightens the image, I posted this:
                  Code:
                           R = (255 - R) * correctionFactor + R
                           G = (255 - G) * correctionFactor + G
                           B = (255 - B) * correctionFactor + B
                  Is there an equivalent example in what you gave, or were you just giving me a general suggestion on handling RGB and that I should experiment to generate equivalent results?

                  And, of course, I do appreciate the response. I work only occasionally with images and have even more rarely worked with filtering.
                  Last edited by Gary Beene; 4 Sep 2013, 03:51 PM.

                  Comment


                  • #10
                    The ratios I use actually work quite well. My math is integer based, so i didn't have as much wiggle room for slightly different percentages, but it worked well.

                    The key is that the total of the percentages for the three colors should add up to about 1 (yours is .299 + .587 + .114 = 1). What ever you experiment with the three together should equal 1.

                    Mine more accurately would come out to:

                    iColor = 0.33333*R + 0.5*G + 0.16666*B ' to five decimals

                    which would equal .99999 , which is just about 1.

                    Make sure all three equal about 1 together, but play with changing the percentages.

                    The current percentages come close to the actual effect each color has on the brightness of the color. Green has the greatest effect. Red the second greatest effect and blue the least.

                    The values used have a lot more to do with what desire for a specific picture, rather than a universal ratio. Converting to grayscale loses a lot of the original, so one must tweak the image to produce the effect you want. Don't test with bland photos. Use different photos which highlight different colors.

                    Here are some different ratios to try:

                    Natural look:

                    iColor = 0.33333*R + 0.5*G + 0.16666*B

                    Balanced:

                    iColor = 0.33333*R + 0.33333*G + 0.33333*B

                    Highlight Red:

                    iColor = 0.5*R + 0.33333*G + 0.16666*B

                    Highlight Blue:

                    iColor = 0.25*R + 0.25*G + 0.5*B

                    The key is the effect you want to produce. Certain colors make a color image stand out, but when converting to gray scale one may lose that effect. By tweaking the ratios until you produce a similar effect, but with gray scale you can get better results, but sadly there is no universal value which works with all pictures.

                    You either manually tweak individual images (let user do this) or write a routine with runs through all the pixels testing colors and then calculate the best ratio based on the colors used.

                    Here is an example where I play with different ratios:

                    Chris Boss
                    Computer Workshop
                    Developer of "EZGUI"
                    http://cwsof.com
                    http://twitter.com/EZGUIProGuy

                    Comment


                    • #11
                      It resricts the choice of background colors, but sometimes the graphic mixmodes can be usefull here.
                      Note that the mixmodes are bitwise operations, and so the background color should best include a series of lower bits,
                      so 63 instead of 64.

                      Arie Verheul

                      Code:
                        
                          Graphic Color %White,RGB(63,255,127)
                          Graphic Clear
                          Graphic Copy hBmp,0,%Mix_MergeSrc

                      Comment


                      • #12
                        Hello Arie!
                        Thanks for the post, but I'm afraid I don't understand the benefits of doing what you suggest. Could you expand on your statements a bit? Thanks!

                        Comment


                        • #13
                          Excuse me if i was not clear enough, but it is just quite simple. It takes no more code than is shown above.
                          Attach to the graphic target, set a suitable background color, and draw the image using a mixmode. Just try it.

                          MergeSrc means that the image color is OR-red with the background color.
                          By selecting a background color which contains a series of consecutive lower bits, the lower bits of the image color are in fact
                          replaced with those of the background color, while the higher bits remain untouched and produce a dim image.
                          It only works with a limited number of background colors and the result is simple and may or may not be suitable for your purpose.
                          On the other hand the operation is very simple too.

                          Arie

                          Comment


                          • #14
                            Here's a version of Gary's code that tests the %Mix_MergeSrc effect that Arie described (for a just one background color)..
                            Code:
                            #Compile Exe
                            #Dim All
                            %Unicode=1
                            #Include "Win32API.inc"
                            #Resource Bitmap cowgirl "cowgirl.bmp"
                            Global hDlg As Dword, hBMP As Dword
                            %ID_Graphic1  = 500
                            %ID_Graphic2  = 501
                            %ID_Graphic3  = 502
                            %ID_Graphic4  = 503
                            %IDC_TEXTBOX  = 1001
                            %IDC_UPDOWN   = 1002
                            %IDC_TEXTBOX2 = 1003
                            %IDC_LABEL1   = 1004
                             
                            Function PBMain() As Long
                              Dialog New Pixels, 0, "Lighten+Grayscale Image w/ Arrow Keys", 600, 300, 485, 150, %WS_SysMenu, 0 To hDlg
                                Control Add Button, hDlg, 100, "Lighten+Grayscale", 10, 10, 150, 20
                                Control Add Graphic, hDlg, %ID_Graphic1, "",  10, 40, 100, 100, %WS_Visible
                                Control Add Graphic, hDlg, %ID_Graphic2, "", 130, 40, 100, 100, %WS_Visible
                                Control Add Graphic, hDlg, %ID_Graphic3, "", 250, 40, 100, 100, %WS_Visible
                                Control Add Graphic, hDlg, %ID_Graphic4, "", 370, 40, 100, 100, %WS_Visible
                                Graphic Attach hDlg, %ID_Graphic1 : Graphic Color %Black,%White : Graphic Clear
                                Graphic Render "cowgirl", (0,0)-(99,99)
                                Control Add TextBox, hDlg, %IDC_TEXTBOX, "", 175, 10, 45, 21
                                Control Add "msctls_updown32", hDlg, %IDC_UPDOWN, "msctls_updown32_1", 220, 10, 15, 21, _
                                  %WS_Child Or %WS_Visible Or %UDS_AUTOBUDDY Or %UDS_ALIGNRIGHT Or %UDS_SETBUDDYINT Or %UDS_ARROWKEYS
                                  ' Set UpDown control range
                                Control Send hDlg, %IDC_UPDOWN, %UDM_SETRANGE, 0, Mak(Long, 99, -99)   ' Max, min
                                  ' Set current (start) position
                                Control Send hDlg, %IDC_UPDOWN, %UDM_SETPOS, 0, 70
                                 Dim Uda(1) As UDACCEL    ' Uda() holds the (accelerator) increment values for the updown control. Minimum two.
                                 Uda(0).nSec = 0          ' From 0-5 secs,
                                 Uda(0).nInc = 1         ' control increments by 1      ' avoid (default) acceleration
                                 Uda(1).nSec = 5          ' After 5 secs,
                                 Uda(1).nInc = 1         ' control increments by 1      '   "       "          "
                                Control Send hDlg, %IDC_UPDOWN, %UDM_SETACCEL, 2, VarPtr(Uda(0))
                                Control Set Focus hDlg, %IDC_TEXTBOX
                                Control Add TextBox, hDlg, %IDC_TEXTBOX2, " ", 305, 10, 50, 20
                              Control Add Label,   hDlg, %IDC_LABEL1, "CF", 264, 13, 42, 15
                              Dialog Show Modal hDlg Call DlgProc
                            End Function
                             
                            CallBack Function DlgProc() As Long
                              Select Case As Long Cb.Msg
                                Case %WM_InitDialog : Dialog Post Cb.Hndl, %WM_APP + 1000, 0, 0  ' Test %Mix-MergeSrc
                                Case %WM_App + 1000
                                 Local hBmp As Dword
                                  Graphic Attach Cb.Hndl, %ID_Graphic4 : Graphic Color %White, RGB(63,255,127) : Graphic Clear
                                  Graphic Bitmap Load "cowgirl", 100, 100 To hBmp
                                  Graphic Copy hBmp, 0, %Mix_MergeSrc
                                  Graphic Attach hBmp, 0 : Graphic Bitmap End
                                  Graphic Attach Cb.Hndl, %ID_Graphic1 : Graphic Color %Black,%White
                                Case %WM_Command 
                                  Select Case As Long Cb.Ctl
                                    Case 100 : If Cb.CtlMsg = %BN_Clicked Then GrayScale : Control Set Focus hDlg, %IDC_TEXTBOX
                                    Case %IDC_TextBox : If Cb.CtlMsg = %EN_Change Then Control Send hDlg, 100, %BM_Click, 0, 0
                                  End Select
                              End Select
                            End Function
                             
                            Sub GrayScale   'uses Long pointer/CVL solution
                              Local w As Long, h As Long, p,p2 As Long Ptr, i As Long
                              Local iColor As Long, R,G,B As Single, bmp$, bmp2$
                              Local correctionfactor As Single
                              Local sCF$
                             
                              'get the string from ID_Graphic1
                              Graphic Attach hDlg, %ID_Graphic1
                              Graphic Get Bits To bmp$
                             
                              'get width/height of image
                              w = Cvl(bmp$,1)
                              h = Cvl(bmp$,5)
                              bmp2$ = bmp$             'copy to 2nd string
                              p = StrPtr(bmp$)+8       'position of starting position for bits in string
                              p2 = StrPtr(bmp2$)+8     'position of starting position for bits in 2nd string
                             
                              'get string position of coordinates and modify the string at that position
                              Control Get Text hDlg, %IDC_TextBox To sCF$
                              correctionfactor = Val(sCF$)/100
                              Control Set Text hDlg, %IDC_TextBox2, str$(correctionfactor)
                              For i = 1 To w*h
                                iColor = @p                           'result is a BGR color value 0-R-G-B
                                B = iColor Mod 256                    'or this: iColor AND &HFF&
                                G = (iColor\256) Mod 256              'or this: (iColor AND &HFF00&) \ &H100
                                R = (iColor\256\256) Mod 256          'or this: (iColor AND &HFF0000&) \ &H10000&
                             
                                'lighten/darken
                                If (correctionFactor < 0) Then        'darken image
                                  R *= 1 + correctionFactor
                                  G *= 1 + correctionFactor
                                  B *= 1 + correctionFactor
                                Else
                                  R = (255 - R) * correctionFactor + R
                                  G = (255 - G) * correctionFactor + G
                                  B = (255 - B) * correctionFactor + B
                                End If
                                @p = Bgr(R,G,B)                       'modify string at that position
                             
                                'grayscale
                                iColor = 0.299*R + 0.587*G + 0.114*B
                                @p2 = Bgr(iColor, iColor, iColor)     'modify 2nd string at that position
                             
                                Incr p : Incr p2
                              Next i
                             
                              'put the modified string into ID_Graphic2
                              Graphic Attach hDlg, %ID_Graphic2 : Graphic Set Bits bmp$
                              Graphic Attach hDlg, %ID_Graphic3 : Graphic Set Bits bmp2$
                            End Sub
                            (Small correction of Gary's 'darken' code included)
                            Attached Files
                            Last edited by Dave Biggs; 6 Sep 2013, 07:30 AM. Reason: Add screen shot
                            Rgds, Dave

                            Comment


                            • #15
                              Gary,
                              The wash effect actually involves two factors;
                              1. The percent of color saturation and contrast loss desired (both)
                              2. The average brightness

                              My example deals with both:
                              GrayAvg can be set between 1 and 254
                              correctionfactor can be set between 0 (no difference) and .99(all grayavg)

                              I changed the code to accommodate my graphic and add the GrayScale2 sub, repointing the callback to it.

                              You can set GrayAvg to (B + G + R)\3 and use this to adjust the color saturation, where setting correctionfactor to zero would have no effect and setting it to .99 would kill all color, with anything else in between.

                              The attached graphic shows GrayAvg of 150 and correctionfactor of .5'

                              Code:
                              'Compilable Example:
                              'from here:  http://www.pvladov.com/2012/09/make-color-lighter-or-darker.html
                              #COMPILE EXE
                              #DIM ALL
                              %Unicode=1
                              #INCLUDE &quot;Win32API.inc&quot;
                              #RESOURCE BITMAP cowgirl &quot;girls.bmp&quot;
                              GLOBAL hDlg AS DWORD, hBMP AS DWORD
                              %ID_Graphic1 = 500
                              %ID_Graphic2 = 501
                              
                              FUNCTION PBMAIN() AS LONG
                                 DIALOG NEW PIXELS, 0, &quot;Wash Image&quot;,100,100,800,450, %WS_SYSMENU, 0 TO hDlg
                                 CONTROL ADD BUTTON, hDlg, 100, &quot;Wash&quot;, 10,10,50,20
                                 CONTROL ADD GRAPHIC, hDlg, %ID_Graphic1,&quot;&quot;, 10,40,373,338, %WS_VISIBLE ' Or %SS_Sunken
                                 CONTROL ADD GRAPHIC, hDlg, %ID_Graphic2,&quot;&quot;, 393,40,373,338, %WS_VISIBLE 'Or %SS_Sunken
                                 GRAPHIC ATTACH hDlg, %ID_Graphic1 : GRAPHIC COLOR %BLACK,%WHITE : GRAPHIC CLEAR
                                 GRAPHIC RENDER &quot;girls.bmp&quot;, (0,0)-(372,338)
                                 DIALOG SHOW MODAL hDlg CALL DlgProc
                              END FUNCTION
                              
                              CALLBACK FUNCTION DlgProc() AS LONG
                                 IF CB.MSG = %WM_COMMAND AND CB.CTL = 100 THEN GrayScale2
                              END FUNCTION
                              
                              SUB GrayScale   'uses Long pointer/CVL solution
                                 LOCAL w AS LONG, h AS LONG, p AS LONG PTR, i AS LONG
                                 LOCAL iColor AS LONG, R,G,B AS SINGLE, bmp$
                                 LOCAL correctionfactor AS SINGLE
                              
                                 'get the string from ID_Graphic1
                                 GRAPHIC ATTACH hDlg, %ID_Graphic1
                                 GRAPHIC GET BITS TO bmp$
                              
                                 'get width/height of image
                                 w = CVL(bmp$,1)
                                 h = CVL(bmp$,5)
                                 p = STRPTR(bmp$)+8    'position of starting position for bits in string
                              
                                 'get string position of coordinates and modify the string at that position
                               &d="pnbsp; correctionfactor = .4
                                 FOR i = 1 TO w*h
                                    iColor = @p                           'result is a BGR color value 0-R-G-B
                                    B = iColor MOD 256                    'or this: iColor AND &HFF&
                                    G = (iColor\256) MOD 256              'or this: (iColor AND &HFF00&) \ &H100
                                    R = (iColor\256\256) MOD 256          'or this: (iColor AND &HFF0000&) \ &H10000&
                                    IF (correctionFactor < 0) THEN
                                       correctionFactor = 1 + correctionFactor
                                       R *= correctionFactor
                                       G *= correctionFactor
                                       B *= correctionFactor
                                    ELSE
                                       R = (255 - R) * correctionFactor + R
                                       G = (255 - G) * correctionFactor + G
                                       B = (255 - B) * correctionFactor + B
                                    END IF
                                    @p = BGR(R,G,B)           'modify string at that position
                              &tSibp;     INCR p
                                 NEXT i
                              
                                 'put the modified string into ID_Graphic2
                                 GRAPHIC ATTACH hDlg, %ID_Graphic2
                                 GRAPHIC SET BITS bmp$
                              END SUB
                              
                              SUB GrayScale2   'uses Long pointer/CVL solution
                                 LOCAL w AS LONG, h AS LONG, p AS LONG PTR, i AS LONG
                                 LOCAL iColor AS LONG, R,G,B AS SINGLE, bmp$
                                 LOCAL GrayAvg AS INTEGER
                                 LOCAL correctionfactor AS SINGLE
                              
                                 'get the string from ID_Graphic1
                                 GRAPHIC ATTACH hDlg, %ID_Graphic1
                                 GRAPHIC GET BITS TO bmp$
                              
                                 'get width/height of image
                                 w = CVL(bmp$,1)
                                 h = CVL(bmp$,5)
                                 p = STRPTR(bmp$)+8    'position of starting position for bits in string
                              
                                 'get string position of coordinates and modify the string at that position
                                 'set the average gray tone and amount of color wash desired
                                 GrayAvg = 150
                                 correctionfactor = .5
                                 FOR i = 1 TO w*h
                                    iColor = @p                           'result is a BGR color value 0-R-G-B
                                    B = iColor MOD 256                    'or this: iColor AND &HFF&
                                    G = (iColor\256) MOD 256              'or this: (iColor AND &HFF00&) \ &H100
                                    R = (iColor\256\256) MOD 256          'or this: (iColor AND &HFF0000&) \ &H10000&
                                    IF B > GrayAvg THEN
                                      B = B - ((B - GrayAvg) * correctionfactor)
                                    ELSE
                                      B = B + ((GrayAvg - B) * correctionfactor)
                                    END IF
                                    IF G > GrayAvg THEN
                                      G = G - ((G - GrayAvg) * correctionfactor)
                                    ELSE
                                      G = G + ((GrayAvg - G) * correctionfactor)
                                    END IF
                                    IF R > GrayAvg THEN
                                      R = R - ((R - GrayAvg) * correctionfactor)
                                    ELSE
                                      R = R + ((GrayAvg - R) * correctionfactor)
                                    END IF
                                    @p = BGR(R,G,B)           'modify string at that position
                                    INCR p
                                 NEXT i
                              
                                 'put the modified string into ID_Graphic2
                                 GRAPHIC ATTACH hDlg, %ID_Graphic2
                                 GRAPHIC SET BITS bmp$
                              END SUB
                              Attached Files
                              It's impossible to make anything foolproof because fools are so ingenious.

                              Comment


                              • #16
                                Hey Dave!
                                Thanks for the additional code example. But, what was the darkening correction you mention?

                                I see that instead of this, ...
                                Code:
                                         correctionFactor = 1 + correctionFactor
                                         R *= correctionFactor
                                         G *= correctionFactor
                                         B *= correctionFactor
                                you used this ...
                                Code:
                                      R *= 1 + correctionFactor
                                      G *= 1 + correctionFactor
                                      B *= 1 + correctionFactor
                                But these are the same, so you must have meant some other part of the code?

                                Comment


                                • #17
                                  >But these are the same, so you must have meant some other part of the code?

                                  Um, no, they aren't the same.
                                  Code:
                                  R *= (1 + correctionfactor)
                                  would be the same as
                                  Code:
                                  R*= <separately incremented correctionfactor>

                                  Comment


                                  • #18
                                    But these are the same..
                                    Only for the first pixel!

                                    correctionFactor = 1 + correctionFactor is applied each time through the "For i = 1 To w*h" loop in your original code
                                    Rgds, Dave

                                    Comment


                                    • #19
                                      Just $.02 more cents.

                                      The method you are using (applying a percentage change per color byte) is actually just manual HSL/HSV adjustments, alluding to what I stated earlier. Tweaking with the RGB color percentages directly can be daunting because you will need to adjust multiple colors at once (in different directions) to achieve the desired effect strength.

                                      Once you have HSV/HSL <--> RGB algorithms in place it becomes a simple matter of adjusting the S & L/V values. This would be the "proper" way to go because you are then truly adjusting the aspect you want. The RGB method, albeit simpler up-front , is more a shot in the dark to get the desired effect.
                                      <b>George W. Bleck</b>
                                      <img src='http://www.blecktech.com/myemail.gif'>

                                      Comment


                                      • #20
                                        Hello Michael!
                                        Likewise, thanks for that example. With the insertion of two factors - average gray and correction factor - do I get greater control over the result?

                                        I can see the results from your code (tried it out on my image also). But in general, the results look similar to results of the code I posted from Pavel.

                                        I have no particular experience in image adjustments, so perhaps I'm just not sure how to compare the results of Pavel's code and your code.

                                        Could you give me some guidance on what to look for in assessing the difference between the two code versions?

                                        Here's a side-by-side of the Pavel code and the code you posted, on my cowgirl image.

                                        Comment

                                        Working...
                                        X