Win a copy of The Little Book of Impediments (e-book only) this week in the Agile and Other Processes forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Looping through pixels in an image

 
Bod MacNeil
Ranch Hand
Posts: 44
Java Mac Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi, I'm trying to complete a challenge on HackThisSite.  The challenge is - there is a hidden message in the pixels in an image.  I need to loop through the pixels to find this message.  I've only started the challenge and I've ran into a problem.  Here is my code so far:



The problem is this line It doesn't recognise prog2, which is the image.  Am i using this wrong?    thanks
 
Piet Souris
Rancher
Posts: 1529
33
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
hi  Bod,

what about the scope of a variable?   
 
Bod MacNeil
Ranch Hand
Posts: 44
Java Mac Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
aaahhhh so my for loop needs to be inside the try block   thank you!  Its giving me a new error now but I'll try figure this one out before asking. 
 
Piet Souris
Rancher
Posts: 1529
33
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Or maybe simpler: put your Image outside the try block.

If I may give an advice, out of my own experience :

if you have a pixel(x, y), then x is the horizontal distance, i.e. the column, and y is the vertical distance, or the row. So, if you start looping from 0 to image.height, you are talking about the rows. Therefore, it is wise to name the loop variable 'row', instead of y. That has saved me from many index out of bound errors, where I messed up the columns and the rows, and thus the width and the height!
 
Piet Souris
Rancher
Posts: 1529
33
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Between Bods opening post and his first reply there was a reply about the scope of the Image variable, declared within the try-block. That reply got somehow lost in the transfer of this topc to another forum.
 
Bod MacNeil
Ranch Hand
Posts: 44
Java Mac Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Looks like your reply has been returned.  Thanks for the advice as I was probably have confused them also! 

To loop through the imagine pixels, the only thing I could find was using Raster() and BufferedImage().  Would this be the right route to go down or does anyone know of a method which only reads pixels?  I can't seem to find anything else.  I continue to write my code using these methods as I'm sure it can work this way. 
 
Piet Souris
Rancher
Posts: 1529
33
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
A BufferedIamge is easy to use. When you read your image with ImageIO.read, you automatically get a BufferedImage. It has the method 'getRGB' that you can loop through. The int that you get from this method is in the form ARGB, with the alpha component in the bits 24-31. You xcan use the 'setRGB' to write to the BI.
 
Bod MacNeil
Ranch Hand
Posts: 44
Java Mac Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I've been reading into BufferedImage and RBG and have a question which might seem stupid.  I see that we only use 3 colours - blue, green and red in an integer value.  If all 3 are 255, does that mean the pixel is white?  As I'm trying to find white pixels in a picture. 
 
Carey Brown
Bartender
Posts: 1945
24
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Bod MacNeil wrote:I've been reading into BufferedImage and RBG and have a question which might seem stupid.  I see that we only use 3 colours - blue, green and red in an integer value.  If all 3 are 255, does that mean the pixel is white?  As I'm trying to find white pixels in a picture. 
Yes. Black is 0x000000 and white is 0xFFFFFF and red is 0xFF0000 and green is 0x00FF00 and blue is 0x0000FF.
 
Piet Souris
Rancher
Posts: 1529
33
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Agree, but don't forget that getRGB returns a 32-bit integer, with the bits 24-31 containing the alpha component. If that alpha is 255, then the pixel is fully opaque, if alpha is 0, then the pixel is completely transparant. Does a white pixel count as white in that case?

A simple check would be to first have a look at your BufferedImage (either in Java, or in Paint or similar), to see if it is easy to detect the hidden message. Success!
 
Bod MacNeil
Ranch Hand
Posts: 44
Java Mac Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I wish it was that simple :P  The hidden message is the space between all the pixels in the white dots in the picture.  So I need to loop through the picture, once It finds a white dot it stores the dots pixel location and moves on to the next.  I just have no idea how to get the program to detect a certain colour!

 
Piet Souris
Rancher
Posts: 1529
33
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Remember what I said about not mixing the row and the column?  

Well, if you have obtaibed the colour, as you do above, then you could do:


et cetera, and then test for:



Or should you test for colour NOT being white?
 
Bod MacNeil
Ranch Hand
Posts: 44
Java Mac Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I actually had this bit of code before but deleted it as my program didn't work, so I figured that was the problem.  It was clearly something else in the code that was the problem.

I only need to check for white pixels.  This is the image here:


So once we locate the first white pixel at the top, I save the location to an int, and then carry on looping to the next white pixel.  I will have a mess around with what you've suggested.  Thanks
 
Bod MacNeil
Ranch Hand
Posts: 44
Java Mac Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I did a quick test.  My loops seem to be looping through every pixel as the number of pixels were right, but its not picking up any colours when I use this:



This return 000.  Which at first I thought was black?  But if its picking the black up then it must also be picking up the white, which it is not.  IS there something Im missing in this?  thanks
 
Bod MacNeil
Ranch Hand
Posts: 44
Java Mac Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I fixed the problem.  It was code I had written earlier and forgot to remove that was causing the problem!!
 
Carey Brown
Bartender
Posts: 1945
24
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Piet Souris wrote:Or maybe simpler: put your Image outside the try block.

If I may give an advice, out of my own experience :

if you have a pixel(x, y), then x is the horizontal distance, i.e. the column, and y is the vertical distance, or the row. So, if you start looping from 0 to image.height, you are talking about the rows. Therefore, it is wise to name the loop variable 'row', instead of y. That has saved me from many index out of bound errors, where I messed up the columns and the rows, and thus the width and the height!

Piet, I'll have to disagree with you on this. Having done quite a bit of graphics programming X and Y are used almost exclusively, and ROW and COLUMN are nowhere to be found. Event the getRGB() method takes X and Y. I don't quite understand why you were running into out-of-bounds issues when using X and Y.
 
Piet Souris
Rancher
Posts: 1529
33
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
hi Carey,

that's okay. I made this remark based on my own experience, but of course someone elses experience may be completely different.

If you compare the getRGB(x, y) to, say, array[x][y], where array is a 2D array (yeah I know, array of arrays  ) then there is a difference.
In array[x][y] the x is the row, going 'from top to bottom', and y is the column, 'going from left to right'. When dealing with the 'gerRGB(x,y), the situation is exactly reversed. The x is going from left to right (i.e. it is the column, going from 0 ti the widrh - 1), and y is going from top to bottom, ie is about the height. going from 0 to height - 1.

On more than one occasion, dealing with non square images, I mixed up the x and y, letting the x go from top to bottom like in the array, and got my index out of bounds errors. Since then I use consistently the notation array[row][column] for 2d arrays, and getRGB(column, row) for images.

I can imagine people finding this very personal notation of mine confusing. But don't say I didn't warn!   
 
Bod MacNeil
Ranch Hand
Posts: 44
Java Mac Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have managed to loop through the image and find the white pixels.  This is the method which works. 



Whats happening here is once its finds a white pixel it saves the number in an ArrayList called rbgColours. 

The next thing I nee to do is convert these numbers to characters by using the method below.  We do this by measuring the distance between pixels and subtracting the first pixel location with the seconds. 


Once I ran the program I discovered that the hidden message was in morse code.  So I made another method to convert the more code to characters.  This method is below and uses a HashMap.


The last method also works.  The problem I am having is with the middle method sortArray();  When I run the program I get Null before the morse code.  Any ideas why, or a way around this?  Thanks.
 
Bod MacNeil
Ranch Hand
Posts: 44
Java Mac Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I posted the swrong method last.  Here is the HashMap method used to convert the code to ASCII.

 
Piet Souris
Rancher
Posts: 1529
33
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Bod,

I'm afraid you posted your last post in the wrong topic. But can you explain the meaning of the counter values of IIRC, 32, 45 and 46? Are these white pixels always situated at these distances, even when split over more rows? But we'll done, it looks fine. And in case the message is about the location of a treasure: just send me a pm!   
 
Carey Brown
Bartender
Posts: 1945
24
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Your calls to morse.put() should be put in a static initializer block. You don't want to be doing those puts over and over for each choice.
 
Bod MacNeil
Ranch Hand
Posts: 44
Java Mac Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Carey Brown wrote:Your calls to morse.put() should be put in a static initializer block. You don't want to be doing those puts over and over for each choice.


AH that makes sense! thanks


Piet Souris wrote:Hi Bod,

I'm afraid you posted your last post in the wrong topic. But can you explain the meaning of the counter values of IIRC, 32, 45 and 46? Are these white pixels always situated at these distances, even when split over more rows? But we'll done, it looks fine. And in case the message is about the location of a treasure: just send me a pm!   


haha no treasure unfortunately   Here is a screenshot of the challenge as I'm not very good at explaining it.  It makes sense of the shite dots and what I'm trying to do. 


I've completed it now and are now onto the next challenge.  So no doubt I'll be posting a lot about that one :P
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic