java - 如何在 Scala 中替换缓冲图像中的最低有效位

标签 java scala encoding bufferedimage bit

我试图替换 Scala 中缓冲图像像素中每个红色、绿色和蓝色值中的两个最低有效位。但是当我尝试更改最低有效位时,更改不成立。当更改两个最高有效位时,我已经得到了这个工作,但使用最低有效位则无法工作。这是完成大部分繁重工作的方法

  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)

}

其余代码可以在我的Github上看到.

编辑:这是我的其余代码

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()
  }

最佳答案

代码中的任何位置都不应该有 xy 坐标。内存中像素的布局完全无关,无论如何你都不关心原始图像。您应该直接使用底层线性pixels数组,并按索引寻址像素。

(x, y) 坐标非常有害,它们至少会在您的代码中导致一个错误。这里是错误的:

     val y = i / imageToHideInCopy.getWidth()
     val x = i % imageToHideInCopy.getHeight()

您应该使用 getWidth() getWidth()getHeight() getHeight(),但是不要混合两者。

较小的演示,以了解出了什么问题。假设您的图像是 3x5:

scala> val w = 5
w: Int = 5

scala> val h = 3
h: Int = 3

这就是你正在做的事情:

scala> val coords = (0 until 15).map{ i => (i / w, i % h) }
coords: scala.collection.immutable.IndexedSeq[(Int, Int)] = Vector(
  (0,0), (0,1), (0,2), (0,0), (0,1), 
  (1,2), (1,0), (1,1), (1,2), (1,0), 
  (2,1), (2,2), (2,0), (2,1), (2,2)
)

注意例如(0,0)(0,1) 出现两次。信息被写入这些像素两次。

你应该这样做:

scala> val coords = (0 until 15).map{ i => (i / w, i % w) }
coords: scala.collection.immutable.IndexedSeq[(Int, Int)] = Vector(
  (0,0), (0,1), (0,2), (0,3), (0,4), 
  (1,0), (1,1), (1,2), (1,3), (1,4), 
  (2,0), (2,1), (2,2), (2,3), (2,4)
)

或者这个:

scala> val coords = (0 until 15).map{ i => (i / h, i % h) }
coords: scala.collection.immutable.IndexedSeq[(Int, Int)] = Vector(
  (0,0), (0,1), (0,2), 
  (1,0), (1,1), (1,2), 
  (2,0), (2,1), (2,2), 
  (3,0), (3,1), (3,2), 
  (4,0), (4,1), (4,2)
)

如您所见,无论是行优先还是列优先都完全无关。因此,您实际上可以扔掉这个容易出错的代码并直接使用 pixels

<小时/>

那个位操作代码...好吧,那不是位操作代码。字符串和正则表达式不应与此代码接近。只需阅读 10 个关于位操作和颜色的随机 stackoverflow 答案,例如 something like thisthis ,或者找到一些教程,只是为了了解代码应该是什么样子。

关于java - 如何在 Scala 中替换缓冲图像中的最低有效位,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49418188/

相关文章:

scala - 编译器无法找到单例符号的隐式 Witness.Aux[_]

scala - 检查表达式树的可满足性

json - '+' 字符在 HttpParams Angular 6 中转换为空格

Java获取字符的十进制字节表示

java - 无状态EJB、异常处理问题、容器吞咽异常

java - 比较 Oracle PACKAGE 中的日期类型不起作用

java - 我写了一个通用的有序数组类,比较元素时插入方法出现空指针错误

java - 如何比较 if-else 语句中的字符串?

javascript - 我可以更改 Base 64 编码的字母字符串吗?

Scala 中的 Java 风格 LinkedList