0

I need to set the least significant bits of some bytes (from an image).

For example, I have an image of width w and height h. Each element [w][h] is a pixel.

Sample data for the red channel (where I want to set the bits):

[0][0] = 01010111
[0][1] = 01010110
[0][2] = 01011110
[0][3] = 11111011
[0][4] = 01011010
[0][5] = 01100110
[0][6] = 01010101
[0][7] = 11010101

I want to change the bits in bold text into 00101010.

My code so far:

  Dim img As New Bitmap(TextBox1.Text)

    For w As Integer = 0 To img.Width - 1
        For h As Integer = 0 To img.Height - 1
            Dim pixel As Color = img.GetPixel(w, h)

            If w < 4 AndAlso h < TextBox2.Text.Length Then
                Dim pix As Integer = pixel.R
                Dim pix2bin As String = Convert.ToString(pix, 2).PadLeft(8, "0")

How can I do this?

Andrew Morton
  • 24,203
  • 9
  • 60
  • 84
Unknown
  • 1
  • 4
  • I somewhat re-wrote your question to make it clearer. If you feel it does not represent what you wanted to ask, please feel free to edit it further. – Andrew Morton Feb 06 '17 at 19:34
  • You might find [Changing lsb value of image rgb value giving inconsistent value](http://stackoverflow.com/a/26616856/1115360) to be of use. – Andrew Morton Feb 07 '17 at 19:55

1 Answers1

0

In light of your comment "I need to change the last bit", what you need to do is take the byte from the image, set its lowest bit to zero (And &FE), extract the appropriate bit from the byte you want to set the lowest bits to (shift right >> and And with 1) then Or them together:

Option Strict On

Module Module1

    Sub Main()
        ' {&H57, &H56, &H5e, &Hfb, &H5a, &H66, &H55, &Hd5}
        Dim bb As Byte() = {&B1010111, &B1010110, &B1011110, &B11111011, &B1011010, &B1100110, &B1010101, &B11010101}
        Dim lowestBits As Byte = &B101010 ' &H2A

        ' output before state:
        Console.WriteLine(String.Join(" ", bb.Select(Function(b) Convert.ToString(b, 2).PadLeft(8, "0"c))))

        Dim bitPosition = 7
        For i = 0 To bb.Length - 1
            bb(i) = CByte((bb(i) And &HFE) Or ((lowestBits >> bitPosition) And 1))
            bitPosition = (bitPosition + 7) Mod 8 ' equivalent to subtract one and keep it in the range [0, 7]
        Next

        ' output after state:
        Console.WriteLine(String.Join(" ", bb.Select(Function(b) Convert.ToString(b, 2).PadLeft(8, "0"c))))
        Console.ReadLine()

    End Sub

End Module

Outputs:

01010111 01010110 01011110 11111011 01011010 01100110 01010101 11010101
01010110 01010110 01011111 11111010 01011011 01100110 01010101 11010100

You didn't say which way you wanted to set the bits from the replacement, so I did it by using the highest bit from the values-to-set-it-to for the first byte. Modify the code appropriately if you want them the other way round.

You really do not want to convert bytes to strings to perform bit operations on them because it will be very slow.

[I used VS 2017 RC for the convenience of binary literals - I included comments for hex format for you to test this.]

Andrew Morton
  • 24,203
  • 9
  • 60
  • 84