dbrckovi
asked on
Algorythm which will display all RGB colors in a Picture box
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?
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?
ASKER
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 )
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 )
Is it easier to use dialogbox?
ASKER
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.
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.
ASKER
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.
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.
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
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
ASKER
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?
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?
>> 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.
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,
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
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
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
ASKER
I still don't understand why byte won't loop from 0 to 255, but I'll ask it in another question.
>> 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).
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).
ASKER
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.
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.
>> 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.
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.
ASKER
>> 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!
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!
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.
"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.
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