joeylib2/tests/gate/common/gateImage.h

107 lines
3.9 KiB
C

// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// gateImage.h - screenshots and icons for the gate tools.
//
// A gate's screenshot (a PNG of any colour type and bit depth) or an icon
// (a BMP, or an ICO's picture) is read as RGBA, four bytes a pixel. Beside
// that: the tolerant search for an icon on a screen, the nearest of a
// palette's colours, and KEYS's palette and the row it stamps
// (examples/keys).
#ifndef GATE_IMAGE_H
#define GATE_IMAGE_H
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include "toolBuf.h"
#define GATE_RGB_BYTES 3u
#define GATE_RGBA_BYTES 4u
#define GATE_ALPHA 3u
#define GATE_KEYS_COLOURS 16u
// A picture: RGBA, four bytes a pixel, row after row.
typedef struct GateImageT {
uint32_t width;
uint32_t height;
uint8_t *rgba;
} GateImageT;
// One opaque pixel of an icon: where it is in the icon, and its colour.
typedef struct GateIconPixelT {
uint32_t x;
uint32_t y;
uint8_t rgb[GATE_RGB_BYTES];
} GateIconPixelT;
// An icon to look for: its size (it must lie wholly on the screen) and its
// opaque pixels, in the order they were added.
typedef struct GateIconT {
uint32_t width;
uint32_t height;
uint32_t count;
uint32_t cap;
GateIconPixelT *pixels;
} GateIconT;
// The squared distance between two RGB colours.
uint32_t gateDistance(const uint8_t *a, const uint8_t *b);
// Print bytes as upper-case hex, two digits a byte, to stdout.
void gateHexPrint(const uint8_t *data, size_t len);
// Add an opaque pixel to an icon (running out of memory is fatal).
void gateIconAdd(GateIconT *icon, uint32_t x, uint32_t y, const uint8_t *rgb);
// Where the screen shows the icon: every opaque pixel within tolerance a
// gun of its colour. The search anchors on the opaque pixel whose colour
// the screen holds least (the first of equals) and tries the icon at each
// place that colour is, top to bottom, left to right; the first place the
// whole icon fits and matches is the answer. An icon with no opaque pixel
// is fatal.
bool gateIconFind(const GateImageT *screen, const GateIconT *icon, uint32_t tolerance, uint32_t *left, uint32_t *top);
// Free an icon's pixels (the struct is the caller's).
void gateIconFree(GateIconT *icon);
// Free a picture's pixels (the struct is the caller's).
void gateImageFree(GateImageT *img);
// Whether (x, y) is on the picture.
bool gateImageHas(const GateImageT *img, long x, long y);
// Load a PNG, BMP, or ICO (its default picture: the largest, and of those
// the one of fewest colours). Anything unreadable is fatal.
void gateImageLoad(const char *path, GateImageT *img);
// As gateImageLoad, but an ICO gives its side x side picture of bpp bits
// (any bits when bpp is 0), else its default picture.
void gateImageLoadIcon(const char *path, uint32_t side, uint32_t bpp, GateImageT *img);
// The pixel at (x, y), which must be on the picture.
const uint8_t *gateImagePixel(const GateImageT *img, uint32_t x, uint32_t y);
// KEYS's verification row for target as bytes: the sentinel A5 A5, the
// count, a zero, then the characters. A target that is not ASCII, or is
// longer than a count byte holds, is a bad argument (gateArgBad).
void gateKeysExpect(const char *target, ToolBufT *expect);
// KEYS's palette 0 (examples/keys buildPalette) as 12-bit $0RGB words.
void gateKeysPalette(uint16_t words[GATE_KEYS_COLOURS]);
// Little-endian 16- and 32-bit numbers at p.
uint32_t gateLe16(const uint8_t *p);
uint32_t gateLe32(const uint8_t *p);
// The palette entry nearest rgb (squared distance, the first of equals),
// and that distance.
uint32_t gateNearest(const uint8_t *rgb, const uint8_t (*palette)[GATE_RGB_BYTES], uint32_t count, uint32_t *distance);
// A $0RGB word as 8-bit RGB, each 4-bit gun widened x17.
void gateRgb12(uint32_t word, uint8_t *rgb);
#endif