[RESOLVED] StretchBlt to update a part of the image-VBForums
Results 1 to 8 of 8

Thread: [RESOLVED] StretchBlt to update a part of the image

  1. #1

    Thread Starter
    Member
    Join Date
    Apr 2015
    Posts
    48

    Resolved [RESOLVED] StretchBlt to update a part of the image

    I have a full screen image size : 1366x768 that scaled to a picture box roughly 847x476 .
    Afterwards, only a few dozens of pixel changed on the top-left of the original 1366x768 image and I want to update that changes on the scaled image.

    As usual, the easiest way is to do a full stretch:
    Code:
    StretchBlt(hdc2, 0, 0, 847, 476, hdc1, 0, 0, 1366, 768, ...)
    However, a full stretch will earn a lot of performance, since i just want to update only a part of the scaled image.

    So I tried to stretch only a part of the image, for example a small part about 80x80 pixel on the top left:
    srcX=0; targetX =0
    srcY=0; targetY =0
    srcWidth = 80; targetWidth = (847/1366) * 80= 49.6046852 = ~50 pixel
    srcHeight = 80; targetHeight = (476/768) * 80=49.58333 = ~50 pixel

    Code:
    StretchBlt(hdc2, 0, 0, 50, 50, hdc1, 0, 0, 80, 80, ...)
    However, after doing it, I realized that there is a distortion on the scaled part that does not fit with the full stretched image. I think it caused because the portion is not an integer. Is there any idea about how to fix this issue
    Last edited by vietnamvodich; Apr 9th, 2017 at 02:07 AM.

  2. #2
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    3,870

    Re: StretchBlt to update a part of the image

    I haven't tried anything, but I think I would try to make the scaling as symmetrical as possible to the original image size.
    So if your source is 1366x768, and you want the size to be close to 847x476, I would try using 854x480 as the scaled version.
    The 768 to 480 conversion should scale on a pixel boundary (I'm theorizing, not tested). And an 80x80 portion of the scaled image should also correspond to an integer pixel boundary (128x128) of the original image. I would think this would minimize the distortion from stretching. The horizontal resolution 1366 to 854 is still not symmetrical with the vertical stretch (768 to 480) but since the portions of the stretch (128x128 to 80x80) are, then perhaps the edge distortion of the stretch will match at those values. (i.e. if you stretch subsections of your large image to your smaller image in "tile" sizes of 128x128 from the original to 80x80 tiles on the scaled image, maybe the stretch compromises will align).

    This is all mathematical theory with no empirical testing to back it up, but may be worth a shot.
    Last edited by passel; Apr 10th, 2017 at 01:40 PM.

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

    Re: StretchBlt to update a part of the image

    If you set a clipping rectangle (stretched size) to encompass the target area (+1 pixel in width/height) then GDI should only try to render the clipping area not entire image. The tricky part is calculating the starting top/left target pixel to begin the rendering. However, not guaranteed to prevent distortion around the edges.
    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} {GDI+ Classes/Samples} {Unicode Open/Save Dialog} {Icon Organizer/Extractor}
    {VB and DPI Tutorial} {XP/Vista Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  4. #4

    Thread Starter
    Member
    Join Date
    Apr 2015
    Posts
    48

    Re: StretchBlt to update a part of the image

    Thank you all for reply on my thread, after a dozen times tested. I realized that the only way to make no distortion is to make an integer scale. For example, (847/1366)= 0.62005.... is an odd number so this is a problem. Try to using other portion that does not produce an odd value will resolve this, but it hard to achieve.

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

    Re: StretchBlt to update a part of the image

    If you are not willing to give in just yet, try this out and let us know if it is what you are after? Maybe it needs a off-by-one pixel adjustment if it is close, but it appears to work. Apologize for the rough code, threw it together quickly.

    1. Create a new test project. On the form add 2 picturebox controls and 1 command button. Leave their default names
    2. In Picture1, add the attached bitmap
    3. Add this code to the form, run the project and test
    Code:
    Option Explicit
    
    Private Declare Function StretchBlt Lib "gdi32.dll" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal nSrcWidth As Long, ByVal nSrcHeight As Long, ByVal dwRop As Long) As Long
    
    
    Private Sub Command1_Click()
        Dim srcX As Long, srcY As Long
        Dim srcCx As Long, srcCy As Long
        Dim destX As Long, destY As Long
        Dim destCx As Long, destCy As Long
        Dim sclX As Single, sclY As Single
        Dim x As Single, y As Single, lColor As Long
        
        srcY = Picture1.ScaleHeight \ 4
        srcX = Picture1.ScaleWidth \ 4
        For y = srcY To Picture1.ScaleHeight - Picture1.ScaleHeight \ 4
            For x = srcX To Picture1.ScaleWidth - Picture1.ScaleWidth \ 4
                lColor = Picture1.Point(x, y)
                Picture1.PSet (x, y), lColor Xor &HFFFFFF
            Next
        Next
        
        srcCy = y - srcY
        srcCx = x - srcX
        sclX = Picture2.ScaleWidth / Picture1.ScaleWidth
        sclY = Picture2.ScaleHeight / Picture1.ScaleHeight
        
        destX = srcX * sclX
        destY = srcY * sclY
        destCx = srcCx * sclX
        destCy = srcCy * sclY
        
        StretchBlt Picture2.hdc, destX, destY, destCx, destCy, _
            Picture1.hdc, srcX, srcY, srcCx, srcCy, vbSrcCopy
        Picture2.Refresh
        
        
    End Sub
    
    Private Sub Form_Load()
    
        With Picture1
            .AutoRedraw = True: .AutoSize = True
            .ScaleMode = vbPixels
            .Move 3210, 150
        End With
        With Picture2
            .AutoRedraw = True
            .ScaleMode = vbPixels  ' on next line, change scale from 0.62005as desired:
            .Move 270, 150, Picture1.Width * 0.62005, Picture1.Height * 0.62005
        End With
        With Command1
            .Caption = "Toggle Inverse"
            .Move 3870, 3465, 2100, 525
        End With
    
        StretchBlt Picture2.hdc, 0, 0, Picture2.ScaleWidth, Picture2.ScaleHeight, _
            Picture1.hdc, 0, 0, Picture1.ScaleWidth, Picture1.ScaleHeight, vbSrcCopy
    End Sub
    Edited: Resize Picture2 as desired to produce other scale ratios. You'll want to remove the lines of code in Form_Load that position/size the controls if you are manually placing them on the form where you want them. You can modify the For:Next loop to select different areas of the source bitmap to invert. If this works for you, you wouldn't need to consider a clipping rectangle either.

    The test project scales from Picture1 to Picture2 (downward scale). I think you are scaling down also? If not, the logic remains, but the source & destination are swapped within the logic
    Attached Images Attached Images  
    Last edited by LaVolpe; Apr 16th, 2017 at 10:19 AM.
    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} {GDI+ Classes/Samples} {Unicode Open/Save Dialog} {Icon Organizer/Extractor}
    {VB and DPI Tutorial} {XP/Vista Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  6. #6

    Thread Starter
    Member
    Join Date
    Apr 2015
    Posts
    48

    Re: StretchBlt to update a part of the image

    Hi LaVolpe,
    Nice to talk with you and thank you very much for trying to help me.
    To see my problem clearly , let add a timer, named timer1 to the form, and edit a bit from your code :

    Code:
    Option Explicit
    
    Private Declare Function StretchBlt Lib "gdi32.dll" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal nSrcWidth As Long, ByVal nSrcHeight As Long, ByVal dwRop As Long) As Long
    Dim toggled As Boolean
    
    Private Sub Command1_Click()
        Dim srcX As Long, srcY As Long
        Dim srcCx As Long, srcCy As Long
        Dim destX As Long, destY As Long
        Dim destCx As Long, destCy As Long
        Dim sclX As Single, sclY As Single
        Dim x As Single, y As Single, lColor As Long
        
        srcY = Picture1.ScaleHeight \ 4
        srcX = Picture1.ScaleWidth \ 4
     
       ' We don't need this anymore:
        'For y = srcY To Picture1.ScaleHeight - Picture1.ScaleHeight \ 4
        '    For x = srcX To Picture1.ScaleWidth - Picture1.ScaleWidth \ 4
        '        lColor = Picture1.Point(x, y)
        '        Picture1.PSet (x, y), lColor Xor &HFFFFFF
        '    Next
        'Next
       ' Replace with this code:
       y = Picture1.ScaleHeight - Picture1.ScaleHeight \ 4
       x = Picture1.ScaleWidth - Picture1.ScaleWidth \ 4
      
        
        srcCy = y - srcY
        srcCx = x - srcX
        sclX = Picture2.ScaleWidth / Picture1.ScaleWidth
        sclY = Picture2.ScaleHeight / Picture1.ScaleHeight
        
        destX = srcX * sclX
        destY = srcY * sclY
        destCx = srcCx * sclX
        destCy = srcCy * sclY
        
        StretchBlt Picture2.hdc, destX, destY, destCx, destCy, _
            Picture1.hdc, srcX, srcY, srcCx, srcCy, vbSrcCopy
        Picture2.Refresh
        
        
    End Sub
    
    
    Private Sub Form_Load()
    
    Picture1.Picture = LoadPicture("C:\fullscreentest.bmp")  ' a full screen image captured, with text content at the center screen to see the effect more clearly
    
    Timer1.interval =300
    Timer1.Enabled= true
        With Picture1
            .AutoRedraw = True: .AutoSize = True
            .ScaleMode = vbPixels
            .Move 3210, 150
        End With
        With Picture2
            .AutoRedraw = True
            .ScaleMode = vbPixels  ' on next line, change scale from 0.62005as desired:
            .Move 270, 150, Picture1.Width * 0.62005, Picture1.Height * 0.62005
        End With
        With Command1
            .Caption = "Toggle Inverse"
            .Move 3870, 3465, 2100, 525
        End With
      StretchBlt Picture2.hdc, 0, 0, Picture2.ScaleWidth, Picture2.ScaleHeight, _
            Picture1.hdc, 0, 0, Picture1.ScaleWidth, Picture1.ScaleHeight, vbSrcCopy
    
    End Sub
    
    Private Sub Timer1_Timer()
    If toggled = True Then
       StretchBlt Picture2.hdc, 0, 0, Picture2.ScaleWidth, Picture2.ScaleHeight, _
            Picture1.hdc, 0, 0, Picture1.ScaleWidth, Picture1.ScaleHeight, vbSrcCopy
            Picture2.Refresh
            toggled = False
            Else
            toggled = True
            Command1_Click
            End If
    End Sub
    Now press F5 to run, you will see the scaled bitmap 'blinking' at the center and a distortion appear around & inside the scaled region, make it very easy to notice. All i want is to make no blinking and no distortion, but it seems hard to achieve.
    Last edited by vietnamvodich; Apr 16th, 2017 at 10:40 PM.

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

    Re: StretchBlt to update a part of the image

    I see what you are describing. Well, maybe a clipping region on the destination might prove successful. You will be doing a full stretchblt, but the clipping area should prevent the entire destination from being updated...
    Code:
    ' APIs
    Private Declare Function CreateRectRgn Lib "gdi32.dll" (ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As Long
    Private Declare Function DeleteObject Lib "gdi32.dll" (ByVal hObject As Long) As Long
    Private Declare Function SelectClipRgn Lib "gdi32.dll" (ByVal hDC As Long, ByVal hRgn As Long) As Long
    
    
    ' sample adjustment
    
        Dim hRgn As Long
        hRgn = CreateRectRgn(destX, destY, destCx + destX, destCy + destY)
        SelectClipRgn Picture2.hdc, hRgn
        DeleteObject hRgn
        
          StretchBlt Picture2.hdc, 0, 0, Picture2.ScaleWidth, Picture2.ScaleHeight, _
            Picture1.hdc, 0, 0, Picture1.ScaleWidth, Picture1.ScaleHeight, vbSrcCopy
        
        SelectClipRgn Picture2.hdc, 0
    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} {GDI+ Classes/Samples} {Unicode Open/Save Dialog} {Icon Organizer/Extractor}
    {VB and DPI Tutorial} {XP/Vista Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  8. #8

    Thread Starter
    Member
    Join Date
    Apr 2015
    Posts
    48

    Re: StretchBlt to update a part of the image

    Quote Originally Posted by LaVolpe View Post
    I see what you are describing. Well, maybe a clipping region on the destination might prove successful. You will be doing a full stretchblt, but the clipping area should prevent the entire destination from being updated...
    Code:
    ' APIs
    Private Declare Function CreateRectRgn Lib "gdi32.dll" (ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As Long
    Private Declare Function DeleteObject Lib "gdi32.dll" (ByVal hObject As Long) As Long
    Private Declare Function SelectClipRgn Lib "gdi32.dll" (ByVal hDC As Long, ByVal hRgn As Long) As Long
    
    
    ' sample adjustment
    
        Dim hRgn As Long
        hRgn = CreateRectRgn(destX, destY, destCx + destX, destCy + destY)
        SelectClipRgn Picture2.hdc, hRgn
        DeleteObject hRgn
        
          StretchBlt Picture2.hdc, 0, 0, Picture2.ScaleWidth, Picture2.ScaleHeight, _
            Picture1.hdc, 0, 0, Picture1.ScaleWidth, Picture1.ScaleHeight, vbSrcCopy
        
        SelectClipRgn Picture2.hdc, 0
    Yessssssss, it workingggg! The performance increased quite a lot ! Thank you very much Lalvope. You're amazingg!

    ( Incredible! I was thought this issue won't able to resolve. I'm very happy to hear your response! Thank you again thousand times! )

Posting Permissions

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



Featured


Click Here to Expand Forum to Full Width

Survey posted by VBForums.