Advertisement
Guest User

Convert image to Python string

a guest
Aug 28th, 2022
56
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.52 KB | None | 0 0
  1. #!/usr/bin/env python3
  2. # img2py: Convert a black and white image to a pyimage.
  3. # Copyright (C) 2022  Jeffry Johnston
  4. #
  5. # This program is free software: you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation, either version 3 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program.  If not, see <https://www.gnu.org/licenses/>.
  17.  
  18. import sys
  19. from PIL import Image
  20.  
  21. # Parse command line arguments
  22. if len(sys.argv) != 3:
  23.     sys.exit(f"Usage: {sys.argv[0]} B&W_IMAGE.png VAR_NAME")
  24. filename = sys.argv[1]
  25. var_name = sys.argv[2]
  26.  
  27. # Convert every 7 image pixels to one ASCII character
  28. with Image.open(filename) as im:
  29.     width, height = im.size
  30.     value = 0
  31.     bits = 0
  32.     original_data: list[int] = [1, width, height]
  33.     for y in range(height):
  34.         for x in range(width):
  35.             data = im.getpixel((x, y)) # type: ignore
  36.             pixel = int(
  37.                 (data[0] if type(data) is tuple else data) == 0 # type: ignore
  38.             )
  39.  
  40.             # This "backward" bit order was chosen for a few reasons:
  41.             # 1) Trivial to decode with & and >>
  42.             # 2) Any needed padding bits at the end of the image are automatic
  43.             #    and their presence can be completely ignored by the decoder
  44.             # 3) No special case when the last character is padded and repeated
  45.             value |= pixel << bits
  46.             bits += 1
  47.             if bits >= 7:
  48.                 original_data.append(value)
  49.                 value = 0
  50.                 bits = 0
  51.     if bits > 0:
  52.         original_data.append(value)
  53.  
  54. # Determine which bytes are used
  55. dist: dict[int, int] = {}
  56. for i in range(128):
  57.     dist[i] = False
  58. for i in original_data:
  59.     dist[i] = True
  60. used = [i for i in dist if dist[i]]
  61.  
  62. # Add an offset to each byte in the hopes of avoiding restricted characters
  63. for offset in range(128):
  64.     invalid = False
  65.     for i in [0, 10, 13, 34, 92]:
  66.         if i in used:
  67.             invalid = True
  68.             break
  69.     if not invalid:
  70.         break
  71.     for j in range(len(used)):
  72.         used[j] = (used[j] + 1) % 128
  73. else:
  74.     sys.exit("Failed to find a valid offset")
  75.  
  76. # Convert data to a Python string
  77. offset_data = "".join([chr((i + offset) % 128) for i in original_data])
  78. var_str = f"{var_name}=b\"{offset_data}\""
  79.  
  80. # Write output
  81. sys.stdout.buffer.write(var_str.encode("latin1"))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement