Go Back  Xtreme Visual Basic Talk > Legacy Visual Basic (VB 4/5/6) > Interface and Graphics > [VB6 - API - DIB's] - change a color


Reply
 
Thread Tools Display Modes
  #1  
Old 06-09-2012, 06:19 AM
Cambalinho_83's Avatar
Cambalinho_83 Cambalinho_83 is offline
Senior Contributor
 
Join Date: Feb 2008
Location: somewhere in space
Posts: 1,177
Default [VB6 - API - DIB's] - change a color


i don't understand why my code don't change the color:
Code:
Public Property Get BackColor() As Long
    BackColor = lngBackColor
End Property

Public Property Let BackColor(ByVal vNewValue As Long)
    Dim R As Long
    Dim G As Long
    Dim B As Long
    
    'If vNewValue  lngBackColor Then
        lngBackColor = vNewValue
        R = lngBackColor And &HFF&
        G = (lngBackColor And &HFF00&) \ &H100&
        B = (lngBackColor And &HFF0000) \ &H10000
        For X = 0 To ByteAlignOnWord(bmi.bmHeader.bmBitCount, bm.bmWidth) - 3 Step 3
            For Y = 0 To bm.bmHeight - 1
                If ImageData(X + 2, Y) = ImageData(2, 0) And ImageData(X + 1, Y) = ImageData(1, 0) And ImageData(X, Y) = ImageData(0, 0) Then
                    ImageData(X + 2, Y) = R
                    ImageData(X + 1, Y) = G
                    ImageData(X, Y) = B
                End If
            Next Y
        Next X
    'End If
End Property
i use the same tecnic from transparent. but when i draw the image, the backcolor continue be the same(original image). why my code don't change the color(backcolor).
Reply With Quote
  #2  
Old 06-09-2012, 10:13 PM
Cerian Knight's Avatar
Cerian Knight Cerian Knight is offline
Multi-Technologist

Super Moderator
* Expert *
 
Join Date: May 2004
Location: Michigan
Posts: 3,740
Default

What are your type declarations? I see bmi.bmHeader.bmBitCount then bm.bmWidth, which seems a little strange.
__________________
"May the code that you write never work in ways that you didn't expect; and may the code that you didn't write never require you to maintain it". - Ancient Chinese Proverb
Reply With Quote
  #3  
Old 06-10-2012, 01:16 AM
Cambalinho_83's Avatar
Cambalinho_83 Cambalinho_83 is offline
Senior Contributor
 
Join Date: Feb 2008
Location: somewhere in space
Posts: 1,177
Default

Quote:
Originally Posted by Cerian Knight View Post
What are your type declarations? I see bmi.bmHeader.bmBitCount then bm.bmWidth, which seems a little strange.
heres the entire code class:
Code:
Option Explicit

Private Type BITMAP
    bmType As Long
    bmWidth As Long
    bmHeight As Long
    bmWidthBytes As Long
    bmPlanes As Integer
    bmBitsPixel As Integer
    bmBits As Long
End Type

Private Declare Function GetObject Lib "gdi32" Alias "GetObjectA" _
(ByVal hObject As Long, ByVal nCount As Long, ByRef lpObject As Any) _
As Long

Private Type RGBQUAD
    rgbBlue As Byte
    rgbGreen As Byte
    rgbRed As Byte
    rgbAlpha As Byte
End Type

Private Type BITMAPINFOHEADER
    bmSize As Long
    bmWidth As Long
    bmHeight As Long
    bmPlanes As Integer
    bmBitCount As Integer
    bmCompression As Long
    bmSizeImage As Long
    bmXPelsPerMeter As Long
    bmYPelsPerMeter As Long
    bmClrUsed As Long
    bmClrImportant As Long
End Type

Private Type BITMAPINFO
    bmHeader As BITMAPINFOHEADER
    bmColors(0 To 255) As RGBQUAD
End Type

Private Declare Function GetDIBits Lib "gdi32" (ByVal hDC As Long, _
ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As _
Long, lpBits As Any, lpBI As BITMAPINFO, ByVal wUsage As Long) As Long

Private Declare Function StretchDIBits Lib "gdi32" (ByVal hDC As Long, _
ByVal X As Long, ByVal Y As Long, ByVal dWidth As Long, ByVal dHeight _
As Long, ByVal SrcX As Long, ByVal SrcY As Long, ByVal SrcWidth As _
Long, ByVal SrcHeight As Long, lpBits As Any, lpBI As BITMAPINFO, _
ByVal wUsage As Long, ByVal RasterOp As Long) As Long

Dim ImageData() As Byte
Dim ImageDataChanged() As Byte
Dim ImageDataMask() As Byte
Dim blnTransparent As Boolean
Dim bm As BITMAP
Dim bmi As BITMAPINFO
Dim bmLen As Long
Dim X As Long
Dim Y As Long
Dim lngBackColor As Long

Private Function ByteAlignOnWord(ByVal bitDepth As Byte, ByVal Width As Long) As Long
    ' function to align any bit depth on dWord boundaries
    ByteAlignOnWord = (((Width * bitDepth) + &H1F&) And Not &H1F&) \ &H8&
End Function


'Routine to get an image's pixel information into an array dimensioned (rgb, x, y)
Public Sub GetImageData(ByRef SrcPictureBox As Control)
      
    bmi.bmHeader.bmSize = 40 'Size, in bytes, of the header (always 40)
    bmi.bmHeader.bmPlanes = 1 'Number of planes (always one)
    bmi.bmHeader.bmBitCount = 24 'Bits per pixel (always 24 for image processing)
    bmi.bmHeader.bmCompression = 0 'Compression: none or RLE (always zero)

    'Calculate the size of the bitmap type (in bytes)
    
    bmLen = Len(bm)

    'Get the picture box information from SrcPictureBox and put it into our 'bm' variable
    GetObject SrcPictureBox.Image, bmLen, bm
    
    'Build a correctly sized array.
    ReDim ImageData(0 To ByteAlignOnWord(24, bm.bmWidth) - 1, 0 To bm.bmHeight - 1)

    'Finish building the 'bmi' variable we want to pass to the GetDIBits call (the same variable we used above)
    bmi.bmHeader.bmWidth = bm.bmWidth
    bmi.bmHeader.bmHeight = bm.bmHeight

    'Now that we've completely filled up the 'bmi' variable, we use GetDIBits to take the data from SrcPictureBox and put it into the ImageData() array using the settings we specified in 'bmi'
    GetDIBits SrcPictureBox.hDC, SrcPictureBox.Image, 0, bm.bmHeight, ImageData(0, 0), bmi, 0
    lngBackColor = RGB(ImageData(2, 0), ImageData(1, 0), ImageData(0, 0))
End Sub

'Routine to set an image's pixel information from an array dimensioned(rgb, x, y)
Public Sub DrawImageData(ByRef DstPictureBox As Control, Optional ByRef X As Long = 0, Optional ByRef Y As Long = 0)
    
    Dim blnAutoRedraw As Boolean
          
    If DstPictureBox.AutoRedraw = False Then
        blnAutoRedraw = True
        DstPictureBox.AutoRedraw = True
    End If
    
    If blnTransparent = False Then
        StretchDIBits DstPictureBox.hDC, X, Y, bm.bmWidth, bm.bmHeight, 0, 0, _
            bm.bmWidth, bm.bmHeight, ImageData(0, 0), bmi, 0, vbSrcCopy
    Else
        StretchDIBits DstPictureBox.hDC, X, Y, bm.bmWidth, bm.bmHeight, 0, 0, _
            bm.bmWidth, bm.bmHeight, ImageData(0, 0), bmi, 0, vbSrcInvert
        StretchDIBits DstPictureBox.hDC, X, Y, bm.bmWidth, bm.bmHeight, 0, 0, _
            bm.bmWidth, bm.bmHeight, ImageDataMask(0, 0), bmi, 0, vbSrcAnd
        StretchDIBits DstPictureBox.hDC, X, Y, bm.bmWidth, bm.bmHeight, 0, 0, _
            bm.bmWidth, bm.bmHeight, ImageData(0, 0), bmi, 0, vbSrcInvert
    End If
        
    'Since this doesn't automatically initialize AutoRedraw, we have to do it manually
    'Note: always keep AutoRedraw as 'True' when using DIB sections.
    'Otherwise, you WILL get unpredictable results.
    DstPictureBox.Picture = DstPictureBox.Image
    If blnAutoRedraw = True Then DstPictureBox.AutoRedraw = False
End Sub

Public Property Get Transparent() As Boolean
    Transparent = blnTransparent
End Property

Public Property Let Transparent(ByVal vNewValue As Boolean)
    Dim RWhite As Byte
    Dim GWhite As Byte
    Dim BWhite As Byte
    Dim RBlack As Byte
    Dim GBlack As Byte
    Dim BBlack As Byte
    blnTransparent = vNewValue
    
    If blnTransparent = True Then
        ReDim ImageDataMask(0 To ByteAlignOnWord(24, bm.bmWidth) - 1, 0 To bm.bmHeight - 1)
        RWhite = vbWhite And &HFF&
        GWhite = (vbWhite And &HFF00&) \ &H100&
        BWhite = (vbWhite And &HFF0000) \ &H10000
        RBlack = vbBlack And &HFF&
        GBlack = (vbBlack And &HFF00&) \ &H100&
        BBlack = (vbBlack And &HFF0000) \ &H10000
        
        For X = 0 To ByteAlignOnWord(bmi.bmHeader.bmBitCount, bm.bmWidth) - 3 Step 3
            For Y = 0 To bm.bmHeight - 1
                If ImageData(X + 2, Y) = ImageData(2, 0) And ImageData(X + 1, Y) = ImageData(1, 0) And ImageData(X, Y) = ImageData(0, 0) Then
                    ImageDataMask(X + 2, Y) = RWhite
                    ImageDataMask(X + 1, Y) = GWhite
                    ImageDataMask(X, Y) = BWhite
                Else
                    ImageDataMask(X + 2, Y) = RBlack
                    ImageDataMask(X + 1, Y) = GBlack
                    ImageDataMask(X, Y) = BBlack
                End If
            Next Y
        Next X
    End If
End Property

Public Property Get Width() As Long
    Width = bmi.bmHeader.bmWidth
End Property

Public Property Get Height() As Long
    Height = bmi.bmHeader.bmHeight
End Property


Public Property Get BackColor() As Long
    BackColor = lngBackColor
End Property

Public Property Let BackColor(ByVal vNewValue As Long)
    Dim R As Long
    Dim G As Long
    Dim B As Long
    
    'If vNewValue  lngBackColor Then
        lngBackColor = vNewValue
        R = lngBackColor And 255
        G = (lngBackColor And 65535) \ 256
        B = (lngBackColor And &HFF0000) \ 65536
               
        For X = 0 To ByteAlignOnWord(bmi.bmHeader.bmBitCount, bm.bmWidth) - 3 Step 3
            For Y = 0 To bm.bmHeight - 1
                If ImageData(X + 2, Y) = ImageData(2, 0) And ImageData(X + 1, Y) = ImageData(1, 0) And ImageData(X, Y) = ImageData(0, 0) Then
                    ImageData(X + 2, Y) = R
                    ImageData(X + 1, Y) = G
                    ImageData(X, Y) = B
                End If
            Next Y
        Next X
    'End If
    'Debug.Print bm.bmWidth
End Property
what is more strange is, on transparent property, because it's more or less the same code and works fine. but the change color(the backcolor property) isn't working. is like do just 1 cycle, but don't make sence
Reply With Quote
  #4  
Old 06-10-2012, 10:49 PM
passel's Avatar
passel passel is offline
Sinecure Expert

Super Moderator
* Guru *
 
Join Date: Jun 2003
Location: Upstate New York, usa
Posts: 7,714
Default

Did you try to step through the code with the debugger?
You are comparing the colors in your ImageData to the pixel at location 0,0.
Does the pixel at 0,0 match the pixel at 0,0?
Do you change the color of the pixel at 0,0?
Will any of the other background colors match the pixel at 0,0 once you've changed it?

I was wondering why you didn't cache the "transparent" color before entering your loop when you were doing the transparency test before. It would be faster than indexing three times into the two dimensional array repeatedly for data that is "not suppose to change" while in the loop.
__________________
There Is An Island Of Opportunity In The Middle of Every Difficulty.
Miss That, Though, And You're Pretty Much Doomed.

Last edited by passel; 06-10-2012 at 11:03 PM.
Reply With Quote
  #5  
Old 06-11-2012, 12:48 PM
Cambalinho_83's Avatar
Cambalinho_83 Cambalinho_83 is offline
Senior Contributor
 
Join Date: Feb 2008
Location: somewhere in space
Posts: 1,177
Default

i did a new code and works:
Code:
Private Type Color
    Red As Long
    Green As Long
    Blue As Long
    Alpha As Long
End Type

Private Function ByteAlignOnWord(ByVal bitDepth As Byte, ByVal Width As Long) As Long
    ' function to align any bit depth on dWord boundaries
    ByteAlignOnWord = (((Width * bitDepth) + &H1F&) And Not &H1F&) \ &H8&
End Function

Private Function RGBValues(ByVal Color As Long) As Color 'find the rgb color values of a color
    Dim ReturnColor As Color
    With ReturnColor
        .Red = Color And 255
        .Green = (Color And 65535) / 256
        .Blue = (Color And &HFF0000) \ 65536
        .Alpha = ((Color And &HFF000000) \ 16777216) And &HFF
    End With
    RGBValues = ReturnColor
End Function

Public Property Get BackColor() As Long
    BackColor = lngBackColor
End Property

Public Property Let BackColor(ByVal vNewValue As Long)
    Dim clrBackColor As Color
    Dim clrOldBackColor As Color
    
    If vNewValue <> lngBackColor Then
        clrOldBackColor = RGBValues(lngBackColor)
        lngBackColor = vNewValue
        clrBackColor = RGBValues(lngBackColor)
        For X = 0 To ByteAlignOnWord(bmi.bmHeader.bmBitCount, bm.bmWidth) - 3 Step 3
            For Y = 0 To bm.bmHeight - 1
                If ImageData(X + 2, Y) = clrOldBackColor.Red And ImageData(X + 1, Y) = clrOldBackColor.Green And ImageData(X, Y) = clrOldBackColor.Blue Then
                    ImageData(X + 2, Y) = clrBackColor.Red
                    ImageData(X + 1, Y) = clrBackColor.Green
                    ImageData(X, Y) = clrBackColor.Blue
                End If
            Next Y
        Next X
    End If
End Property
i don't know what is the big diference. but now works lol.
if you know why the last code wasn't correct, please tell me.
now i need 1 advice:
these class is for work with graphics and have:
1 - accept the image from picturebox, form or usercontrol;
2 - have some graphics effects: mirror, rotate, transparent, change color, black and white and more;
3 - draw the image on picturebox, form or usercontrol.
i want do every effects on just 1 cycle for(when is drawed).
maybe i need use a new variable for do the change, but the best is start on changing pixels positions before change the colors, right?
Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off

Forum Jump

Advertisement:





Free Publications
The ASP.NET 2.0 Anthology
101 Essential Tips, Tricks & Hacks - Free 156 Page Preview. Learn the most practical features and best approaches for ASP.NET.
subscribe
Programmers Heaven C# School Book -Free 338 Page eBook
The Programmers Heaven C# School book covers the .NET framework and the C# language.
subscribe
Build Your Own ASP.NET 3.5 Web Site Using C# & VB, 3rd Edition - Free 219 Page Preview!
This comprehensive step-by-step guide will help get your database-driven ASP.NET web site up and running in no time..
subscribe
 
 
-->