Advertisement
Guest User

Untitled

a guest
Feb 19th, 2019
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.40 KB | None | 0 0
  1. #!/usr/bin/env python
  2. #-*- coding: utf-8 -*-
  3.  
  4. '''
  5. Usage Example -
  6. python steganography.py -f X.bmp -o Y.bmp -m "Hidden message!"
  7. '''
  8.  
  9.  
  10.  
  11. from optparse import OptionParser
  12.  
  13.  
  14. __author__ = "ITC"
  15. __license__ = "GPLv3"
  16.  
  17. from PIL import Image
  18.  
  19. try:
  20. input = raw_input
  21. except NameError:
  22. pass
  23.  
  24.  
  25. def set_bit(v, index, x):
  26. """Set the index:th bit of v to 1 if x is truthy, else to 0, and return the new value."""
  27. mask = 1 << index
  28. v &= ~mask
  29. if x:
  30. v |= mask
  31. return v
  32.  
  33. def setlsb(component, bit):
  34. """
  35. Set Least Significant Bit of a colour component.
  36. """
  37. return component & ~1 | int(bit)
  38.  
  39. def a2bits_list(chars):
  40. """
  41. Convert a string to its bits representation as a list of 0's and 1's.
  42. """
  43. return [bin(ord(x))[2:].rjust(8,"0") for x in chars]
  44.  
  45. def fib():
  46. a, b = 0, 1
  47. while 1:
  48. yield a
  49. a, b = b, a + b
  50.  
  51. def hide(input_image_file, message, auto_convert_rgb=False, order_func = fib):
  52. """
  53. Hide a message (string) in an image with a (Least Significant Bit) technique.
  54. """
  55.  
  56.  
  57. message_length = len(message)
  58. assert message_length != 0, "message length is zero"
  59.  
  60. img = Image.open(input_image_file)
  61.  
  62.  
  63. if img.mode not in ['RGB', 'RGBA']:
  64. if not auto_convert_rgb:
  65. print('The mode of the image is not RGB. Mode is {}'.\
  66. format(img.mode))
  67. answer = input('Convert the image to RGB ? [Y / n]\n') or 'Y'
  68. if answer.lower() == 'n':
  69. raise Exception('Not a RGB image.')
  70. img = img.convert('RGB')
  71.  
  72. hidden_bits_order = order_func()
  73. encoded = img.copy()
  74. width, height = img.size
  75. index = 0
  76.  
  77. message = str(message_length) + ":" + str(message)
  78. message_bits = "".join(a2bits_list(message))
  79. message_bits += '0' * ((3 - (len(message_bits) % 3)) % 3)
  80.  
  81. npixels = width * height
  82. len_message_bits = len(message_bits)
  83. if len_message_bits > npixels * 3:
  84. raise Exception("The message you want to hide is too long: {}". \
  85. format(message_length))
  86. for row in range(height):
  87. for col in range(width):
  88. if index + 3 <= len_message_bits :
  89.  
  90. # Get the colour component.
  91. pixel = img.getpixel((col, row))
  92. r = pixel[0]
  93. g = pixel[1]
  94. b = pixel[2]
  95.  
  96. # Change the Least Significant Bit of each colour component.
  97. # Get next bit to hide.
  98. bit = hidden_bits_order.next() % 8
  99. r = set_bit(r, bit, ('1' == message_bits[index]))
  100. g = set_bit(g, bit, ('1' == message_bits[index+1]))
  101. b = set_bit(b, bit, ('1' == message_bits[index+2]))
  102.  
  103. # Save the new pixel
  104. if img.mode == 'RGBA':
  105. updated_pixel = (r, g, b, pixel[3])
  106. else:
  107. updated_pixel = (r, g, b)
  108.  
  109. encoded.putpixel((col, row), updated_pixel)
  110.  
  111. index += 3
  112. else:
  113. img.close()
  114. return encoded
  115.  
  116. img.close()
  117. return encoded
  118.  
  119.  
  120. def write(image, output_image_file):
  121. """
  122. Writes the output image file to disk, handles exceptions.
  123. """
  124. try:
  125. image.save(output_image_file)
  126. except Exception as e:
  127. # If hide() returns an error (Too long message).
  128. print(e)
  129. finally:
  130. image.close()
  131.  
  132. def main():
  133.  
  134. # Read the imahe from disk
  135. encoded = hide(options.input_file, options.message, True)
  136. write(encoded, options.output_file)
  137.  
  138.  
  139. if __name__ == "__main__" :
  140. parser = OptionParser()
  141. parser.add_option("-f", "--input-file", dest="input_file",
  142. help="input image file", action="store", type="string")
  143.  
  144. parser.add_option("-o", "--output-file", dest="output_file",
  145. help="output image file", action="store", type="string")
  146.  
  147. parser.add_option("-m", "--message", dest="message",
  148. help="message to encode", action="store", type="string")
  149.  
  150. (options, args) = parser.parse_args()
  151.  
  152. if None in (options.input_file, options.output_file, options.message): # if filename is not given
  153. parser.error('Aall parameters are required')
  154.  
  155. main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement