Kahaan / image-manipulation

0 stars 0 forks source link

API improvements #1

Closed choochootrain closed 5 years ago

choochootrain commented 6 years ago

you have the core functionality down but now you have to think about how it will be used. it's useful to think about how you would use this code if someone else wrote it.

so here's a full encode and decode implementation using your library - by writing it out like this you should be able to spot exactly what you need to do to your code in order for this code to run:

def encode(image_path, encoded_image_path, message):
  image = ChunkyPNG::Image.from_file(image_path)
  manipulator = ImageManipulator.new(image)

  # encoded_image is also a ChunkyPNG::Image
  encoded_image = manipulator.encode(message)
  encoded_image.save(encoded_image_path)
end

def decode(encoded_image_path):
  encoded_image = ChunkyPNG::Image.from_file(encoded_image_path)
  manipulator = ImageManipulator.new(encoded_image)

  return manipulator.decode_message()
end

encode('../Downloads/dank_meme.png', '../Downloads/dank_meme2.png', "send nudes")
puts decode('../Downloads/dank_meme2.png')
Kahaan commented 6 years ago

I dun it!

I made the changes you suggested with a few small tweaks. The program now requires an image path when it initializes, turns the image into bits and makes those bits accessible publicly.

The encode function takes in a text message to encode, raises an error if the message is too long and asks the user to enter a shorter message or use a larger file. It also errors to the user is they enter nothing... I took your suggestion and packed the whole image with the message instead of trying to store the length of the bits to extract, much more elegant :). I wrap the message in a beginning and ending single quote (required during extraction...)

After encoding, the image turns back into a png and is saved to a new file

decode img takes in a path from which to decode an img from, doesn't require the text. The default path is the one encode saves to. It turns the image to binary, extracts all the least significant bits, returns the message.

Check it!

Still required:

But other than that, this look good?

choochootrain commented 6 years ago

looks good, add those tests!

also now you can start separating your test/library/tool code. your tests are already separate so thats good, but right now sample.rb is both the library with all the steganography logic and also the script that you run to encode an image - i would separate out that part into something like the code above and remove all the hardcoded image paths and ImageManipulator.news from sample.rb (also maybe rename it to image.rb and delete the old file?)

moving forward you should keep those 3 types of code separate and you'll notice that it'll make things more convenient for you

Kahaan commented 6 years ago

Hmm I'm kinda confused what you mean by separating the script from the library code. The scripting was just to test the functionality of whether this works or not, if I was to take it out, whats the benefit of adding it to a new file if I'll be adding an interface a user can interact with? I'm not clear on what the objective is :p Are you saying I should bake it into a rails controller?

Also I think I've already removed all the hardcoded image path's (other than the script at the bottom I was using for testing) I've only hardcoded where to save the modified new img file, everything else is dynamic, right?

choochootrain commented 6 years ago

its all about abstraction - you wrote a functional routine for encoding and decoding messages in images. the next step is to turn it into a web app. when youre implementing the rails side of this, the details of how the encoding/decoding shouldn't matter at all because you've abstracted them away into an ImageManipulator class with an encode and decode method that just do the right thing.

so the value is in treating this code as a black box as you move on to other parts of your project. but the only way the black box is useful is if it has the rightknobs/inputs/outputs on it. right now you can provide it an image, choose the text to encode, and also decode text. but as a user of the black box you don't have control over the fact that calling encode will save the picture at ../encoded_pic.png - so that harcoded file path should be an argument to the function.

Kahaan commented 6 years ago

Got it, makes sense. I've tweaked it so that the user can choose to specify which image path to save the encoded pic at and given it a default incase they don't care.

I've moved the encode, decode scripts for the sample test I was running to a separate folder tools. Let me know if this is not what you had in mind, tried looking up test/lib/tool structure, couldn't find much but I think this is what you were asking. Eventually I'm going under the assumption that I'll remove even this because the user will click buttons that have event listeners on the front end.

Still working on tests...

Kahaan commented 5 years ago

Strangest error just happened when I tried to run the script for initializing the pic, and then encoding it. Literally didn't change any code. This is probably really stupid but can't figure it out.

For some reason, when I run the script file (like I have been for the past month) I get an error saying the initialize function can't find the IronMonkey file, even though the path looks fine. So I tweaked it a bit and included the name of the dir (so instead of '../IronMonkey.png' if I do '../ChunkyPNG/IronMonkey.png' the initialize works. Super confused why this is happening now, was using the first path literally since writing the program.

Here is what the error looks like if I don't use the new path:

Kahaans-MacBook-Pro:ChunkyPNG kahaanpatel$ ruby tool/script.rb /Users/kahaanpatel/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/chunky_png-1.3.10/lib/chunky_png/datastream.rb:70:ininitialize': No such file or directory @ rb_sysopen - ../IronMonkey.png (Errno::ENOENT) from /Users/kahaanpatel/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/chunky_png-1.3.10/lib/chunky_png/datastream.rb:70:in open' from /Users/kahaanpatel/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/chunky_png-1.3.10/lib/chunky_png/datastream.rb:70:infrom_file' from /Users/kahaanpatel/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/chunky_png-1.3.10/lib/chunky_png/canvas/png_decoding.rb:45:in from_file' from /Users/kahaanpatel/Downloads/aa/ChunkyPNG/lib/image.rb:13:ininitialize' from tool/script.rb:4:in new' from tool/script.rb:4:in

' Kahaans-MacBook-Pro:ChunkyPNG kahaanpatel$

`

BUT even if I add the ChunkyPNG to the path, the encode script (which uses #binary_to_image) function won't work. I figured it was a path issue again so went tweaked the path and added the /ChunkyPNG bit again but this time expecting the function to encode the given image and create a new img file in my folder (like it has been) but no folder is created, and no error. WTF?! lol

I feel like this is something ridiculous obvious that I'm missing but not sure what lol...

I ran git diff to see what changed, here is the result:

`Kahaans-MacBook-Pro:ChunkyPNG kahaanpatel$ git diff diff --git a/encoded_pic.png b/encoded_pic.png deleted file mode 100644 index 756784e..0000000 Binary files a/encoded_pic.png and /dev/null differ diff --git a/tool/script.rb b/tool/script.rb index f7a7281..c2ddfbe 100644 --- a/tool/script.rb +++ b/tool/script.rb @@ -3,6 +3,6 @@ require_relative '../lib/image.rb'

img = ImageManipulator.new('../IronMonkey.png') # -img.encode('Career Karma ') +img.encode('Random message')

img.decode_message Kahaans-MacBook-Pro:ChunkyPNG kahaanpatel$ `

Any idea whats wrong?

Kahaan commented 5 years ago

Found my mistake, was very stupid....

choochootrain commented 5 years ago

whatever it was i guarantee you'll do something just as stupid or stupider the more time you spend coding :upside_down_face:

here's a really good example of that: https://github.com/MrMEEE/bumblebee-Old-and-abbandoned/commit/a047be85247755cdbe0acce6#diff-1