mirror of
https://git.planet-casio.com/Lephenixnoir/fxsdk.git
synced 2024-12-28 20:43:37 +01:00
133 lines
3 KiB
C
133 lines
3 KiB
C
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
#include <fxg1a.h>
|
||
|
#include <png.h>
|
||
|
|
||
|
/* icon_print(): Show a monochrome 30*17 icon on stdout */
|
||
|
void icon_print(uint8_t const *icon)
|
||
|
{
|
||
|
for(int y = 0; y < 17; y++)
|
||
|
{
|
||
|
for(int x = 0; x < 30; x++)
|
||
|
{
|
||
|
int v = icon[(y << 2) + (x >> 3)] & (0x80 >> (x & 7));
|
||
|
putchar(v ? '#' : ' ');
|
||
|
putchar(v ? '#' : ' ');
|
||
|
}
|
||
|
|
||
|
putchar('\n');
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* icon_load(): Load a monochrome PNG image into an array */
|
||
|
uint8_t *icon_load(const char *filename, size_t *width, size_t *height)
|
||
|
{
|
||
|
png_image img;
|
||
|
memset(&img, 0, sizeof img);
|
||
|
img.opaque = NULL;
|
||
|
img.version = PNG_IMAGE_VERSION;
|
||
|
|
||
|
png_image_begin_read_from_file(&img, filename);
|
||
|
if(img.warning_or_error)
|
||
|
{
|
||
|
fprintf(stderr, "libpng %s: %s\n", img.warning_or_error == 1
|
||
|
? "warning": "error", img.message);
|
||
|
if(img.warning_or_error > 1)
|
||
|
{
|
||
|
png_image_free(&img);
|
||
|
return NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
img.format = PNG_FORMAT_GRAY;
|
||
|
|
||
|
void *buffer = calloc(img.width * img.height, 1);
|
||
|
if(!buffer)
|
||
|
{
|
||
|
fprintf(stderr, "error: cannot read %s: %m\n", filename);
|
||
|
png_image_free(&img);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
png_image_finish_read(&img, NULL, buffer, img.width, NULL);
|
||
|
if(width) *width = img.width;
|
||
|
if(height) *height = img.height;
|
||
|
|
||
|
png_image_free(&img);
|
||
|
return buffer;
|
||
|
}
|
||
|
|
||
|
/* icon_save(): Save an 8-bit array to a PNG image */
|
||
|
int icon_save(const char *filename, uint8_t *input, size_t width,
|
||
|
size_t height)
|
||
|
{
|
||
|
png_image img;
|
||
|
memset(&img, 0, sizeof img);
|
||
|
|
||
|
img.version = PNG_IMAGE_VERSION;
|
||
|
img.width = width;
|
||
|
img.height = height;
|
||
|
img.format = PNG_FORMAT_GRAY;
|
||
|
|
||
|
png_image_write_to_file(&img, filename, 0, input, 0, NULL);
|
||
|
png_image_free(&img);
|
||
|
|
||
|
if(img.warning_or_error)
|
||
|
{
|
||
|
fprintf(stderr, "libpng %s: %s\n", img.warning_or_error == 1
|
||
|
? "warning": "error", img.message);
|
||
|
if(img.warning_or_error > 1) return 1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/* icon_conv_8to1(): Convert an 8-bit icon to 1-bit */
|
||
|
uint8_t *icon_conv_8to1(uint8_t const *input, size_t width, size_t height)
|
||
|
{
|
||
|
if(!input) return NULL;
|
||
|
uint8_t *mono = calloc(68, 1);
|
||
|
if(!mono) return NULL;
|
||
|
size_t stride = width;
|
||
|
|
||
|
/* If the image is wider than 30 pixels, ignore columns at the right */
|
||
|
if(width > 30) width = 30;
|
||
|
|
||
|
/* Skip the first line if there is enough rows, because in standard
|
||
|
30*19 icons, the first and last lines are skipped */
|
||
|
if(height > 17) input += stride, height--;
|
||
|
|
||
|
/* If height is still larger than 17, ignore rows at the bottom */
|
||
|
if(height > 17) height = 17;
|
||
|
|
||
|
/* Then copy individual pixels on the currently-blank image */
|
||
|
for(size_t y = 0; y < height; y++)
|
||
|
for(size_t x = 0; x < width; x++)
|
||
|
{
|
||
|
int offset = (y << 2) + (x >> 3);
|
||
|
int color = input[y * stride + x] < 128;
|
||
|
uint8_t mask = color << (~x & 7);
|
||
|
mono[offset] |= mask;
|
||
|
}
|
||
|
|
||
|
return mono;
|
||
|
}
|
||
|
|
||
|
/* icon_conv_1to8(): Convert an 1-bit icon to 8-bit */
|
||
|
uint8_t *icon_conv_1to8(uint8_t const *mono)
|
||
|
{
|
||
|
uint8_t *data = calloc(30 * 17, 1);
|
||
|
if(!data) return NULL;
|
||
|
|
||
|
for(int y = 0; y < 17; y++)
|
||
|
for(int x = 0; x < 30; x++)
|
||
|
{
|
||
|
int offset = (y << 2) + (x >> 3);
|
||
|
int bit = mono[offset] & (0x80 >> (x & 7));
|
||
|
data[y * 30 + x] = (bit ? 0x00 : 0xff);
|
||
|
}
|
||
|
|
||
|
return data;
|
||
|
}
|