bite-core 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- bite_core-0.1.0/LICENSE +21 -0
- bite_core-0.1.0/PKG-INFO +217 -0
- bite_core-0.1.0/README.md +202 -0
- bite_core-0.1.0/bite/__init__.py +7 -0
- bite_core-0.1.0/bite/bite.py +102 -0
- bite_core-0.1.0/bite_core.egg-info/PKG-INFO +217 -0
- bite_core-0.1.0/bite_core.egg-info/SOURCES.txt +9 -0
- bite_core-0.1.0/bite_core.egg-info/dependency_links.txt +1 -0
- bite_core-0.1.0/bite_core.egg-info/top_level.txt +1 -0
- bite_core-0.1.0/pyproject.toml +24 -0
- bite_core-0.1.0/setup.cfg +4 -0
bite_core-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Brianna Ladson
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
bite_core-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: bite-core
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A lightweight library for managing binary sprites, palettes, resizing, and XBM conversion.
|
|
5
|
+
Author: Brianna Ladson
|
|
6
|
+
Keywords: bitmap,sprite,xbm,tkinter,pixel-art
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: Topic :: Multimedia :: Graphics
|
|
11
|
+
Requires-Python: >=3.10
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Dynamic: license-file
|
|
15
|
+
|
|
16
|
+
# Bite v0.1.0
|
|
17
|
+
|
|
18
|
+
Bite is a lightweight Python library for managing binary sprites and color palettes, resizing sprites, and converting them into XBM data for use with Tkinter.
|
|
19
|
+
|
|
20
|
+
Define your sprites using 2D arrays of `0`s and `1`s, store them under unique IDs, and resize them to fit the pixel space you need.
|
|
21
|
+
|
|
22
|
+
## Features
|
|
23
|
+
|
|
24
|
+
- Store multiple sprites under unique IDs.
|
|
25
|
+
- Define sprites using 2D arrays of binary integers.
|
|
26
|
+
- Store reusable foreground and background palettes.
|
|
27
|
+
- Resize sprites to an exact width and height using nearest-neighbor sampling.
|
|
28
|
+
- Convert sprite structures into XBM strings without writing XBM files.
|
|
29
|
+
- No third-party dependencies or Tkinter imports inside Bite.
|
|
30
|
+
|
|
31
|
+
Bite handles data. Your application creates and displays the images.
|
|
32
|
+
|
|
33
|
+
## Setup
|
|
34
|
+
|
|
35
|
+
Place the package folder alongside your application:
|
|
36
|
+
|
|
37
|
+
- `bite/__init__.py`
|
|
38
|
+
- `bite/bite.py`
|
|
39
|
+
- `main.py`
|
|
40
|
+
|
|
41
|
+
Then import Bite:
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
from bite import Bite
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Bite itself uses standard Python features and requires no additional packages. The example below requires a Python installation with Tkinter available.
|
|
48
|
+
|
|
49
|
+
## Quick Start
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
from bite import Bite
|
|
53
|
+
|
|
54
|
+
sprite_manager = Bite(
|
|
55
|
+
structures={
|
|
56
|
+
"house": [
|
|
57
|
+
[0, 0, 1, 0, 0],
|
|
58
|
+
[0, 1, 1, 1, 0],
|
|
59
|
+
[1, 1, 1, 1, 1],
|
|
60
|
+
[0, 1, 0, 1, 0],
|
|
61
|
+
[0, 1, 1, 1, 0],
|
|
62
|
+
],
|
|
63
|
+
},
|
|
64
|
+
palettes={
|
|
65
|
+
"parchment": {
|
|
66
|
+
"foreground": "#69432b",
|
|
67
|
+
"background": "#f3dfac",
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
sprite = sprite_manager.get_sprite("house")
|
|
73
|
+
palette = sprite_manager.get_palette("parchment")
|
|
74
|
+
|
|
75
|
+
resized_sprite = sprite.resize(width=150, height=150)
|
|
76
|
+
bitmap_data = resized_sprite.to_xbm()
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Using Bite with Tkinter
|
|
80
|
+
|
|
81
|
+
This complete example creates a sprite, applies a palette, and displays a resized bitmap on a canvas.
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
from tkinter import Tk, Canvas, BitmapImage, BOTH
|
|
85
|
+
from bite import Bite
|
|
86
|
+
|
|
87
|
+
root = Tk()
|
|
88
|
+
root.title("Bite Demo")
|
|
89
|
+
|
|
90
|
+
canvas = Canvas(root, width=500, height=500)
|
|
91
|
+
canvas.pack(fill=BOTH, expand=True)
|
|
92
|
+
|
|
93
|
+
sprite_manager = Bite()
|
|
94
|
+
|
|
95
|
+
sprite_manager.add_sprite("house", [
|
|
96
|
+
[0, 0, 1, 0, 0],
|
|
97
|
+
[0, 1, 1, 1, 0],
|
|
98
|
+
[1, 1, 1, 1, 1],
|
|
99
|
+
[0, 1, 0, 1, 0],
|
|
100
|
+
[0, 1, 1, 1, 0],
|
|
101
|
+
])
|
|
102
|
+
|
|
103
|
+
sprite_manager.add_palette(
|
|
104
|
+
"parchment",
|
|
105
|
+
foreground="#69432b",
|
|
106
|
+
background="#f3dfac",
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
sprite = sprite_manager.get_sprite("house")
|
|
110
|
+
palette = sprite_manager.get_palette("parchment")
|
|
111
|
+
resized_sprite = sprite.resize(150, 150)
|
|
112
|
+
|
|
113
|
+
image = BitmapImage(
|
|
114
|
+
master=root,
|
|
115
|
+
data=resized_sprite.to_xbm(),
|
|
116
|
+
foreground=palette.foreground,
|
|
117
|
+
background=palette.background,
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
canvas.create_image(250, 250, image=image)
|
|
121
|
+
|
|
122
|
+
root.mainloop()
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Keep a Python reference to each `BitmapImage` while it is displayed. For multiple images, you can store references in a list or dictionary.
|
|
126
|
+
|
|
127
|
+
## Sprite Structures
|
|
128
|
+
|
|
129
|
+
Each inner list represents one row. All rows must have the same length, and every value must be the integer `0` or `1`.
|
|
130
|
+
|
|
131
|
+
- `1` uses the image's foreground color.
|
|
132
|
+
- `0` uses the image's background color.
|
|
133
|
+
|
|
134
|
+
Empty structures, uneven rows, and values other than integer `0` or `1` raise `ValueError`.
|
|
135
|
+
|
|
136
|
+
Bite copies the supplied rows when creating a sprite, so later changes to the original input array do not change the stored sprite.
|
|
137
|
+
|
|
138
|
+
## Palettes
|
|
139
|
+
|
|
140
|
+
Palettes store color strings independently of sprites. The same sprite can be displayed with multiple palettes, and the same palette can be used with multiple sprites.
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
sprite_manager.add_palette(
|
|
144
|
+
"night",
|
|
145
|
+
foreground="lightblue",
|
|
146
|
+
background="midnightblue",
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
sprite_manager.add_palette(
|
|
150
|
+
"transparent",
|
|
151
|
+
foreground="darkgreen",
|
|
152
|
+
background="",
|
|
153
|
+
)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Use an empty background string for transparent `0` pixels in Tkinter. Colors are passed through unchanged; Tkinter validates them when they are applied to an image.
|
|
157
|
+
|
|
158
|
+
To change an existing Tkinter image's palette:
|
|
159
|
+
|
|
160
|
+
```python
|
|
161
|
+
palette = sprite_manager.get_palette("night")
|
|
162
|
+
|
|
163
|
+
image.configure(
|
|
164
|
+
foreground=palette.foreground,
|
|
165
|
+
background=palette.background,
|
|
166
|
+
)
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Palette colors are supplied separately to `BitmapImage`; they are not embedded in the XBM string. Changing a stored palette does not automatically update existing images.
|
|
170
|
+
|
|
171
|
+
## Resizing
|
|
172
|
+
|
|
173
|
+
```python
|
|
174
|
+
sprite = sprite_manager.get_sprite("house")
|
|
175
|
+
resized_sprite = sprite.resize(width=200, height=100)
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
`resize()` returns a new sprite and leaves the original unchanged. Width and height must be positive integers.
|
|
179
|
+
|
|
180
|
+
The sprite is stretched to exactly the requested dimensions. Each axis scales independently, so the original aspect ratio is not automatically preserved. Nearest-neighbor sampling keeps all pixels binary, although shrinking can remove small details.
|
|
181
|
+
|
|
182
|
+
For repeated resizing, start from the original sprite rather than a previously resized version.
|
|
183
|
+
|
|
184
|
+
## API Reference
|
|
185
|
+
|
|
186
|
+
### Bite
|
|
187
|
+
|
|
188
|
+
| Method | Description |
|
|
189
|
+
| --- | --- |
|
|
190
|
+
| `Bite(structures=None, palettes=None)` | Create a manager, optionally with dictionaries of sprite structures and palette settings. |
|
|
191
|
+
| `add_sprite(sprite_id, structure)` | Create, store, and return a sprite. |
|
|
192
|
+
| `get_sprite(sprite_id)` | Return a stored sprite. |
|
|
193
|
+
| `add_palette(palette_id, foreground="black", background="")` | Create, store, and return a palette. |
|
|
194
|
+
| `get_palette(palette_id)` | Return a stored palette. |
|
|
195
|
+
|
|
196
|
+
Sprite IDs must be unique within `sprites`; palette IDs must be unique within `palettes`. The same ID can appear in both collections. Duplicate IDs raise `ValueError`; requesting a missing ID raises `KeyError`.
|
|
197
|
+
|
|
198
|
+
### Sprite
|
|
199
|
+
|
|
200
|
+
Sprite objects are created and returned by Bite.
|
|
201
|
+
|
|
202
|
+
| Attribute or method | Description |
|
|
203
|
+
| --- | --- |
|
|
204
|
+
| `structure` | The stored 2D array of binary pixels. |
|
|
205
|
+
| `width` | Width of the sprite in pixels. |
|
|
206
|
+
| `height` | Height of the sprite in pixels. |
|
|
207
|
+
| `resize(width, height)` | Return a new sprite at the requested dimensions. |
|
|
208
|
+
| `to_xbm()` | Return an XBM-formatted string for the sprite. |
|
|
209
|
+
|
|
210
|
+
### Palette
|
|
211
|
+
|
|
212
|
+
Palette objects are created and returned by Bite.
|
|
213
|
+
|
|
214
|
+
| Attribute | Description |
|
|
215
|
+
| --- | --- |
|
|
216
|
+
| `foreground` | Color used for `1` pixels. Defaults to `"black"`. |
|
|
217
|
+
| `background` | Color used for `0` pixels. Defaults to `""`. |
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# Bite v0.1.0
|
|
2
|
+
|
|
3
|
+
Bite is a lightweight Python library for managing binary sprites and color palettes, resizing sprites, and converting them into XBM data for use with Tkinter.
|
|
4
|
+
|
|
5
|
+
Define your sprites using 2D arrays of `0`s and `1`s, store them under unique IDs, and resize them to fit the pixel space you need.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- Store multiple sprites under unique IDs.
|
|
10
|
+
- Define sprites using 2D arrays of binary integers.
|
|
11
|
+
- Store reusable foreground and background palettes.
|
|
12
|
+
- Resize sprites to an exact width and height using nearest-neighbor sampling.
|
|
13
|
+
- Convert sprite structures into XBM strings without writing XBM files.
|
|
14
|
+
- No third-party dependencies or Tkinter imports inside Bite.
|
|
15
|
+
|
|
16
|
+
Bite handles data. Your application creates and displays the images.
|
|
17
|
+
|
|
18
|
+
## Setup
|
|
19
|
+
|
|
20
|
+
Place the package folder alongside your application:
|
|
21
|
+
|
|
22
|
+
- `bite/__init__.py`
|
|
23
|
+
- `bite/bite.py`
|
|
24
|
+
- `main.py`
|
|
25
|
+
|
|
26
|
+
Then import Bite:
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
from bite import Bite
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Bite itself uses standard Python features and requires no additional packages. The example below requires a Python installation with Tkinter available.
|
|
33
|
+
|
|
34
|
+
## Quick Start
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
from bite import Bite
|
|
38
|
+
|
|
39
|
+
sprite_manager = Bite(
|
|
40
|
+
structures={
|
|
41
|
+
"house": [
|
|
42
|
+
[0, 0, 1, 0, 0],
|
|
43
|
+
[0, 1, 1, 1, 0],
|
|
44
|
+
[1, 1, 1, 1, 1],
|
|
45
|
+
[0, 1, 0, 1, 0],
|
|
46
|
+
[0, 1, 1, 1, 0],
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
palettes={
|
|
50
|
+
"parchment": {
|
|
51
|
+
"foreground": "#69432b",
|
|
52
|
+
"background": "#f3dfac",
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
sprite = sprite_manager.get_sprite("house")
|
|
58
|
+
palette = sprite_manager.get_palette("parchment")
|
|
59
|
+
|
|
60
|
+
resized_sprite = sprite.resize(width=150, height=150)
|
|
61
|
+
bitmap_data = resized_sprite.to_xbm()
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Using Bite with Tkinter
|
|
65
|
+
|
|
66
|
+
This complete example creates a sprite, applies a palette, and displays a resized bitmap on a canvas.
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
from tkinter import Tk, Canvas, BitmapImage, BOTH
|
|
70
|
+
from bite import Bite
|
|
71
|
+
|
|
72
|
+
root = Tk()
|
|
73
|
+
root.title("Bite Demo")
|
|
74
|
+
|
|
75
|
+
canvas = Canvas(root, width=500, height=500)
|
|
76
|
+
canvas.pack(fill=BOTH, expand=True)
|
|
77
|
+
|
|
78
|
+
sprite_manager = Bite()
|
|
79
|
+
|
|
80
|
+
sprite_manager.add_sprite("house", [
|
|
81
|
+
[0, 0, 1, 0, 0],
|
|
82
|
+
[0, 1, 1, 1, 0],
|
|
83
|
+
[1, 1, 1, 1, 1],
|
|
84
|
+
[0, 1, 0, 1, 0],
|
|
85
|
+
[0, 1, 1, 1, 0],
|
|
86
|
+
])
|
|
87
|
+
|
|
88
|
+
sprite_manager.add_palette(
|
|
89
|
+
"parchment",
|
|
90
|
+
foreground="#69432b",
|
|
91
|
+
background="#f3dfac",
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
sprite = sprite_manager.get_sprite("house")
|
|
95
|
+
palette = sprite_manager.get_palette("parchment")
|
|
96
|
+
resized_sprite = sprite.resize(150, 150)
|
|
97
|
+
|
|
98
|
+
image = BitmapImage(
|
|
99
|
+
master=root,
|
|
100
|
+
data=resized_sprite.to_xbm(),
|
|
101
|
+
foreground=palette.foreground,
|
|
102
|
+
background=palette.background,
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
canvas.create_image(250, 250, image=image)
|
|
106
|
+
|
|
107
|
+
root.mainloop()
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Keep a Python reference to each `BitmapImage` while it is displayed. For multiple images, you can store references in a list or dictionary.
|
|
111
|
+
|
|
112
|
+
## Sprite Structures
|
|
113
|
+
|
|
114
|
+
Each inner list represents one row. All rows must have the same length, and every value must be the integer `0` or `1`.
|
|
115
|
+
|
|
116
|
+
- `1` uses the image's foreground color.
|
|
117
|
+
- `0` uses the image's background color.
|
|
118
|
+
|
|
119
|
+
Empty structures, uneven rows, and values other than integer `0` or `1` raise `ValueError`.
|
|
120
|
+
|
|
121
|
+
Bite copies the supplied rows when creating a sprite, so later changes to the original input array do not change the stored sprite.
|
|
122
|
+
|
|
123
|
+
## Palettes
|
|
124
|
+
|
|
125
|
+
Palettes store color strings independently of sprites. The same sprite can be displayed with multiple palettes, and the same palette can be used with multiple sprites.
|
|
126
|
+
|
|
127
|
+
```python
|
|
128
|
+
sprite_manager.add_palette(
|
|
129
|
+
"night",
|
|
130
|
+
foreground="lightblue",
|
|
131
|
+
background="midnightblue",
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
sprite_manager.add_palette(
|
|
135
|
+
"transparent",
|
|
136
|
+
foreground="darkgreen",
|
|
137
|
+
background="",
|
|
138
|
+
)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Use an empty background string for transparent `0` pixels in Tkinter. Colors are passed through unchanged; Tkinter validates them when they are applied to an image.
|
|
142
|
+
|
|
143
|
+
To change an existing Tkinter image's palette:
|
|
144
|
+
|
|
145
|
+
```python
|
|
146
|
+
palette = sprite_manager.get_palette("night")
|
|
147
|
+
|
|
148
|
+
image.configure(
|
|
149
|
+
foreground=palette.foreground,
|
|
150
|
+
background=palette.background,
|
|
151
|
+
)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Palette colors are supplied separately to `BitmapImage`; they are not embedded in the XBM string. Changing a stored palette does not automatically update existing images.
|
|
155
|
+
|
|
156
|
+
## Resizing
|
|
157
|
+
|
|
158
|
+
```python
|
|
159
|
+
sprite = sprite_manager.get_sprite("house")
|
|
160
|
+
resized_sprite = sprite.resize(width=200, height=100)
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
`resize()` returns a new sprite and leaves the original unchanged. Width and height must be positive integers.
|
|
164
|
+
|
|
165
|
+
The sprite is stretched to exactly the requested dimensions. Each axis scales independently, so the original aspect ratio is not automatically preserved. Nearest-neighbor sampling keeps all pixels binary, although shrinking can remove small details.
|
|
166
|
+
|
|
167
|
+
For repeated resizing, start from the original sprite rather than a previously resized version.
|
|
168
|
+
|
|
169
|
+
## API Reference
|
|
170
|
+
|
|
171
|
+
### Bite
|
|
172
|
+
|
|
173
|
+
| Method | Description |
|
|
174
|
+
| --- | --- |
|
|
175
|
+
| `Bite(structures=None, palettes=None)` | Create a manager, optionally with dictionaries of sprite structures and palette settings. |
|
|
176
|
+
| `add_sprite(sprite_id, structure)` | Create, store, and return a sprite. |
|
|
177
|
+
| `get_sprite(sprite_id)` | Return a stored sprite. |
|
|
178
|
+
| `add_palette(palette_id, foreground="black", background="")` | Create, store, and return a palette. |
|
|
179
|
+
| `get_palette(palette_id)` | Return a stored palette. |
|
|
180
|
+
|
|
181
|
+
Sprite IDs must be unique within `sprites`; palette IDs must be unique within `palettes`. The same ID can appear in both collections. Duplicate IDs raise `ValueError`; requesting a missing ID raises `KeyError`.
|
|
182
|
+
|
|
183
|
+
### Sprite
|
|
184
|
+
|
|
185
|
+
Sprite objects are created and returned by Bite.
|
|
186
|
+
|
|
187
|
+
| Attribute or method | Description |
|
|
188
|
+
| --- | --- |
|
|
189
|
+
| `structure` | The stored 2D array of binary pixels. |
|
|
190
|
+
| `width` | Width of the sprite in pixels. |
|
|
191
|
+
| `height` | Height of the sprite in pixels. |
|
|
192
|
+
| `resize(width, height)` | Return a new sprite at the requested dimensions. |
|
|
193
|
+
| `to_xbm()` | Return an XBM-formatted string for the sprite. |
|
|
194
|
+
|
|
195
|
+
### Palette
|
|
196
|
+
|
|
197
|
+
Palette objects are created and returned by Bite.
|
|
198
|
+
|
|
199
|
+
| Attribute | Description |
|
|
200
|
+
| --- | --- |
|
|
201
|
+
| `foreground` | Color used for `1` pixels. Defaults to `"black"`. |
|
|
202
|
+
| `background` | Color used for `0` pixels. Defaults to `""`. |
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
class Bite:
|
|
2
|
+
def __init__(self, structures=None, palettes=None):
|
|
3
|
+
self.sprites = {}
|
|
4
|
+
self.palettes = {}
|
|
5
|
+
|
|
6
|
+
if structures is not None:
|
|
7
|
+
for sprite_id, structure in structures.items():
|
|
8
|
+
self.add_sprite(sprite_id, structure)
|
|
9
|
+
|
|
10
|
+
if palettes is not None:
|
|
11
|
+
for palette_id, colors in palettes.items():
|
|
12
|
+
self.add_palette(palette_id, **colors)
|
|
13
|
+
|
|
14
|
+
def add_sprite(self, sprite_id, structure):
|
|
15
|
+
if sprite_id in self.sprites:
|
|
16
|
+
raise ValueError(f"Sprite ID {sprite_id!r} already exists.")
|
|
17
|
+
|
|
18
|
+
sprite = Sprite(structure)
|
|
19
|
+
self.sprites[sprite_id] = sprite
|
|
20
|
+
|
|
21
|
+
return sprite
|
|
22
|
+
|
|
23
|
+
def get_sprite(self, sprite_id):
|
|
24
|
+
return self.sprites[sprite_id]
|
|
25
|
+
|
|
26
|
+
def add_palette(self, palette_id, foreground="black", background=""):
|
|
27
|
+
if palette_id in self.palettes:
|
|
28
|
+
raise ValueError(f"Palette ID {palette_id!r} already exists.")
|
|
29
|
+
|
|
30
|
+
palette = Palette(foreground, background)
|
|
31
|
+
self.palettes[palette_id] = palette
|
|
32
|
+
|
|
33
|
+
return palette
|
|
34
|
+
|
|
35
|
+
def get_palette(self, palette_id):
|
|
36
|
+
return self.palettes[palette_id]
|
|
37
|
+
|
|
38
|
+
class Sprite:
|
|
39
|
+
def __init__(self, structure):
|
|
40
|
+
if not structure or not structure[0]:
|
|
41
|
+
raise ValueError("The sprite cannot be empty.")
|
|
42
|
+
|
|
43
|
+
width = len(structure[0])
|
|
44
|
+
|
|
45
|
+
for row in structure:
|
|
46
|
+
if len(row) != width:
|
|
47
|
+
raise ValueError("All rows must have the same length.")
|
|
48
|
+
|
|
49
|
+
for pixel in row:
|
|
50
|
+
if type(pixel) is not int or pixel not in (0, 1):
|
|
51
|
+
raise ValueError("Pixels must be integers: 0 or 1.")
|
|
52
|
+
|
|
53
|
+
self.structure = [list(row) for row in structure]
|
|
54
|
+
self.width = width
|
|
55
|
+
self.height = len(structure)
|
|
56
|
+
|
|
57
|
+
def to_xbm(self):
|
|
58
|
+
values = []
|
|
59
|
+
|
|
60
|
+
for row in self.structure:
|
|
61
|
+
for start in range(0, self.width, 8):
|
|
62
|
+
byte = 0
|
|
63
|
+
|
|
64
|
+
for offset, pixel in enumerate(row[start:start + 8]):
|
|
65
|
+
byte |= pixel << offset
|
|
66
|
+
|
|
67
|
+
values.append(f"0x{byte:02x}")
|
|
68
|
+
|
|
69
|
+
return (
|
|
70
|
+
f"#define sprite_width {self.width}\n"
|
|
71
|
+
f"#define sprite_height {self.height}\n"
|
|
72
|
+
"static unsigned char sprite_bits[] = {\n"
|
|
73
|
+
+ ", ".join(values)
|
|
74
|
+
+ "\n};"
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
def resize(self, width, height):
|
|
78
|
+
if type(width) is not int or type(height) is not int:
|
|
79
|
+
raise ValueError("Width and height must be integers.")
|
|
80
|
+
|
|
81
|
+
if width <= 0 or height <= 0:
|
|
82
|
+
raise ValueError("Width and height must be greater than zero.")
|
|
83
|
+
|
|
84
|
+
structure = []
|
|
85
|
+
|
|
86
|
+
for y in range(height):
|
|
87
|
+
source_y = y * self.height // height
|
|
88
|
+
row = []
|
|
89
|
+
|
|
90
|
+
for x in range(width):
|
|
91
|
+
source_x = x * self.width // width
|
|
92
|
+
pixel = self.structure[source_y][source_x]
|
|
93
|
+
row.append(pixel)
|
|
94
|
+
|
|
95
|
+
structure.append(row)
|
|
96
|
+
|
|
97
|
+
return Sprite(structure)
|
|
98
|
+
|
|
99
|
+
class Palette:
|
|
100
|
+
def __init__(self, foreground="black", background=""):
|
|
101
|
+
self.foreground = foreground
|
|
102
|
+
self.background = background
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: bite-core
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A lightweight library for managing binary sprites, palettes, resizing, and XBM conversion.
|
|
5
|
+
Author: Brianna Ladson
|
|
6
|
+
Keywords: bitmap,sprite,xbm,tkinter,pixel-art
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: Topic :: Multimedia :: Graphics
|
|
11
|
+
Requires-Python: >=3.10
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Dynamic: license-file
|
|
15
|
+
|
|
16
|
+
# Bite v0.1.0
|
|
17
|
+
|
|
18
|
+
Bite is a lightweight Python library for managing binary sprites and color palettes, resizing sprites, and converting them into XBM data for use with Tkinter.
|
|
19
|
+
|
|
20
|
+
Define your sprites using 2D arrays of `0`s and `1`s, store them under unique IDs, and resize them to fit the pixel space you need.
|
|
21
|
+
|
|
22
|
+
## Features
|
|
23
|
+
|
|
24
|
+
- Store multiple sprites under unique IDs.
|
|
25
|
+
- Define sprites using 2D arrays of binary integers.
|
|
26
|
+
- Store reusable foreground and background palettes.
|
|
27
|
+
- Resize sprites to an exact width and height using nearest-neighbor sampling.
|
|
28
|
+
- Convert sprite structures into XBM strings without writing XBM files.
|
|
29
|
+
- No third-party dependencies or Tkinter imports inside Bite.
|
|
30
|
+
|
|
31
|
+
Bite handles data. Your application creates and displays the images.
|
|
32
|
+
|
|
33
|
+
## Setup
|
|
34
|
+
|
|
35
|
+
Place the package folder alongside your application:
|
|
36
|
+
|
|
37
|
+
- `bite/__init__.py`
|
|
38
|
+
- `bite/bite.py`
|
|
39
|
+
- `main.py`
|
|
40
|
+
|
|
41
|
+
Then import Bite:
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
from bite import Bite
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Bite itself uses standard Python features and requires no additional packages. The example below requires a Python installation with Tkinter available.
|
|
48
|
+
|
|
49
|
+
## Quick Start
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
from bite import Bite
|
|
53
|
+
|
|
54
|
+
sprite_manager = Bite(
|
|
55
|
+
structures={
|
|
56
|
+
"house": [
|
|
57
|
+
[0, 0, 1, 0, 0],
|
|
58
|
+
[0, 1, 1, 1, 0],
|
|
59
|
+
[1, 1, 1, 1, 1],
|
|
60
|
+
[0, 1, 0, 1, 0],
|
|
61
|
+
[0, 1, 1, 1, 0],
|
|
62
|
+
],
|
|
63
|
+
},
|
|
64
|
+
palettes={
|
|
65
|
+
"parchment": {
|
|
66
|
+
"foreground": "#69432b",
|
|
67
|
+
"background": "#f3dfac",
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
sprite = sprite_manager.get_sprite("house")
|
|
73
|
+
palette = sprite_manager.get_palette("parchment")
|
|
74
|
+
|
|
75
|
+
resized_sprite = sprite.resize(width=150, height=150)
|
|
76
|
+
bitmap_data = resized_sprite.to_xbm()
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Using Bite with Tkinter
|
|
80
|
+
|
|
81
|
+
This complete example creates a sprite, applies a palette, and displays a resized bitmap on a canvas.
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
from tkinter import Tk, Canvas, BitmapImage, BOTH
|
|
85
|
+
from bite import Bite
|
|
86
|
+
|
|
87
|
+
root = Tk()
|
|
88
|
+
root.title("Bite Demo")
|
|
89
|
+
|
|
90
|
+
canvas = Canvas(root, width=500, height=500)
|
|
91
|
+
canvas.pack(fill=BOTH, expand=True)
|
|
92
|
+
|
|
93
|
+
sprite_manager = Bite()
|
|
94
|
+
|
|
95
|
+
sprite_manager.add_sprite("house", [
|
|
96
|
+
[0, 0, 1, 0, 0],
|
|
97
|
+
[0, 1, 1, 1, 0],
|
|
98
|
+
[1, 1, 1, 1, 1],
|
|
99
|
+
[0, 1, 0, 1, 0],
|
|
100
|
+
[0, 1, 1, 1, 0],
|
|
101
|
+
])
|
|
102
|
+
|
|
103
|
+
sprite_manager.add_palette(
|
|
104
|
+
"parchment",
|
|
105
|
+
foreground="#69432b",
|
|
106
|
+
background="#f3dfac",
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
sprite = sprite_manager.get_sprite("house")
|
|
110
|
+
palette = sprite_manager.get_palette("parchment")
|
|
111
|
+
resized_sprite = sprite.resize(150, 150)
|
|
112
|
+
|
|
113
|
+
image = BitmapImage(
|
|
114
|
+
master=root,
|
|
115
|
+
data=resized_sprite.to_xbm(),
|
|
116
|
+
foreground=palette.foreground,
|
|
117
|
+
background=palette.background,
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
canvas.create_image(250, 250, image=image)
|
|
121
|
+
|
|
122
|
+
root.mainloop()
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Keep a Python reference to each `BitmapImage` while it is displayed. For multiple images, you can store references in a list or dictionary.
|
|
126
|
+
|
|
127
|
+
## Sprite Structures
|
|
128
|
+
|
|
129
|
+
Each inner list represents one row. All rows must have the same length, and every value must be the integer `0` or `1`.
|
|
130
|
+
|
|
131
|
+
- `1` uses the image's foreground color.
|
|
132
|
+
- `0` uses the image's background color.
|
|
133
|
+
|
|
134
|
+
Empty structures, uneven rows, and values other than integer `0` or `1` raise `ValueError`.
|
|
135
|
+
|
|
136
|
+
Bite copies the supplied rows when creating a sprite, so later changes to the original input array do not change the stored sprite.
|
|
137
|
+
|
|
138
|
+
## Palettes
|
|
139
|
+
|
|
140
|
+
Palettes store color strings independently of sprites. The same sprite can be displayed with multiple palettes, and the same palette can be used with multiple sprites.
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
sprite_manager.add_palette(
|
|
144
|
+
"night",
|
|
145
|
+
foreground="lightblue",
|
|
146
|
+
background="midnightblue",
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
sprite_manager.add_palette(
|
|
150
|
+
"transparent",
|
|
151
|
+
foreground="darkgreen",
|
|
152
|
+
background="",
|
|
153
|
+
)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Use an empty background string for transparent `0` pixels in Tkinter. Colors are passed through unchanged; Tkinter validates them when they are applied to an image.
|
|
157
|
+
|
|
158
|
+
To change an existing Tkinter image's palette:
|
|
159
|
+
|
|
160
|
+
```python
|
|
161
|
+
palette = sprite_manager.get_palette("night")
|
|
162
|
+
|
|
163
|
+
image.configure(
|
|
164
|
+
foreground=palette.foreground,
|
|
165
|
+
background=palette.background,
|
|
166
|
+
)
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Palette colors are supplied separately to `BitmapImage`; they are not embedded in the XBM string. Changing a stored palette does not automatically update existing images.
|
|
170
|
+
|
|
171
|
+
## Resizing
|
|
172
|
+
|
|
173
|
+
```python
|
|
174
|
+
sprite = sprite_manager.get_sprite("house")
|
|
175
|
+
resized_sprite = sprite.resize(width=200, height=100)
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
`resize()` returns a new sprite and leaves the original unchanged. Width and height must be positive integers.
|
|
179
|
+
|
|
180
|
+
The sprite is stretched to exactly the requested dimensions. Each axis scales independently, so the original aspect ratio is not automatically preserved. Nearest-neighbor sampling keeps all pixels binary, although shrinking can remove small details.
|
|
181
|
+
|
|
182
|
+
For repeated resizing, start from the original sprite rather than a previously resized version.
|
|
183
|
+
|
|
184
|
+
## API Reference
|
|
185
|
+
|
|
186
|
+
### Bite
|
|
187
|
+
|
|
188
|
+
| Method | Description |
|
|
189
|
+
| --- | --- |
|
|
190
|
+
| `Bite(structures=None, palettes=None)` | Create a manager, optionally with dictionaries of sprite structures and palette settings. |
|
|
191
|
+
| `add_sprite(sprite_id, structure)` | Create, store, and return a sprite. |
|
|
192
|
+
| `get_sprite(sprite_id)` | Return a stored sprite. |
|
|
193
|
+
| `add_palette(palette_id, foreground="black", background="")` | Create, store, and return a palette. |
|
|
194
|
+
| `get_palette(palette_id)` | Return a stored palette. |
|
|
195
|
+
|
|
196
|
+
Sprite IDs must be unique within `sprites`; palette IDs must be unique within `palettes`. The same ID can appear in both collections. Duplicate IDs raise `ValueError`; requesting a missing ID raises `KeyError`.
|
|
197
|
+
|
|
198
|
+
### Sprite
|
|
199
|
+
|
|
200
|
+
Sprite objects are created and returned by Bite.
|
|
201
|
+
|
|
202
|
+
| Attribute or method | Description |
|
|
203
|
+
| --- | --- |
|
|
204
|
+
| `structure` | The stored 2D array of binary pixels. |
|
|
205
|
+
| `width` | Width of the sprite in pixels. |
|
|
206
|
+
| `height` | Height of the sprite in pixels. |
|
|
207
|
+
| `resize(width, height)` | Return a new sprite at the requested dimensions. |
|
|
208
|
+
| `to_xbm()` | Return an XBM-formatted string for the sprite. |
|
|
209
|
+
|
|
210
|
+
### Palette
|
|
211
|
+
|
|
212
|
+
Palette objects are created and returned by Bite.
|
|
213
|
+
|
|
214
|
+
| Attribute | Description |
|
|
215
|
+
| --- | --- |
|
|
216
|
+
| `foreground` | Color used for `1` pixels. Defaults to `"black"`. |
|
|
217
|
+
| `background` | Color used for `0` pixels. Defaults to `""`. |
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
bite
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77.0.3"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "bite-core"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "A lightweight library for managing binary sprites, palettes, resizing, and XBM conversion."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
authors = [
|
|
12
|
+
{ name = "Brianna Ladson" },
|
|
13
|
+
]
|
|
14
|
+
keywords = ["bitmap", "sprite", "xbm", "tkinter", "pixel-art"]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Programming Language :: Python :: 3",
|
|
17
|
+
"Operating System :: OS Independent",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"Topic :: Multimedia :: Graphics",
|
|
20
|
+
]
|
|
21
|
+
dependencies = []
|
|
22
|
+
|
|
23
|
+
[tool.setuptools]
|
|
24
|
+
packages = ["bite"]
|