summaryrefslogtreecommitdiff
path: root/gbimg.py
diff options
context:
space:
mode:
Diffstat (limited to 'gbimg.py')
-rw-r--r--gbimg.py122
1 files changed, 122 insertions, 0 deletions
diff --git a/gbimg.py b/gbimg.py
new file mode 100644
index 0000000..6a3613f
--- /dev/null
+++ b/gbimg.py
@@ -0,0 +1,122 @@
+#! /usr/bin/env python3
+##
+## gbimg - turn PC image files into Game Boy tilesets
+## Copyright (C) 2016 Delwink, LLC
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU Affero General Public License as published by
+## the Free Software Foundation, version 3 only.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU Affero General Public License for more details.
+##
+## You should have received a copy of the GNU Affero General Public License
+## along with this program. If not, see <http://www.gnu.org/licenses/>.
+##
+
+from wand.image import Image
+
+_PALETTE = {
+ 0: 3,
+ 85: 2,
+ 170: 1,
+ 255: 0
+}
+
+def map_palette(color):
+ if color not in _PALETTE:
+ raise ValueError('{} is not a valid color level'.format(color))
+
+ return _PALETTE[color]
+
+class Tileset:
+ def __init__(self, img, data, bank=None):
+ self._img = img
+ self._data = None
+ self._data_var = data
+
+ if type(bank) is str:
+ self._bank_var = bank
+ self._bank_num = None
+ elif type(bank) is int:
+ self._bank_var = None
+ self._bank_num = bank
+ elif bank is None:
+ self._bank_var = None
+ self._bank_num = None
+ else:
+ raise TypeError('bank must be str, int, or None')
+
+ def set_bank_num(self, num):
+ self._bank_num = num
+
+ def _convert(self):
+ with Image(filename=self._img) as img:
+ width, height = img.size
+ if height != 8:
+ raise ValueError('{} height is {}'.format(self, height))
+
+ num_tiles = width / 8
+ if num_tiles % 1 != 0:
+ raise ValueError('Irregular tile width in {}'.format(self))
+
+ num_tiles = int(num_tiles)
+ img.depth = 8
+ blob = img.make_blob(format='RGB')
+
+ encoded = []
+ for tile in range(num_tiles):
+ encoded_tile = []
+
+ for i in range(0, width * 8 * 3, width * 3):
+ byte1 = 0
+ byte2 = 0
+ bit = 0x80
+
+ for j in range(0, 8 * 3, 3):
+ color = map_palette(blob[(i + j) + ((8 * 3) * tile)])
+
+ if color & 0x02:
+ byte1 |= bit
+ if color & 0x01:
+ byte2 |= bit
+
+ bit >>= 1
+
+ encoded_tile.append(byte1)
+ encoded_tile.append(byte2)
+
+ encoded += encoded_tile
+
+ return bytes(encoded)
+
+ @property
+ def data(self):
+ if not self._data:
+ self._data = self._convert()
+
+ return self._data
+
+ @property
+ def image_file(self):
+ return self._img
+
+ @property
+ def data_var(self):
+ return self._data_var
+
+ @property
+ def bank_var(self):
+ return self._bank_var
+
+ @property
+ def bank_num(self):
+ return self._bank_num
+
+ def __len__(self):
+ return len(self.data)
+
+ def __str__(self):
+ return 'Tileset ' + self.image_file