Help: converting long integer colour values to RGB 
Author Message
 Help: converting long integer colour values to RGB

Hi, I have a VB 5 (sp3) problem that I can't seem to find the answer to.
I have a picture box in VB which I load a bmp into using:

Set Box.Picture = LoadPicture(App.Path & "\Image.bmp")

("Box" is the name of my picturebox)
Then I want to take each pixel on the picture box and average out the
red green and blue values for this pixel and load it into a 2D array so
in fact I have a greyscale copy of the image in an array.
I am doing this as I have little knowledge of graphics formats and from
what I have seen loading a bitmap into an array is very complex but this
way I can make VB do all the work. Here is how I do it:

For j = 0 To maxY
    For i = 0 To maxX
        frac(i, j) = Box.Point(i, j)
    Next
Next

Unfortunately the .point method returns a long integer as the colour
value of each pixel and I want a separate red, green and blue value
which I can then average.
My Question is: is there a way to convert the long integer value for the
colour to separate red, green and blue values or is there another easier
way to do what I want instead of the .point method.
Thanks in advance,
George Cole

--
Imagine Renderings and Tutorials
http://www.*-*-*.com/




Wed, 09 Jan 2002 03:00:00 GMT  
 Help: converting long integer colour values to RGB
George,

I'm not quite sure what your `frac' routine does, but in any event, I wrote
this code which will take an RGB Long, convert it into RGB Bytes (in an
array), Average the bytes togethor, and then create a new Long value with
the proper Grey color.  You could use PSet or something and paint the new
pixel over top the old.

Option Explicit
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory"
(Destination As Any, Source As Any, ByVal Length As Long)

Private Sub Command1_Click()
Dim RGBLongColor As Long, RedGreenBlue() As Byte
Dim AvgGrey As Byte, NewGreyLong As Long
  RGBLongColor = RGB(120, 25, 99)
  ReDim RedGreenBlue(1 To 3) As Byte
  Call CopyMemory(RedGreenBlue(1), RGBLongColor, 3)
  Debug.Print "Red: " & RedGreenBlue(1)
  Debug.Print "Green: " & RedGreenBlue(2)
  Debug.Print "Blue: " & RedGreenBlue(3)
  AvgGrey = (RedGreenBlue(1) + RedGreenBlue(2) + RedGreenBlue(3)) / 3
  Debug.Print "Grey: " & AvgGrey
  Debug.Print "Grey Long: " & RGB(AvgGrey, AvgGrey, AvgGrey)
End Sub

--
Howard Henry 'Gawyn Ballpeen' Schlunder
Gawyn Developments; Core developer
http://venus.ajusd.org/~hschlund/


Quote:
> Hi, I have a VB 5 (sp3) problem that I can't seem to find the answer to.
> I have a picture box in VB which I load a bmp into using:

> Set Box.Picture = LoadPicture(App.Path & "\Image.bmp")

> ("Box" is the name of my picturebox)
> Then I want to take each pixel on the picture box and average out the
> red green and blue values for this pixel and load it into a 2D array so
> in fact I have a greyscale copy of the image in an array.
> I am doing this as I have little knowledge of graphics formats and from
> what I have seen loading a bitmap into an array is very complex but this
> way I can make VB do all the work. Here is how I do it:

> For j = 0 To maxY
>     For i = 0 To maxX
>         frac(i, j) = Box.Point(i, j)
>     Next
> Next

> Unfortunately the .point method returns a long integer as the colour
> value of each pixel and I want a separate red, green and blue value
> which I can then average.
> My Question is: is there a way to convert the long integer value for the
> colour to separate red, green and blue values or is there another easier
> way to do what I want instead of the .point method.
> Thanks in advance,
> George Cole

> --
> Imagine Renderings and Tutorials
> http://surf.to/g.cole/





Wed, 09 Jan 2002 03:00:00 GMT  
 Help: converting long integer colour values to RGB
Quote:
> I'm not quite sure what your `frac' routine does, but in any event, I

wrote

Oops, silly me.  I read the code too quickly.  `frac' is a variable not a
proceedure.



Wed, 09 Jan 2002 03:00:00 GMT  
 Help: converting long integer colour values to RGB

Quote:

>> I'm not quite sure what your `frac' routine does, but in any event, I
>wrote

>Oops, silly me.  I read the code too quickly.  `frac' is a variable not a
>proceedure.

HHBS,
More importantly It is an array!!!
So this suggests the following approach:
Neila

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory"
(Destination As Any, Source As Any, ByVal Length As Long)

'I cannot recall if the Byte order is correct here!!!!
'EXPERIMENT and check it!!!!
Private Type RGB
    Red As Byte
    Green As Byte
    Blue As Byte
    Dummy As Byte
End Type

Private Sub Command1_Click()
Dim atRGBArr() As RGB
Dim aFrac() As Long
Dim lHeight As Long
Dim lWidth As Long
Dim lngSize As Long
Dim X As Long
Dim Y As Long
    With Box
        lHeight = .Height
        lWidth = .Width
        ReDim aFrac(lWidth, lHeight)
        ReDim atRGBArr(lWidth, lHeight)

        'Load those pixels !!!!
        For Y = 0 To lHeight
            For X = 0 To lWidth
                aFrac(X, Y) = .Point(X, Y)
            Next
        Next

        'Blast the Bits
        Call CopyMemory(atRGBArr(0, 0), aFrac(0, 0), (lWidth + 1) * (lHeight
+ 1) * 4)
    End With

    'I don't have a clue what you want to do here!!
    For Y = 0 To lHeight
        For X = 0 To lWidth
            With atRGBArr(X, Y)
                Box2.PSet (X, Y), (CLng(.Blue) + CLng(.Red) + CLng(.Green))
/ 3
            End With
        Next
    Next

End Sub

'Scalemode is Pixels!!!
Private Sub Form_Load()
    With Box
        .ScaleMode = vbPixels
        Set .Picture = LoadPicture(App.Path & "\Image.bmp")
    End With
    Box2.ScaleMode = vbPixels
End Sub



Wed, 09 Jan 2002 03:00:00 GMT  
 Help: converting long integer colour values to RGB
Thanks very much for both your help. I'd never succesfully posted to a
newsgroup before this week but I'd been told that they were full of
flame wars, warez and {*filter*} so I'm pretty surprise at what I've found on
comp.lang.basic.visual.misc and comp.graphics.algorithms as both have
helped me out a lot.
My final algorithm looks like this (the API call is in the form too):

Private Sub Load_Click()
Dim y As Integer, x As Integer, i As Integer, RedGreenBlue() As Byte
ReDim RedGreenBlue(1 To 3) As Byte
Set Box.Picture = LoadPicture(App.Path & "\Image.bmp")
For y = 0 To maxY
    For x = 0 To maxX
        Call CopyMemory(RedGreenBlue(1), Box.Point(x, y), 3)
        frac(x, y) = (RedGreenBlue(1) + RedGreenBlue(2) +
RedGreenBlue(3)) / 3
    Next
Next
End Sub

I get this error on the first time round the loops:

Run-time error '6':
Overflow

I hit debug and for some reason it encounters an overflow when adding:
"(RedGreenBlue(1) + RedGreenBlue(2) + RedGreenBlue(3))"

frac(x,y) is indeed an array, I thought I'd said that in my original
post but I did not so I apologise. It's set up as a single data type
elsewhere and is the correct dimensions.
I put my mouse over the redgreenblue texts and they display the correct
red, green and blue values for that pixel so that part of the code works
perfectly, but for some reason VB cannot add the values together.
I would never have found out how to put the long value into separate RGB
bytes as I have not yet learnt how to use the API (I think this is what
you are doing).
I do not need any code to display the array as I have loads of code
elsewhere for that.

Incase I haven't made it clear: could you please now help me find why
the red, green and blue values will not add together.

Thanks,
George Cole

--
Imagine Renderings and Tutorials
http://www.*-*-*.com/




Wed, 09 Jan 2002 03:00:00 GMT  
 Help: converting long integer colour values to RGB

Quote:

>Thanks very much for both your help. I'd never succesfully posted to a
>newsgroup before this week but I'd been told that they were full of
>flame wars, warez and {*filter*} so I'm pretty surprise at what I've found on
>comp.lang.basic.visual.misc and comp.graphics.algorithms as both have
>helped me out a lot.
>My final algorithm looks like this (the API call is in the form too):

>Private Sub Load_Click()
>Dim y As Integer, x As Integer, i As Integer, RedGreenBlue() As Byte
>ReDim RedGreenBlue(1 To 3) As Byte
>Set Box.Picture = LoadPicture(App.Path & "\Image.bmp")
>For y = 0 To maxY
>    For x = 0 To maxX
>        Call CopyMemory(RedGreenBlue(1), Box.Point(x, y), 3)
>        frac(x, y) = (RedGreenBlue(1) + RedGreenBlue(2) +
>RedGreenBlue(3)) / 3
>    Next
>Next
>End Sub

>I get this error on the first time round the loops:

>Run-time error '6':
>Overflow

>I hit debug and for some reason it encounters an overflow when adding:
>"(RedGreenBlue(1) + RedGreenBlue(2) + RedGreenBlue(3))"

>frac(x,y) is indeed an array, I thought I'd said that in my original
>post but I did not so I apologise. It's set up as a single data type
>elsewhere and is the correct dimensions.
>I put my mouse over the redgreenblue texts and they display the correct
>red, green and blue values for that pixel so that part of the code works
>perfectly, but for some reason VB cannot add the values together.
>I would never have found out how to put the long value into separate RGB
>bytes as I have not yet learnt how to use the API (I think this is what
>you are doing).
>I do not need any code to display the array as I have loads of code
>elsewhere for that.

>Incase I haven't made it clear: could you please now help me find why
>the red, green and blue values will not add together.

>Thanks,
>George Cole

>--
>Imagine Renderings and Tutorials
> http://www.*-*-*.com/



See my first code (Clng...( Also use CopyMemory on the entire array
rather than each element ;-) RAW SPEED!!!!!!
Neila.
Here is a revison which does what I THINK you are looking for:
-

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory"
(Destination As Any, Source As Any, ByVal Length As Long)

'I cannot recall if the Byte order is correct here!!!!
'EXPERIMENT and check it!!!!
Private Type RGB
    Red As Byte
    Green As Byte
    Blue As Byte
    Dummy As Byte
End Type

Private Sub Command1_Click()
Dim atRGBArr() As RGB
Dim aFrac() As Long
Dim lHeight As Long
Dim lWidth As Long
Dim lngSize As Long
Dim X As Long
Dim Y As Long
    With Box
        .ScaleMode = vbPixels
        lHeight = .Height
        lWidth = .Width
        ReDim aFrac(lWidth, lHeight)
        ReDim atRGBArr(lWidth, lHeight)

        'Load those pixels !!!!
        For Y = 0 To lHeight
            For X = 0 To lWidth
                aFrac(X, Y) = .Point(X, Y)
            Next
        Next

        'Blast the Bits
        Call CopyMemory(atRGBArr(0, 0), aFrac(0, 0), (lWidth + 1) * (lHeight
+ 1) * 4)
    End With

    'I NOW have a clue what you want to do here!!
    Dim lVal As Long
    For Y = 0 To lHeight
        For X = 0 To lWidth
            With atRGBArr(X, Y)
                lVal = (CLng(.Blue) + CLng(.Red) + CLng(.Green)) / 3
                .Blue = CByte(lVal)
                .Red = CByte(lVal)
                .Green = CByte(lVal)
            End With
        Next
    Next

    'Blast the Bits
    Call CopyMemory(aFrac(0, 0), atRGBArr(0, 0), (lWidth + 1) * (lHeight +
1) * 4)
  '  Box2.AutoRedraw = False
    For Y = 0 To lHeight
        For X = 0 To lWidth
            Box2.PSet (X, Y), aFrac(X, Y)
        Next
    Next
  '  Box2.AutoRedraw = True

End Sub

'Scalemode is Pixels!!!
Private Sub Form_Load()
    With Box
        .ScaleMode = vbPixels
        Set .Picture = LoadPicture(App.Path & "\Image.bmp")
    End With
    Box2.ScaleMode = vbPixels
End Sub



Wed, 09 Jan 2002 03:00:00 GMT  
 Help: converting long integer colour values to RGB
To fix it, you could replace this line of code:

Quote:
>         frac(x, y) = (RedGreenBlue(1) + RedGreenBlue(2) +
> RedGreenBlue(3)) / 3

with this

        frac(x, y) = (CInt(RedGreenBlue(1)) + _
        CInt(RedGreenBlue(2)) + CInt(RedGreenBlue(3))) / 3

You probably only need to convert one of the bytes to an Integer to prevent
the overflow, but I converted all three just in case.

Addmittedly, though, Neila's code would be faster (perhaps a LOT faster; I'm
not sure).  Mine conserves a few bytes of memory in comparison, however.

--
Howard Henry 'Gawyn Ballpeen' Schlunder
Gawyn Developments; Core developer
http://www.*-*-*.com/ ~hschlund/


Quote:
> Thanks very much for both your help. I'd never succesfully posted to a
> newsgroup before this week but I'd been told that they were full of
> flame wars, warez and {*filter*} so I'm pretty surprise at what I've found on
> comp.lang.basic.visual.misc and comp.graphics.algorithms as both have
> helped me out a lot.
> My final algorithm looks like this (the API call is in the form too):

> Private Sub Load_Click()
> Dim y As Integer, x As Integer, i As Integer, RedGreenBlue() As Byte
> ReDim RedGreenBlue(1 To 3) As Byte
> Set Box.Picture = LoadPicture(App.Path & "\Image.bmp")
> For y = 0 To maxY
>     For x = 0 To maxX
>         Call CopyMemory(RedGreenBlue(1), Box.Point(x, y), 3)
>         frac(x, y) = (RedGreenBlue(1) + RedGreenBlue(2) +
> RedGreenBlue(3)) / 3
>     Next
> Next
> End Sub

> I get this error on the first time round the loops:

> Run-time error '6':
> Overflow

> I hit debug and for some reason it encounters an overflow when adding:
> "(RedGreenBlue(1) + RedGreenBlue(2) + RedGreenBlue(3))"

> frac(x,y) is indeed an array, I thought I'd said that in my original
> post but I did not so I apologise. It's set up as a single data type
> elsewhere and is the correct dimensions.
> I put my mouse over the redgreenblue texts and they display the correct
> red, green and blue values for that pixel so that part of the code works
> perfectly, but for some reason VB cannot add the values together.
> I would never have found out how to put the long value into separate RGB
> bytes as I have not yet learnt how to use the API (I think this is what
> you are doing).
> I do not need any code to display the array as I have loads of code
> elsewhere for that.

> Incase I haven't made it clear: could you please now help me find why
> the red, green and blue values will not add together.

> Thanks,
> George Cole

> --
> Imagine Renderings and Tutorials
> http://www.*-*-*.com/





Wed, 09 Jan 2002 03:00:00 GMT  
 Help: converting long integer colour values to RGB
While the arithmetic average is given by your:

Avg = (RGB(1) + RGB(2) + RGB(3)) / 3

...this isn't what most people usually want, which is a representative
monochrome value.  This is better calculated as:

Mono = ((R * 30) + (G * 59) + (B * 11)) \ 100

That's because the three primaries don't contribute equally to the
brightness of the color.  As you can see from the values, green contributes
most, blue the least.

--
     Jim Mack
     MicroDexterity, Inc

     http://www.microdexterity.com




Quote:
>   Call CopyMemory(RedGreenBlue(1), Box.Point(x, y), 3)
>   frac(x, y) = (RedGreenBlue(1) + RedGreenBlue(2) +
> RedGreenBlue(3)) / 3



Thu, 10 Jan 2002 03:00:00 GMT  
 Help: converting long integer colour values to RGB
Thanks to both of you again. It works fine now, and I'm playing with
both methods to see which is most appropriate for my use.
Thanks,
George Cole

--
Imagine Renderings and Tutorials
http://surf.to/g.cole/




Thu, 10 Jan 2002 03:00:00 GMT  
 
 [ 9 post ] 

 Relevant Pages 

1. Converting Long color value to RGB values

2. Converting Long color value to RGB values

3. Converting long value to RGB

4. converting long value rgb() to r,g,b

5. Converting integers and long integers to byte arrays

6. Obtaining RGB components of long colour

7. HELP: Converting to time_t (long integer) taking into account Daylight Hours

8. Help me convert system color NAMES to hex or RGB VALUES

9. Colour to RGB values

10. HELP: Converting colorbox return-value back to RGB ?!!

11. RGB Colour values

12. Help me convert system color NAMES to hex or RGB VALUES

 

 
Powered by phpBB® Forum Software