2 256boss - bootable launcher for 256byte intros
3 Copyright (C) 2018-2019 John Tsiombikas <nuclear@member.fsf.org>
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.
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.
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/>.
26 int alloc_image(struct image *img, int x, int y, int bpp)
28 memset(img, 0, sizeof *img);
32 img->scansz = img->pitch = x * bpp / 8;
34 if(!(img->pixels = malloc(y * img->scansz))) {
35 printf("failed to allocate %dx%d (%dbpp) pixel buffer\n", x, y, bpp);
39 /* just a guess, assume the user will fill the details, but set up reasonable
40 * defaults just in case...
44 img->cmap_ncolors = 1 << bpp;
45 } else if(bpp <= 24) {
53 int load_image(struct image *img, const char *fname)
59 int chan_bits, color_type;
62 unsigned char **scanline;
65 if(!(fp = fopen(fname, "rb"))) {
66 printf("failed to open: %s: %s\n", fname, strerror(errno));
70 if(!(png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0))) {
74 if(!(info = png_create_info_struct(png))) {
76 png_destroy_read_struct(&png, 0, 0);
79 if(setjmp(png_jmpbuf(png))) {
81 png_destroy_read_struct(&png, &info, 0);
86 png_read_png(png, info, 0, 0);
88 png_get_IHDR(png, info, &xsz, &ysz, &chan_bits, &color_type, 0, 0, 0);
91 img->nchan = png_get_channels(png, info);
92 img->bpp = img->nchan * chan_bits;
93 img->scansz = img->pitch = xsz * img->bpp / 8;
94 img->cmap_ncolors = 0;
96 if(color_type == PNG_COLOR_TYPE_PALETTE) {
97 png_get_PLTE(png, info, &palette, &img->cmap_ncolors);
98 memcpy(img->cmap, palette, img->cmap_ncolors * sizeof *img->cmap);
101 if(!(img->pixels = malloc(ysz * img->scansz))) {
102 perror("failed to allocate pixel buffer");
104 png_destroy_read_struct(&png, &info, 0);
109 scanline = (unsigned char**)png_get_rows(png, info);
110 for(i=0; i<ysz; i++) {
111 memcpy(dptr, scanline[i], img->scansz);
116 png_destroy_read_struct(&png, &info, 0);
120 int save_image(struct image *img, const char *fname)
122 int i, chan_bits, coltype;
127 unsigned char **scanline = 0;
130 if(!(fp = fopen(fname, "wb"))) {
131 printf("save_image: failed to open: %s: %s\n", fname, strerror(errno));
135 if(!(png = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0))) {
139 if(!(info = png_create_info_struct(png))) {
140 png_destroy_write_struct(&png, 0);
145 txt.compression = PNG_TEXT_COMPRESSION_NONE;
146 txt.key = "Software";
147 txt.text = "img2tiles";
150 if(setjmp(png_jmpbuf(png))) {
151 png_destroy_write_struct(&png, &info);
159 if(img->cmap_ncolors > 0) {
160 coltype = PNG_COLOR_TYPE_PALETTE;
162 coltype = PNG_COLOR_TYPE_GRAY;
166 coltype = PNG_COLOR_TYPE_GRAY_ALPHA;
169 coltype = PNG_COLOR_TYPE_RGB;
172 coltype = PNG_COLOR_TYPE_RGB_ALPHA;
176 chan_bits = img->bpp / img->nchan;
177 png_set_IHDR(png, info, img->width, img->height, chan_bits, coltype, PNG_INTERLACE_NONE,
178 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
179 png_set_text(png, info, &txt, 1);
181 if(img->cmap_ncolors > 0) {
182 png_set_PLTE(png, info, (png_color*)img->cmap, img->cmap_ncolors);
185 if(!(scanline = malloc(img->height * sizeof *scanline))) {
186 png_destroy_write_struct(&png, &info);
192 for(i=0; i<img->height; i++) {
196 png_set_rows(png, info, scanline);
198 png_init_io(png, fp);
199 png_write_png(png, info, 0, 0);
200 png_destroy_write_struct(&png, &info);
207 int cmp_image(struct image *a, struct image *b)
210 unsigned char *aptr = a->pixels;
211 unsigned char *bptr = b->pixels;
213 if(a->width != b->width || a->height != b->height || a->bpp != b->bpp || a->nchan != b->nchan) {
217 for(i=0; i<a->height; i++) {
218 if(memcmp(aptr, bptr, a->scansz) != 0) {
227 void blit_image(struct image *src, int sx, int sy, int w, int h, struct image *dst, int dx, int dy)
230 unsigned char *sptr, *dptr;
232 assert(src->bpp == dst->bpp);
233 assert(src->nchan == dst->nchan);
235 if(sx < 0) { w += sx; sx = 0; }
236 if(sy < 0) { h += sy; sy = 0; }
237 if(dx < 0) { w += dx; sx -= dx; dx = 0; }
238 if(dy < 0) { h += dy; sy -= dy; dy = 0; }
239 if(sx + w >= src->width) w = src->width - sx;
240 if(sy + h >= src->height) h = src->height - sy;
241 if(dx + w >= dst->width) w = dst->width - dx;
242 if(dy + h >= dst->height) h = dst->height - dy;
244 if(w <= 0 || h <= 0) return;
246 sptr = src->pixels + sy * src->pitch + sx * src->bpp / 8;
247 dptr = dst->pixels + dy * dst->pitch + dx * dst->bpp / 8;
250 memcpy(dptr, sptr, w * dst->bpp / 8);
256 void image_color_offset(struct image *img, int offs)
258 int i, sz = img->height * img->pitch;
259 unsigned char *pptr = img->pixels;
261 for(i=0; i<sz; i++) {