Week 6: A New Era

Madeline Krajewski

This week, I finished what I could with Algorithm 1 and began planning how I would approach Algorithm 2. First, I was able to hide a smaller image within a larger host image. For the sake of demonstration purposes, I encoded 6/8 bits. The two birds shown here are the American Robin and the Brown Headed Cowbird. The Cowbird is a brood parasite who lays its eggs in other birds’ nests. One of the host birds is the American Robin, so I thought it would be a bit funny to use the two birds here.

Currently, the only things left I have to do for Algorithm 1 are:

  • Encode the width/height of the secret image
  • Add Hashing to the encoding process to better obscure the fact changes occurred

I spent quite a bit of time trying to decide how to encode the width and height of the secret image. At a first glance, this seems like a small problem. After all, I already encoded the number of bits which were swapped; surely encoding two more numbers is a minor hurdle at best.

However, the issue lies not within the encoding process, but in the decoding process. The decoder needs to know how many bits to read. Since images are generally more than 255 pixels in width and height, I need a method on how to tell when I should stop looking at the least significant bit of each pixel.

At first, I considered putting a series of zeroes. However, I have no way of knowing whether those zeroes are part of the larger number or not. A run of zeroes doesn’t necessarily mean the reading is over, after all. Take the base 10 number 1280. In binary, it would be: 101 0000 0000. I’ve added spaces to make it easier to read. If I encoded eight zeroes to be the breaking point, the decoder would falsely think the hidden image’s width/height should be 5 pixels instead of 1280.

I’ve instead chosen to allocate the number of bits related to the host image’s dimensions. That is, if the host image’s width is 1280 pixels, I would set aside eleven pixels to store the secret image’s width. As it currently stands, I do not believe I need to worry about hidden images with dimensions (either width or height) exceeding the associated dimension of the host image.

Consider images with these dimensions:

Based off the number of pixels, I should (and could!) hide the secret image within the host image. However, decoding it would be rather difficult. I wouldn’t be able to tell what the secret image’s width was. Therefore, making the secret image have smaller dimensions than the host image is the best way I can conceive of implementing this. However, I do wish to discuss this with my professors before proceeding.

Now, for Algorithm 2. I have a variety of approaches on how to go about this. Algorithm 2 takes an image and splits it into k parts. Each part is incomprehensible on its own (imagine each k image as a QR code, appearance wise), but when assembled, the secret image will be revealed. The number of images needed to reassemble an image is t.

There are three different forms I need to make for Algorithm 2:

  • t = k = 2
  • General k (t = k, where k can be any positive integer)
  • t < k, where the number of k image parts needed is less than the total number generated. I’ve conceptualized it as though some spies can be captured, but if enough make it to the meeting spot, the image can still be revealed despite the loss of some of the k images.

For t < k, this will work by having the image’s information overlap in multiple pieces (at least k – t + 1, since one image does need to make it to the meeting location). This will be the final part I need to create. Largely, I’ve focused on conceptualizing the other two parts of Algorithm 2.

I’ve focused mainly on general k, as by doing so, t = k = 2 will automatically be taken care of. Here are a few ideas:

Idea 1: I split each pixel’s color (R, G, B) byte into k parts. By adding/ multiplying all the values together, we generate the [R, G, or B] color value of that pixel.

  • Pro: Easy to understand and implement; uses math, which will make my mom happy.
  • Con: It will take a long time to encode and decode. I’ve found that even with bitwise operations, the encoding and decoding of Algorithm 1 takes a handful of seconds per run.

Idea 2: I encode each pixel’s RGB values in such a way that the decoder performs a series of && bitwise operations in order to find the proper values. (The && operator requires there to be a 1 in each column in order for the 1 to continue to the end. Basically, in any column where I need a zero, I just put a zero in any one of the k images in that pixel’s color and in that “column.”)

Here’s a visualization of what I mean:

  • Pro: Quick code execution; relatively easy to understand how it works.
  • Con: Potentially difficult to implement, mainly because I currently am struggling to encode binary by its column as-is.

Idea 3: I give up and instead pursue my childhood dream of becoming a clown.

  • Pro: I might get to drive the tiny clown car.
  • Con: I would have to pay for clown college in addition to my current student loans. Plus, I’m pretty sure I hate getting shot out of a cannon.

I think, of these, Idea 2 has the highest likelihood of success. I will likely spend a chunk of next week testing out how best to implement this. If I can’t figure it out, I suppose I should start looking into clown colleges.

Just kidding. I’ll instead research and consult my professors over how to best approach this. The decoder should be the easier part, but I can’t exactly code that until I have the encoder working.

    Sources

    “American Robin” by Veronika Andrews Andrews from Pixabay

    “Brown Headed Cowbird” by Bernell MacDonald from Pixabay