Solved

Algorythm which will display all RGB colors in a Picture box

Posted on 2004-04-08
16
432 Views
Last Modified: 2010-05-02
Hi!

I need an algorythm which will display RGB colors in a rectangle organised in a color pallete like in Paint or similar program.
I don't need all colors (255*255*255), becouse monitor doesn't have so much pixels, but every n'th color from a pallete, so user can click on a color which they wan't to work with.

If possible, I would like to have an algorythm which will do the oposite thing: when user types in a Red, Green and Blue values, algorythm would return x and y position of that color in a palette ( or the nearest one )

I have been playing with algorythms for some time now, and I managed to get all colors, but they  are not organised as I have expected them to be.
Here's what I have by now:      place 3 buttons and a picturebox on a form
--------------------------------------------------------------------------------------------------------------------------
Private Sub Command1_Click()
    For coly = 0 To 15
        For colx = 0 To 15
            For r = 0 To 255 Step 5
                For g = 0 To 255 Step 5
                Picture1.PSet (r / 5 + colx * 51, g / 5 + coly * 51), RGB(r, g, b)
                DoEvents
                Next g
            Next r
            b = b + 1
        Next colx
    Next coly
    Form1.Caption = "Done"
End Sub

Private Sub Command2_Click()
    For x = 0 To 765
        For y = 0 To 765
            myColor = myColor + 28
            Picture1.PSet (x, y), myColor
        Next y
    Next x
End Sub

Private Sub Command3_Click()
    For x = 0 To 765
        For y = 0 To 765
            myColor = x * y * 28
            Picture1.PSet (x, y), myColor
        Next y
    Next x
End Sub

Private Sub Form_Load()
    Form1.ScaleMode = 3
    Picture1.ScaleMode = 3
    Picture1.Width = 765
    Picture1.Height = 765
    Me.WindowState = 2
End Sub
---------------------------------------------------------------------------------------------

Do you have some other ideas?
0
Comment
Question by:dbrckovi
  • 8
  • 5
  • 3
16 Comments
 
LVL 26

Expert Comment

by:EDDYKT
ID: 10782612
When the user click on the pixel box, just do

Private Declare Function GetPixel Lib "gdi32" (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long) As Long


Private Sub Picture1_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
On Error Resume Next
Debug.Print GetPixel(Picture1.hdc, X, Y)
End Sub
0
 
LVL 11

Author Comment

by:dbrckovi
ID: 10782899
This isn't what I wanted.      I wan't the oposite.

I wan't the function which will give X and Y coordinates of a pixel whoose color matches the given Red, Green and Blue ( or which is the closest to given values )

To be able to do this, I need to create souch picture ( color pallete ) which will be used for containing as much colors as possible.

I can thing of two approaches:
 - To copy and paste souch picture from Paint, but then I don't know the algorythm how was this palette created, so I can't figure the way how to retrieve the position of specific color
    I could create a loop which will look through all colors (pixels) in the picturebox in order to find a match, but this is too slow
 - I coud create my own palette, once, save it as BMP, and the n use it as a picture in picturebox
   That way I would know where my pixels are, and it would be easier to write algorythm which will do the oposite.


P.S. I don't wan't to use already built sollutions in form of ActiveX or similar, becouse I need to be able to transfer this code to other platforms and languages ( Linux, DOS, PS2 eventualy )
0
 
LVL 26

Expert Comment

by:EDDYKT
ID: 10782939
Is it easier to use dialogbox?
0
 
LVL 11

Author Comment

by:dbrckovi
ID: 10783020
Right now I'm trying to create a circular pallete, where center would be white, and borders of the circle would be black.

Then I would make 3 loops each would do a full circle around.

First would start at 0 degrees, and loop to 180. At each step it would draw a blue line from center to the top, but with smaller amount of blue each time. At 180 deg it would draw (0,0,0), and then,
again raise the amount of blue from 180 to 360.

I'll do the same for green and red but they would start from 120 and 240 degrees respectively.

I still have no idea how will this look, but at the moment it looks promissing.
0
 
LVL 11

Author Comment

by:dbrckovi
ID: 10783081
It is easier for Visual Basic and Windows-based languages, but other platforms won't support it.

Maybe I should have asked this Q in Programming section, but at the moment I understand Visual Basic the best, so I choose to ask it here.
0
 
LVL 26

Expert Comment

by:EDDYKT
ID: 10783220
The one way I can think of is use collection to store the color and location

use RGB as your key for fast search

in order to use collection you should be able to find out the location


ie

Private Sub Command1_Click()
Dim col As New Collection

    For x = 0 To 7
        For y = 0 To 7
           
           
            mycolor = mycolor + 28
           
            col.Add CStr(x & "~" & y & "~" & mycolor), CStr(mycolor)
        Next y
    Next x
For Each a In col
Debug.Print a
Next

0
 
LVL 11

Author Comment

by:dbrckovi
ID: 10787691
It would make a search faster once I have colors organised properly.
But I don't have this at the moment.

Maybe I could paste the pallete from paint and store the colors in array or collection like you mentioned.
But the search would still be noticable without having a function which will calculate the corrext position (maybe in one line)

I started to think about alternatives.

Like in Photoshop. It has 3 scrollbars used to define 3 primary colors ( R,G,B )

But each scroll bar is not painted with one solid color, but with a scale of colors which represents what would the final color be if the slider would be placed to that position.
As I scroll one of the scrollbars, other two would change their color scale accordingly.

Few examples:
1) All 3 scrollbars are set to 0    (Final color is black)
    "Red"       - scrollbar has colors from black to red
    "Green"    - from Black to Green
    "Blue"      - from Black To Blue

2) Red scrollbar is set to 255 while other two to 0       (Final color is red)
    Red        - form Black To Red
    Green     - from red to yellow
    Blue        - from red to magenta

3) All 3 set to 255:                                                   ( Final color is white )
    Red        - cyan to white
    Green     - magenta to white
    Blue        - yellow to white
-------------------------------------------------------------------------------------------------------
I hope you understood what I mean.           (I know it is not the best explanation, but my english is limited)

Can you think of a fast algorythm which will do that?

Even if I make function which will do that, drawing would take too long. Photoshop does calculation + drawing for each bar almost "instantly".
This simple code takes almost 1/2 seconds to execute on my comp, even without any calculation.

    For x = 0 To 255
        For y = 1 To 25
            PSet (x * Screen.TwipsPerPixelX, (100 + y) * Screen.TwipsPerPixelX), RGB(x, 0, 0)
            PSet (x * Screen.TwipsPerPixelX, (130 + y) * Screen.TwipsPerPixelX), RGB(0, x, 0)
            PSet (x * Screen.TwipsPerPixelX, (160 + y) * Screen.TwipsPerPixelX), RGB(0, 0, x)
        Next y
    Next x

How can I make this faster?             I can make dimensions of each bar smaller, but there must other way.

I mean 10 years old games could draw whole screen 10+ times in a second without accelerator, and this puny 3 * 255 * 25  pixels take 0.5 sec's to draw.
I tried declaring x as byte, but then I get Owerflow error on the last     Next x     in a loop.  ????

I guess I'm too tired for this now. More I try, more weird problems I have. I mean, what is wrong with looping a byte from 0 to 255? Isn't a byte's value range from 0 to 255?
0
 
LVL 17

Expert Comment

by:zzzzzooc
ID: 10789026
>> How can I make this faster?

PSet is slow and if the DC of the object has to constantly redraw what's being painted, it'll be even more slow. Most graphics-intensive applications do their processing of the bits in memory and then paint the image out from memory (a lot faster). If your palette won't be too intensive, you can still use what PSet uses (SetPixel) for appropriate speeds.

Private Declare Function SetPixel Lib "gdi32" (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long, ByVal crColor As Long) As Long
Private Sub Command1_Click()
    Me.AutoRedraw = True
    For X = 0 To 255
        For Y = 1 To 25
            SetPixel Me.hdc, X, (30 + Y), RGB(X, 0, 0)
            SetPixel Me.hdc, X, (60 + Y), RGB(0, X, 0)
            SetPixel Me.hdc, X, (90 + Y), RGB(0, 0, X)
        Next Y
    Next X
    Me.Refresh
End Sub

I checked the times it took for the above and the one you used. (about 0.03 seconds for mine to draw and 0.17 seconds for yours.) So.. about 5x faster and when you work with memory-bitmaps/memory-dcs, it'd probably be more significantly faster.
0
Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

 
LVL 17

Accepted Solution

by:
zzzzzooc earned 500 total points
ID: 10789142
>> But each scroll bar is not painted with one solid color, but with a scale of colors which represents what would the final color be if the slider would be placed to that position.

Try what I have below. It may be close enough to what you want. Just add 3 PictureBoxes (Indexes set to 0,1,2) and 3 HScroll bars (same indexes as PictureBoxes). The Init() sub will align them for you. It's not perfect but I tried to base it on what you wanted.


Form1:
==============

Option Explicit

Private Declare Function SetPixel Lib "gdi32" (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long, ByVal crColor As Long) As Long
Private Sub InitControls(ByVal bRedraw As Boolean)
    Dim iLoop As Integer
    Dim lPosX As Long, lPosY As Long
    Dim lRGB1 As Long, lRGB2 As Long, lRGB3 As Long
    If bRedraw = False Then
        For iLoop = 0 To 2
            Picture1(iLoop).AutoRedraw = True
            Picture1(iLoop).Width = 255 * Screen.TwipsPerPixelX
            Picture1(iLoop).Height = 20 * Screen.TwipsPerPixelY
            Picture1(iLoop).Left = 0
            Picture1(iLoop).Top = Picture1(iLoop).Height * iLoop
            HScroll1(iLoop).Min = 0
            HScroll1(iLoop).Max = 255
            HScroll1(iLoop).Height = Picture1(iLoop).Height
            HScroll1(iLoop).Top = Picture1(iLoop).Top
            HScroll1(iLoop).Left = Picture1(iLoop).Left + Picture1(iLoop).Width + 50
        Next iLoop
    End If
    For lPosX = 0 To 255
        For lPosY = 1 To 20
            lRGB1 = RGB(HScroll1(0).Value + lPosX, HScroll1(1).Value, HScroll1(2).Value)
            lRGB2 = RGB(HScroll1(0).Value, HScroll1(1).Value + lPosX, HScroll1(2).Value)
            lRGB3 = RGB(HScroll1(0).Value, HScroll1(1).Value, HScroll1(2).Value + lPosX)
            Call SetPixel(Picture1(0).hdc, lPosX, lPosY, lRGB1)
            Call SetPixel(Picture1(1).hdc, lPosX, lPosY, lRGB2)
            Call SetPixel(Picture1(2).hdc, lPosX, lPosY, lRGB3)
        Next lPosY
    Next lPosX
    Call Picture1(0).Refresh
    Call Picture1(1).Refresh
    Call Picture1(2).Refresh
End Sub
Private Sub Form_Load()
    Call InitControls(False)
End Sub
Private Sub HScroll1_Change(Index As Integer)
    Me.BackColor = RGB(HScroll1(0).Value, HScroll1(1), HScroll1(2))
    Call InitControls(True)
End Sub
0
 
LVL 11

Author Comment

by:dbrckovi
ID: 10789588
Thanks.

The world seems a lot more clearer after a full night sleep.
I completely forgot about line function yesterday. It works even faster than SetPixel.

This is it now:

    For lPosX = 0 To 255
            lRGB1 = RGB(lPosX, HScroll1(1).Value, HScroll1(2).Value)
            lRGB2 = RGB(HScroll1(0).Value, lPosX, HScroll1(2).Value)
            lRGB3 = RGB(HScroll1(0).Value, HScroll1(1).Value, lPosX)
            Call SetPixel(Picture1(0).hdc, lPosX, lPosY, lRGB1)
            Call SetPixel(Picture1(1).hdc, lPosX, lPosY, lRGB2)
            Call SetPixel(Picture1(2).hdc, lPosX, lPosY, lRGB3)
            Picture1(0).Line (lPosX * 15, 0)-(lPosX * 15, 20 * 15), lRGB1
            Picture1(1).Line (lPosX * 15, 0)-(lPosX * 15, 20 * 15), lRGB2
            Picture1(2).Line (lPosX * 15, 0)-(lPosX * 15, 20 * 15), lRGB3
    Next lPosX

0
 
LVL 11

Author Comment

by:dbrckovi
ID: 10789594
I still don't understand why byte won't loop from 0 to 255, but I'll ask it in another question.
0
 
LVL 17

Expert Comment

by:zzzzzooc
ID: 10789628
>> I still don't understand why byte won't loop from 0 to 255

After x reaches 255, it'll execute "Next x" and then be directed to the For statement where it will stop since it has reached 255. However, when it reaches "Next x", it'll still increment to 256 before getting to the For statement.. the reason for your overflow.

This will error:
    Dim x As Byte
    For x = 0 To 255
       
    Next x

This will not since we exit For before it reaches "Next x":
    Dim x As Byte
    For x = 0 To 255
        If x = 255 Then
            MsgBox "Reached 255.. manually exit For"
            Exit For
        End If
    Next x


Btw, you should have asked more in this question if you weren't fully satisfied (Grade B).
0
 
LVL 11

Author Comment

by:dbrckovi
ID: 10789655
I originaly wanted an algorythm which will create a color pallete and one or two functions which will be able to calculate x and y positions of desired color ( without searching )
But noone responded to this.  EDDYKT scratched the surface of the problem, but it wasn't what I wanted.

This 3-scroll bars sollution is only an alternative.

I gave it a B grade only becouse it is not the answer to my original question.

I'll make up for this "point-loos" by accepting the other 0-255 question.
0
 
LVL 17

Expert Comment

by:zzzzzooc
ID: 10789677
>> I gave it a B grade only becouse it is not the answer to my original question.

Understandable but you could have asked for more. :) I don't have any problem expanding.

>> I'll make up for this "point-loos" by accepting the other 0-255 question.

I have no worries about the points. Was just curious about your grade.

Good luck.
0
 
LVL 11

Author Comment

by:dbrckovi
ID: 10789710
>> I have no worries about the points. Was just curious about your grade.

Since all PAQ-ed questions go in search, someone may look for this, and then find out that answer is not what was originaly asked.
"B" grade will tell them that answer may not be wxactly what they expect.

No hard feelings!

Regards!
0
 
LVL 17

Expert Comment

by:zzzzzooc
ID: 10789725
Title:
"Algorythm which will display all RGB colors in a Picture box"

Question:
"...I don't need all colors "

They wouldn't have found out anyways since your question doesn't match the title. 16 million pixels in a PictureBox.. :P No worries at all though. As said, I understood the reason for the grade after you mentioned it to me. My last reply.
0

Featured Post

Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Introduction While answering a recent question (http://www.experts-exchange.com/Q_27402310.html) in the VB classic zone, I wrote some VB code in the (Office) VBA environment, rather than fire up my older PC.  I didn't post completely correct code o…
You can of course define an array to hold data that is of a particular type like an array of Strings to hold customer names or an array of Doubles to hold customer sales, but what do you do if you want to coordinate that data? This article describes…
Get people started with the utilization of class modules. Class modules can be a powerful tool in Microsoft Access. They allow you to create self-contained objects that encapsulate functionality. They can easily hide the complexity of a process from…
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now