joeylib2/tests/gate/pngProbe.c

130 lines
3.7 KiB
C

// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
// See LICENSE.md for license information.
// SPDX-License-Identifier: MIT
//
// pngProbe.c - small questions the gates ask of a screenshot.
//
// pngProbe size PNG prints WxH
// pngProbe pixel PNG X Y prints R G B
// pngProbe count PNG X Y W H R G B prints how many of the W x H
// pixels from (X, Y) are R G B
//
// pixel fails (exit 1) when the point is off the screenshot; count counts
// only the part of its box on it. A bad command line exits 2.
#include <stdio.h>
#include <string.h>
#include "gateArg.h"
#include "gateImage.h"
#include "toolFile.h"
#define TOOL_NAME "pngProbe"
#define SAMPLE_MAX 255
// The arguments after a mode's name: the screenshot, a point, a box's
// size, and a colour.
#define ARG_PNG 0u
#define ARG_X 1u
#define ARG_Y 2u
#define ARG_W 3u
#define ARG_H 4u
#define ARG_RGB 5u
static int probeCount(char **args);
static int probePixel(char **args);
static int probeSize(char **args);
static const GateModeT kModes[] = {
{ "size", 1, probeSize },
{ "pixel", 3, probePixel },
{ "count", 8, probeCount }
};
static const char *const kGunNames[GATE_RGB_BYTES] = { "red", "green", "blue" };
static const char *const kUsage[] = {
"usage:",
" pngProbe size PNG prints WxH",
" pngProbe pixel PNG X Y prints R G B",
" pngProbe count PNG X Y W H R G B prints how many of the W x H pixels",
" from (X, Y) are R G B"
};
static int probeCount(char **args) {
GateImageT img;
uint8_t want[GATE_RGB_BYTES];
long x0;
long y0;
long w;
long h;
long x;
long y;
long count;
long gun;
uint32_t i;
x0 = gateArgLong("x", args[ARG_X]);
y0 = gateArgLong("y", args[ARG_Y]);
w = gateArgLong("width", args[ARG_W]);
h = gateArgLong("height", args[ARG_H]);
for (i = 0; i < GATE_RGB_BYTES; i++) {
gun = gateArgLong(kGunNames[i], args[ARG_RGB + i]);
if (gun < 0 || gun > SAMPLE_MAX) {
gateArgBad(kGunNames[i], args[ARG_RGB + i]);
}
want[i] = (uint8_t)gun;
}
gateImageLoad(args[ARG_PNG], &img);
count = 0;
for (y = (y0 < 0) ? 0 : y0; y < y0 + h && y < (long)img.height; y++) {
for (x = (x0 < 0) ? 0 : x0; x < x0 + w && x < (long)img.width; x++) {
if (memcmp(gateImagePixel(&img, (uint32_t)x, (uint32_t)y), want, GATE_RGB_BYTES) == 0) {
count++;
}
}
}
printf("%ld\n", count);
gateImageFree(&img);
return 0;
}
static int probePixel(char **args) {
GateImageT img;
const uint8_t *rgb;
long x;
long y;
x = gateArgLong("x", args[ARG_X]);
y = gateArgLong("y", args[ARG_Y]);
gateImageLoad(args[ARG_PNG], &img);
if (!gateImageHas(&img, x, y)) {
toolFail("%ld,%ld is off the %ux%u screenshot", x, y, (unsigned)img.width, (unsigned)img.height);
}
rgb = gateImagePixel(&img, (uint32_t)x, (uint32_t)y);
printf("%u %u %u\n", (unsigned)rgb[0], (unsigned)rgb[1], (unsigned)rgb[2]);
gateImageFree(&img);
return 0;
}
static int probeSize(char **args) {
GateImageT img;
gateImageLoad(args[ARG_PNG], &img);
printf("%ux%u\n", (unsigned)img.width, (unsigned)img.height);
gateImageFree(&img);
return 0;
}
int main(int argc, char **argv) {
int exitCode;
toolFileName(TOOL_NAME);
if (!gateModeRun(kModes, GATE_COUNT_OF(kModes), argc, argv, &exitCode)) {
return gateUsage(kUsage, GATE_COUNT_OF(kUsage));
}
return exitCode;
}