def test_image_fit(self):
        # Message size: 1024 bits
        # Min image size:  18x19 (18x19x3 bits per pixel = 1026)
        msg = self._create_message_of_len(1024)

        image = self._create_image_mock(18, 19)
        small_image = self._create_image_mock(18, 18)
        large_image = self._create_image_mock(120, 120)

        self.assertTrue(fits_in_image(image, msg, nbits=1))
        self.assertFalse(fits_in_image(small_image, msg, nbits=1))
        self.assertTrue(fits_in_image(large_image, msg, nbits=1))
Exemple #2
0
def _lsb_pixel_encode(image, output, message, nbits=1):
    assert fits_in_image(image, message, nbits)

    # TODO: can this be accomplished with Image.tobytes/frombytes/BytesIO or ImageChops with a dummy message Image
    # Encode nbits of the message into each of the three color-components (RGB)
    # for each pixel until we're at the end of the message.
    # The bit mask needs to capture the least nbits significant bits.
    pixels = image.load()
    bit_mask = (1 << nbits) - 1
    msg_iterator = grouper(iter_bits(message, chunksize=nbits), 3)
    for xy, msg_part in zip(iter_coords(image), msg_iterator):
        rgb = tuple((component & ~bit_mask | chunk) if chunk is not None else component
                    for component, chunk in zip(pixels[xy], msg_part))
        pixels[xy] = rgb
    image.save(output)
    return image