3

So, this is a problem that me and my friends are facing while doing a project for school.

Our idea is the following. Given a certain photo we want to be able to hide a message behind it. Our approach was the following.

We start by using the command Import to get the image to Mathematica. Then we use the command ImageData to extract the list that contains the pixels in the image.

Then, our approach was to identify a sequence which was not present in those digits. For example, there is no number that is of the form 0,1770... Then we could save the information in these types of numbers.

So, we generate these numbers and then, with the command ReplacePixelValue we were able to replace the pixels in the image. At this point we though that our work was done. But it happens that the information was not preserved with the Export of the coded image.

Our main questions are:

  1. Is it true, by any chance, that exporting a file do not preserve the information? And

  2. What would be the best approach to attain our goal?

Thank you som much for your attention. Have a nice day.

UPDATE

By using the ReplacePart in the list of pixels instead of ReplacePixelValue, I managed to obtain the correct list with the correct substitution of values. Although, when I ask for the image of this new list (by using the command Image) the values are edited. When I ask for a value that was substituted by me, the value is no longer there.

Air Mike
  • 141
  • 5

1 Answers1

4

First, the problem with exporting. There are formats that are lossless and formats that will change the content. Lossless picture format are e.g.: BMP, PNG or RAW. On the other hand, e.g. JPEG will change the content.

Now how to hide some message in a picture? Here is a way to do this:

Idea: Change every pixel of the picture by 0 or 1 according to the message in binary form.

First convert the picture into an array of bytes and the message into a binary array. For convenience prepend the original message length in binary to the message array. Then add the message array to first part of the picture array with the same length. Then convert the message array back to a picture.

Here is the code that does this:

encode[pic_, message_] := Module[{len, d, dims, mess, df},
  d = ImageData[pic, "Byte"];
  dims = d // Dimensions;
  mess = IntegerDigits[ToCharacterCode[message], 2, 8] // Flatten;
  mess = Join[IntegerDigits[Length[mess], 2, 16], mess];
  df = Flatten[d];
  If[(len = Length[mess]) > Length[df], Print["Message too long"]; 
   Return[]];
  df[[;; len]] += mess;
  Image[ArrayReshape[df, dims]/255.]
  ]

decode[pic_, pic0_] := Module[{by, byc, len}, byc = ImageData[pic, "Byte"] // Flatten; by = ImageData[pic0, "Byte"] // Flatten; mess = byc - by; len = FromDigits[mess[[;; 16]], 2]; mess = mess[[17 ;; 17 + len]]; FromCharacterCode@FromDigits[#, 2] & /@ Partition[mess, 8] // StringJoin ]

We may test this using a picture from "ExampleData":

pic = ExampleData[{"TestImage", "House"}];
coded = encode[pic, "Hello World"];
decode[coded, pic]

(* "Hello World" *)

And there is little difference in the images:

pic
code

enter image description here

Daniel Huber
  • 51,463
  • 1
  • 23
  • 57