I am trying to replace the two least significant bits in each red, green, and blue value in a buffered image pixel in Scala. But when I try to change the least significant bits the change doesn't hold. I have got this working when changing the two most significant bits but it won't work using least significant. Here is the method that does most of the heavy lifting
def hideDataInImage(dataToHide: String, imageToHideIn: BufferedImage): Option[BufferedImage] = {
// Check that the binary data is short enough to encode in the image. Assumeing that we can hide
// one 6-bit element in one pixel the size of the array must be less than the area of the array
if(dataToHide.length > (imageToHideIn.getHeight() * imageToHideIn.getWidth())) {
return None
}
val imageToHideInCopy = deepCopyBufferedImage(imageToHideIn)
// Turn the string of data into a string of binary numbers
val binaryToHide = stringToBinaryArray(dataToHide)
// Loop through the binary data and hide it in each pixel
for(i <- binaryToHide.indices) {
// Get the x and y data for the pixel
val y = i / imageToHideInCopy.getWidth()
val x = i % imageToHideInCopy.getHeight()
val newColor = hideDataInColor(imageToHideInCopy.getRGB(x, y), binaryToHide(i))
imageToHideInCopy.setRGB(x, y, newColor.getRGB)
}
// Return some image to hide in if success
Some(imageToHideInCopy)
}
The rest of the code can be seen on my Github.
Edit: Here is the rest of my code
def hideDataInColor(pixelValue: Int, binaryDataToHide: String): Color = {
// Get the red green blue and alpha values from the pixel value
// 3 2 1 0
// bitpos 10987654 32109876 54321098 76543210
// ------ +--------+--------+--------+--------+
// bits |AAAAAAAA|RRRRRRRR|GGGGGGGG|BBBBBBBB|
val blueValue = byteToPaddedBinary(pixelValue & 0xff, 8)
val greenValue = byteToPaddedBinary((pixelValue & 0xff00) >> 8, 8)
val redValue = byteToPaddedBinary((pixelValue & 0xff0000) >> 16, 8)
val alphaValue = byteToPaddedBinary((pixelValue & 0xff000000) >>> 24, 8)
// Split the binarydata into three parts
val splitData = binaryDataToHide.split("(?<=\\G.{" + binaryDataToHide.length / 3 + "})")
// Get the modified red blue green values
val newRed = hideBitsInBinaryString(redValue, splitData(0))
val newGreen = hideBitsInBinaryString(greenValue, splitData(1))
val newBlue = hideBitsInBinaryString(blueValue, splitData(2))
// Convert the binary number to an integer and return it
new Color(Integer.parseInt(newRed, 2), Integer.parseInt(newGreen, 2),
Integer.parseInt(newBlue, 2), Integer.parseInt(alphaValue, 2))
}
def hideBitsInBinaryString(binaryString: String, bitsToHide: String): String = {
// Create a string builder from the binary string
val binaryStringStringBuilder = new StringBuilder(binaryString)
// Loop through the bits to hide
for(i <- 0 until bitsToHide.length) {
// replace to chars at the end of the string builder
binaryStringStringBuilder.setCharAt(binaryString.length - bitsToHide.length + i, bitsToHide(i))
// binaryStringStringBuilder.setCharAt(i, bitsToHide(i))
}
// Return the binary string builder to string
binaryStringStringBuilder.toString()
}