130 lines
3.7 KiB
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 color.
|
|
#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;
|
|
}
|