Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Ruby

Patrick Shushereba
Patrick Shushereba
10,911 Points

Help fixing a class

I'm working on a program that will "blur" a pixel representation of an image, by identifying the 1 pixels, and changing the pixels surrounding the 1 pixel to 1's as well.

#Before the blur

image = Image.new([
  [0, 0, 0, 0],
  [0, 1, 0, 0],
  [0, 0, 0, 1],
  [0, 0, 0, 0]
])

#After the blur:

afterImage = Image.new([
[0, 1, 0, 0],
[1, 1, 1, 1],
[0, 1, 1, 1],
[0, 0, 0, 1]
])
class Image

    def initialize(image)
        @image = image
    end

    def output_image
        @image.each { |row| puts row.join }
        #puts blur(row_index, col_index)
        #transform.each { |row_index, col_index| blur(row_index, col_index) }
    end 

    def blur(row_index,col_index)
        @image[row_index-1][col_index] = 1
        @image[row_index][col_index-1] = 1
        [row_index][col_index+1] = 1
        [row_index+1][col_index] = 1
    end

#First "1" in @image [1][1]

# Indicies that need to be changed for blur to be complete
#@image[0][1]
#@image[1][0]
#@image[1][2]
#@image[2][1]

  def transform
    one_index = []
    @image.each_with_index do |row, row_index|
        row.each_with_index do |pixel, col_index|
            if pixel == 1
                #one_index.push([row_index, col_index])
                blur(row_index, col_index)
            end
            #blur(row_index, col_index)
        end
    end
    return Image.new(@image)
  end

end

image = Image.new([
  [0, 0, 0, 0],
  [0, 1, 0, 0],
  [0, 0, 0, 1],
  [0, 0, 0, 0]
])
#image.output_image

afterImage = image.transform
afterImage.output_image

# afterImage = Image.new([
#   [0, 1, 0, 0],
#   [1, 1, 1, 1],
#   [0, 1, 1, 1],
#   [0, 0, 0, 1]
# ])

Right now I'm getting a partial blur, where some of the pixels are being changed, but not all of them. I understand that in my blur method, I can set the other two sets of indices to @image, which should complete the change. But when I try to do that I'm getting errors.

1 Answer

Hi Patrick,

I think it's the 3rd line in the blur method that's producing the problem when you add @image. That line is trying to set the pixel to the right but your second "1" pixel (row 3, col 4) doesn't have a pixel to the right because it's on an edge.

You probably need to add a condition for each one to make sure you won't have an index out of range when you either add 1 or subtract 1.

For example, with the first statement in the blur method, you don't want to do that unless row_index is greater than 0. If it's 0 then there is no pixel above to set to 1.

if row_index > 0
  @image[row_index-1][col_index] = 1
end

It would be similar logic for the second line but with col_index instead.

For the 3rd and 4th lines you'll have to know how many rows and columns you have in order to be able to check whether it's ok to add 1 to either index. You might want to add 2 more instance variables to hold the number of rows and columns which you can set in your initialize method. That way you don't have to figure them out each time the blur method is called.

Let me know if that helps.

After thinking about it more and some testing I realized you're going to have another problem once you get the right and bottom pixels set correctly (3rd and 4th lines in your blue method). These are future pixels you're going to visit and you'll be blurring those too. Essentially, once you reach a "1" pixel then every pixel after that is going to become 1.

Based on the expected results you have in the comments you probably don't want this happening.

I don't know if this is the best way but you should probably loop over every pixel and save the location of the "1" pixels in another array. Looking at your commented code in the transform method, it looks like you had this idea at one point.

After doing that you can loop over your locations and call the blur method on each one. That way, you're not blurring pixels that were the result of a previous blur method call.

So I think you have 2 issues total. Have checks in place to detect edge pixels and don't modify the image array while you're looping over it.