reading pixel color data to an array

Blitz3D Forums/Blitz3D Beginners Area/reading pixel color data to an array

AvestheFox(Posted 2010) [#1]
Alright, so my goal here is to create a tile graphics editor that would save the image data into a basic array, ex:

.tilegfx
data 1,1,1,1,1,1,1,1
data 1,0,0,0,0,0,0,1
data 1,0,5,1,1,1,0,1
data 1,0,1,5,1,1,0,1
data 1,0,1,1,5,1,0,1
data 1,0,1,1,1,5,0,1
data 1,0,0,0,0,0,0,1
data 1,1,1,1,1,1,1,1


Which then could be read into the program like this:



At the moment, I have the basic editor functions down pat (except for loading and saving, which will come later). But the problem I'm having is this:



as the image describes, I'm having a really rough time getting the pixel grid to read the pixel rgb data from the selected tile.

Here's how I have my program set up:

globals and types:
Global ms_x#, ms_y#
Global curr_color
Global curr_tile=0

Type pal
	Field x,y
	Field img,col
End Type

Type pix
	Field x,y
	Field px,py
	Field img,col
	Field red,green,blue
End Type

Type tile
	Field x,y
	Field img,frame    
End Type


setting up the graphics:


Main Loop:
setup_pallete
setup_pixels
setup_tiles

While Not KeyHit(1)

ms_x=MouseX() : ms_y=MouseY()

Cls

DrawImage mouse,ms_x,ms_y
draw_pallete(152,16)
draw_pixels(16,16)
draw_tiles(175,16)
Color 0,0,175 : Rect 152,152,16,16
DrawImage current,152,152,curr_color
Color 255,255,255 : Rect 152,152,16,16,0
If KeyHit(57) Then write_pixels
Flip
Wend
End



Setting up the palette and the grids:


Drawing the palette and the grids:


And now the functions used to read and write the rgb values of the tile's pixel data:


What works and what doesn't seem to work:

if you study the code carefully you'll note that the grid editor is made up of 8x8 tiles with 7 frames (each frame represents a shade of gray from the palette) when the user presses spacebar, the tile data is transfered to the current tile and plotted as pixels (see function write_pixel() )

But when the user selects a tile from the tileset grid, the pixel rgb data needs to be sent to the editor grid which accordingly to that rgb data, the "pixel" is set. (see function read_pixel() )

This does not seem to work at all, and the problem seems to be something with the read_pixel function which is supposed to call this action into play.

the read pixel function is called like this from the draw_tiles(x,y) function :

Function draw_tiles(x,y)
	For t.tile=Each tile
		DrawImage tile_grid,t\x+x,t\y+y
		DrawImage t\img,t\x+x,t\y+y,t\frame
		If ImagesOverlap(mouse,ms_x,ms_y,t\img,t\x+x,t\y+y) 
			DrawImage sel,t\x+x,t\y+y
			If MouseDown(1) Then curr_tile=t\frame : read_pixels
		End If 
		If curr_tile=t\frame Then DrawImage curr,t\x+x,t\y+y
	Next 
End Function 



this is the best I can do in describing my problem... if any further information is needed in helping me then feel free to ask.

Thanks in advance!


Floyd(Posted 2010) [#2]
You are using 16-bit graphics and looking for RGB values which cannot possibly exist, such as red=119.

The right way to determine the color values is to set the graphics mode, plot a color with a red value of 119 and then read it back to see what it really is. It will probably be something like 116.


NOTE: I just tried this. R,G,B values of 119 read back as 112, 116, 112.

I thought 16-bit color was no longer available on my PC, but it is.


Floyd(Posted 2010) [#3]
And an afterthought, be sure this is done every time the program runs. Don't do a test like I just did and then save the values 112, 116, 112 in the source code. There is no guarantee they will alway be the same on other machines.


AvestheFox(Posted 2010) [#4]
what's the test code that your using?

I tried it with this:

GetColor(ms_x,ms_y) ; get color at mouse x and y coords
Text 0,0,"r: "+ColorRed()+" g: "+ColorBlue()+" b: "+ColorGreen()


and the color values came up correct on both 16 and 32 bit mode


Floyd(Posted 2010) [#5]
You're in luck, I hadn't even closed the IDE.

Graphics 1280, 1024, 16, 0

Color 119,119,119
Plot 0,0
GetColor 0,0
Print ColorRed()
Print ColorGreen()
Print ColorBlue()
WaitKey


This is 16-bit, full screen. If you can read back 119 then you are not really in 16-bit mode. That would be the case with windowed mode and 32-bit desktop graphics. If that is what you are running then my claim that values like 119 are unavailable does not apply. The problem must then be something else.


AvestheFox(Posted 2010) [#6]
thanks..

but strange, its always returning 119,119,119

again, in both modes

edit: just saw the explanation below your code... so it must be something else :P


AvestheFox(Posted 2010) [#7]
okay, tested it in full screen mode. the values came up different.. so that solves that bit


AvestheFox(Posted 2010) [#8]
unfortunately that still does not seem to solve my problem here.. :(

I still appreciate your input here, Floyd, I learned something from it :) but I still cant get the program to do what I want...


Serpent(Posted 2010) [#9]
Hang on, I can't really understand your problem - well I might. Can you please confirm this or explain where I'm wrong:

- Your main editor is tile based.
- You have a pixel editor which lets you edit each tile.
- The problem is transferring the data between the tile editor and the pixel editor.

Is this right?


AvestheFox(Posted 2010) [#10]
correct

I cant get the pixel editor to change when the user clicks on a different tile


Serpent(Posted 2010) [#11]
Okay, I'll start looking at your code.


Serpent(Posted 2010) [#12]
Found the problem - and another unnecessary bit of code.

At the start, you initialise your 16x16 set of pixels in setup_pixels(). Then in your two pixel changing functions (read_pixels and write_pixels) you have unnecessary for loops which are causing the problems.

read_pixels()


See how you have the two for loops here (i.e. x = 1 to 16 and y = 1 to 16)? This means that for each individual pixel, your program will go through every pixel in the tile. You don't need these loops because the for-each loop will go through each pixel. Essentially, because of these loops, each pixel would be set to the value of {16,16} in the tile.
In fact, this was another problem. When indexing pixels like this in Blitz, the first pixel is 0, not 1. So, the pixels actually range from {0,0} to {15,15}. When you call GetPixel on {16,16}, which is the last thing that happens before your loops move on, it won't find anything because pixel {16,16} doesn't exist! That's why all of your pixels were being set to 'Transparent' - the RGB values from the non-existent pixel would come out to 0, 0, and 0.

This is what was causing your program 'not' to read tiles. After taking out the two inner loops, px and py will be useless. There are two ways you can resolve this. The first is to use a similar method to your 'write_pixels' function:
GetColor px\x / 8, px\y / 8

Alternatively, in your initialisation loop, you can set the px and py values of each pixel and use these. This will save on divisions, but this doesn't really matter anyway.

Working read_pixels() function:



Now, in your 'write_pixels' function:

You also have two unnecessary for loops here. These don't affect the results though - they just mean each pixel is written 256 times to the same spot... So I've taken them out as well:


As far as I can see, everything is working fine now. Be careful about putting in loops that shouldn't be there. If you haven't understood my explanation, let me know and I'll try again.


AvestheFox(Posted 2010) [#13]
Thanks a bunch, Serpant! :) I'll be looking over your explanation and changes when I get the time to do so. Your help here is greatly apreciated! :)


AvestheFox(Posted 2010) [#14]
alright, so now I got the time to look over everything. It makes perfectly good sense about the for loops causing the problems so your explanation was a perfect ace :)

I guess I have a nasty habit of using these loops when it comes to programming :P

Again, thanks! :) if I make something with this, I'll credit you for your help ;)


Adam Novagen(Posted 2010) [#15]
You are using 16-bit graphics and looking for RGB values which cannot possibly exist, such as red=119.

Not strictly true. In Blitz, if you're in 16-bit mode, it'll still return 24-bit colour values. However, it'll simply average them out. So in other words, it'll take the 16-bit colour of the pixel and return the actual 24-bit colour data.


Ross C(Posted 2010) [#16]
And make sure your in full screen, as i don't believe blitz properly does 16 bit mode, in windowed mode.


Adam Novagen(Posted 2010) [#17]
And make sure your in full screen, as i don't believe blitz properly does 16 bit mode, in windowed mode.

Yep, quite so. In windowed mode, Blitz is forced to render at whatever the Windows desktop colour depth is, and the colour depth parameter of Graphics() is overridden.