Add -% to blind-to-text, blind-colour-srgb, and blind-colour-ciexyz - blind - s… | |
git clone git://git.suckless.org/blind | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit bcac04b4316d64063e743e7a49195173a0c175a0 | |
parent 4154609e5de76bc8858d3f86e0af09ba2700c488 | |
Author: Mattias Andrée <[email protected]> | |
Date: Sun, 24 Sep 2017 01:26:08 +0200 | |
Add -% to blind-to-text, blind-colour-srgb, and blind-colour-ciexyz | |
Signed-off-by: Mattias Andrée <[email protected]> | |
Diffstat: | |
M TODO | 2 -- | |
M man/blind-colour-ciexyz.1 | 38 +++++++++++++++++++++++++++++… | |
M man/blind-colour-srgb.1 | 31 +++++++++++++++++++++++++++++… | |
M man/blind-to-text.1 | 39 +++++++++++++++++++++++++++++… | |
M src/blind-colour-ciexyz.c | 20 +++++++++++++++++--- | |
M src/blind-colour-srgb.c | 10 ++++++++-- | |
M src/blind-to-text.c | 27 ++++++++++++++++++--------- | |
M src/define-functions.h | 14 -------------- | |
M src/stream.c | 154 +++++++++++++++++++++++++++++… | |
M src/stream.h | 2 ++ | |
M src/util.c | 6 +++++- | |
11 files changed, 312 insertions(+), 31 deletions(-) | |
--- | |
diff --git a/TODO b/TODO | |
@@ -35,8 +35,6 @@ blind-preview a graphical tool for previewing … | |
should have sliders to tune environment variab… | |
--- tool from creating blockwise transitions | |
-blind-to-text, blind-from-text: support %a, %e, %g, and custom precision | |
- | |
Add [-j jobs] to blind-from-video, blind-to-video, blind-convert, and blind-ap… | |
long double is slightly faster than long. | |
diff --git a/man/blind-colour-ciexyz.1 b/man/blind-colour-ciexyz.1 | |
@@ -3,6 +3,8 @@ | |
blind-colour-ciexyz - Convert CIE XYZ for use with blind-single-colour(1) | |
.SH SYNOPSIS | |
.B blind-colour-ciexyz | |
+[-% | |
+.IR format ] | |
.RI ( X | |
.I Y | |
.I Z | |
@@ -21,6 +23,42 @@ that colour model. If only | |
is specified, the colour will be CIE Standard Illuminant D65-grey | |
with a luminosity of | |
.IR Y . | |
+.SH OPTIONS | |
+.TP | |
+.BR -% \ \fIformat\fP | |
+Selects in what format parameters are printed. | |
+.I format | |
+may include the prefix | |
+.B + | |
+that specified that non-negative values should be prefixed with a | |
+.BR + . | |
+After any prefix, there may be a positive number specifying | |
+the percision of the output, optionally followed by either of | |
+the letters | |
+.BR a , | |
+.BR e , | |
+.BR f , | |
+other | |
+.B g | |
+(other their synonymous uppercases), | |
+at most once, with the same semantics as in | |
+.BR printf (3). | |
+.B f | |
+is used if this letter is omitted. | |
+ | |
+If ommited, | |
+.B 25f | |
+is used unless all three of | |
+.IR X , | |
+.IR Y , | |
+and | |
+.I Z | |
+is specified, in which case the parameters are | |
+printed as-is. This default is selected for ease | |
+of interoperability with other software, however, | |
+.B a | |
+is recommeded to improve performance and remove | |
+truncation error. | |
.SH SEE ALSO | |
.BR blind (7), | |
.BR blind-single-colour (1), | |
diff --git a/man/blind-colour-srgb.1 b/man/blind-colour-srgb.1 | |
@@ -3,6 +3,8 @@ | |
blind-colour-srgb - Convert sRGB for use with blind-single-colour(1) and blind… | |
.SH SYNOPSIS | |
.B blind-colour-srgb | |
+[-% | |
+.IR format ] | |
[-d | |
.IR depth ] | |
[-l] | |
@@ -38,6 +40,35 @@ unsigned integer with | |
bits. | |
.SH OPTIONS | |
.TP | |
+.BR -% \ \fIformat\fP | |
+Selects in what format parameters are printed. | |
+.I format | |
+may include the prefix | |
+.B + | |
+that specified that non-negative values should be prefixed with a | |
+.BR + . | |
+After any prefix, there may be a positive number specifying | |
+the percision of the output, optionally followed by either of | |
+the letters | |
+.BR a , | |
+.BR e , | |
+.BR f , | |
+other | |
+.B g | |
+(other their synonymous uppercases), | |
+at most once, with the same semantics as in | |
+.BR printf (3). | |
+.B f | |
+is used if this letter is omitted. | |
+ | |
+If ommited, | |
+.B 25f | |
+is used. This default is selected for ease of | |
+interoperability with other software, however, | |
+.B a | |
+is recommeded to improve performance and remove | |
+truncation error. | |
+.TP | |
.BR -d " "\fIdepth\fP | |
If all three parameters are | |
.RI 2^ depth -1, | |
diff --git a/man/blind-to-text.1 b/man/blind-to-text.1 | |
@@ -3,6 +3,8 @@ | |
blind-to-text - Convert a video to text | |
.SH SYNOPSIS | |
.B blind-to-text | |
+[-% | |
+.IR format ] | |
.SH DESCRIPTION | |
.B blind-to-text | |
reads a video from stdin and prints it | |
@@ -36,6 +38,43 @@ line, after the head, where the second | |
frame begins. The pixels are printed | |
from left to right, from top to bottom, | |
and from first frame to last frame. | |
+.SH OPTIONS | |
+.TP | |
+.BR -% \ \fIformat\fP | |
+Selects in what format parameters are printed. | |
+.I format | |
+may include the prefix | |
+.B + | |
+that specified that non-negative values should be prefixed with a | |
+.BR + . | |
+After any prefix, there may be a positive number specifying | |
+the percision of the output, optionally followed by either of | |
+the letters | |
+.BR a , | |
+.BR e , | |
+.BR f , | |
+other | |
+.B g | |
+(other their synonymous uppercases), | |
+or if the input is integer typed, | |
+.B d | |
+or | |
+.BR i , | |
+at most once, with the same semantics as in | |
+.BR printf (3). | |
+.B f | |
+is used if this letter is omitted. | |
+The percision must be omitted the input is integer typed. | |
+ | |
+If ommited, | |
+.B 25f | |
+or | |
+.B i | |
+is used. These defaults are selected for ease of | |
+interoperability with other software, however, | |
+.B a | |
+is recommeded to improve performance and remove | |
+truncation error. | |
.SH SEE ALSO | |
.BR blind (7), | |
.BR blind-from-text (1), | |
diff --git a/src/blind-colour-ciexyz.c b/src/blind-colour-ciexyz.c | |
@@ -1,20 +1,34 @@ | |
/* See LICENSE file for copyright and license details. */ | |
#include "common.h" | |
-USAGE("(X Y Z | Y)") | |
+USAGE("[-% format] (X Y Z | Y)") | |
int | |
main(int argc, char *argv[]) | |
{ | |
double X, Y, Z; | |
+ const char *fmt = NULL; | |
- UNOFLAGS(0); | |
+ ARGBEGIN { | |
+ case '%': | |
+ fmt = UARGF(); | |
+ break; | |
+ default: | |
+ usage(); | |
+ } ARGEND; | |
if (argc == 1) { | |
+ fmt = select_print_format("%! %! %!\n", DOUBLE, fmt); | |
Y = etolf_arg("the Y value", argv[0]); | |
X = Y * D65_XYZ_X; | |
Z = Y * D65_XYZ_Z; | |
- printf("%.50lf %.50lf %.50lf\n", X, Y, Z); | |
+ printf(fmt, X, Y, Z); | |
+ } else if (argc == 3 && fmt) { | |
+ fmt = select_print_format("%! %! %!\n", DOUBLE, fmt); | |
+ X = etolf_arg("the X value", argv[0]); | |
+ Y = etolf_arg("the Y value", argv[1]); | |
+ Z = etolf_arg("the Z value", argv[2]); | |
+ printf(fmt, X, Y, Z); | |
} else if (argc == 3) { | |
printf("%s %s %s\n", argv[0], argv[1], argv[2]); | |
} else { | |
diff --git a/src/blind-colour-srgb.c b/src/blind-colour-srgb.c | |
@@ -1,7 +1,7 @@ | |
/* See LICENSE file for copyright and license details. */ | |
#include "common.h" | |
-USAGE("[-d depth] [-l] red green blue") | |
+USAGE("[-% format] [-d depth] [-l] red green blue") | |
int | |
main(int argc, char *argv[]) | |
@@ -9,6 +9,7 @@ main(int argc, char *argv[]) | |
unsigned long long int max; | |
double red, green, blue, X, Y, Z; | |
int depth = 8, linear = 0; | |
+ const char *fmt = NULL; | |
ARGBEGIN { | |
case 'd': | |
@@ -17,6 +18,9 @@ main(int argc, char *argv[]) | |
case 'l': | |
linear = 1; | |
break; | |
+ case '%': | |
+ fmt = UARGF(); | |
+ break; | |
default: | |
usage(); | |
} ARGEND; | |
@@ -24,6 +28,8 @@ main(int argc, char *argv[]) | |
if (argc != 3) | |
usage(); | |
+ fmt = select_print_format("%! %! %!\n", DOUBLE, fmt); | |
+ | |
max = 1ULL << (depth - 1); | |
max |= max - 1; | |
red = etolf_arg("the red value", argv[0]) / (double)max; | |
@@ -36,7 +42,7 @@ main(int argc, char *argv[]) | |
} | |
srgb_to_ciexyz(red, green, blue, &X, &Y, &Z); | |
- printf("%.50lf %.50lf %.50lf\n", X, Y, Z); | |
+ printf(fmt, X, Y, Z); | |
efshut(stdout, "<stdout>"); | |
return 0; | |
} | |
diff --git a/src/blind-to-text.c b/src/blind-to-text.c | |
@@ -3,7 +3,9 @@ | |
#define INCLUDE_UINT16 | |
#include "common.h" | |
-USAGE("") | |
+USAGE("[-% format]") | |
+ | |
+const char *fmt = NULL; | |
#define FILE "blind-to-text.c" | |
#include "define-functions.h" | |
@@ -14,10 +16,19 @@ main(int argc, char *argv[]) | |
struct stream stream; | |
void (*process)(struct stream *stream, size_t n); | |
- UNOFLAGS(argc); | |
+ ARGBEGIN { | |
+ case '%': | |
+ fmt = UARGF(); | |
+ break; | |
+ default: | |
+ usage(); | |
+ } ARGEND; | |
- eopen_stream(&stream, NULL); | |
+ if (argc) | |
+ usage(); | |
+ eopen_stream(&stream, NULL); | |
+ fmt = select_print_format("%! %! %! %!\n", stream.encoding, fmt); | |
SELECT_PROCESS_FUNCTION(&stream); | |
printf("%zu %zu %zu %s\n", stream.frames, stream.width, stream.height,… | |
process_stream(&stream, process); | |
@@ -32,12 +43,10 @@ PROCESS(struct stream *stream, size_t n) | |
{ | |
size_t i; | |
TYPE *p = (TYPE *)(stream->buf); | |
- for (i = 0, n /= stream->chan_size; i < n; i++) | |
-#ifdef INTEGER_TYPE | |
- printf("%"PRINT_TYPE"%c", (PRINT_CAST)(p[i]), (i + 1) % stream… | |
-#else | |
- printf("%.25"PRINT_TYPE"%c", (PRINT_CAST)(p[i]), (i + 1) % str… | |
-#endif | |
+ for (i = 0, n /= stream->chan_size; i < n; i += 4) { | |
+ printf(fmt, (PRINT_CAST)(p[i + 0]), (PRINT_CAST)(p[i + 1]), | |
+ (PRINT_CAST)(p[i + 2]), (PRINT_CAST)(p[i + 3])); | |
+ } | |
} | |
#endif | |
diff --git a/src/define-functions.h b/src/define-functions.h | |
@@ -4,13 +4,11 @@ | |
# define PROCESS process_lf | |
# define TYPE double | |
# define SCAN_TYPE "lf" | |
-# define PRINT_TYPE "lf" | |
# define PRINT_CAST double | |
# include FILE | |
# undef PROCESS | |
# undef TYPE | |
# undef SCAN_TYPE | |
-# undef PRINT_TYPE | |
# undef PRINT_CAST | |
#endif | |
@@ -18,13 +16,11 @@ | |
# define PROCESS process_f | |
# define TYPE float | |
# define SCAN_TYPE "f" | |
-# define PRINT_TYPE "lf" | |
# define PRINT_CAST double | |
# include FILE | |
# undef PROCESS | |
# undef TYPE | |
# undef SCAN_TYPE | |
-# undef PRINT_TYPE | |
# undef PRINT_CAST | |
#endif | |
@@ -32,13 +28,11 @@ | |
# define PROCESS process_llf | |
# define TYPE long double | |
# define SCAN_TYPE "Lf" | |
-# define PRINT_TYPE "Lf" | |
# define PRINT_CAST long double | |
# include FILE | |
# undef PROCESS | |
# undef TYPE | |
# undef SCAN_TYPE | |
-# undef PRINT_TYPE | |
# undef PRINT_CAST | |
#endif | |
@@ -46,14 +40,12 @@ | |
# define PROCESS process_u8 | |
# define TYPE uint8_t | |
# define SCAN_TYPE SCNu8 | |
-# define PRINT_TYPE "u" | |
# define PRINT_CAST unsigned | |
# define INTEGER_TYPE | |
# include FILE | |
# undef PROCESS | |
# undef TYPE | |
# undef SCAN_TYPE | |
-# undef PRINT_TYPE | |
# undef PRINT_CAST | |
# undef INTEGER_TYPE | |
#endif | |
@@ -62,14 +54,12 @@ | |
# define PROCESS process_u16 | |
# define TYPE uint16_t | |
# define SCAN_TYPE SCNu16 | |
-# define PRINT_TYPE "u" | |
# define PRINT_CAST unsigned | |
# define INTEGER_TYPE | |
# include FILE | |
# undef PROCESS | |
# undef TYPE | |
# undef SCAN_TYPE | |
-# undef PRINT_TYPE | |
# undef PRINT_CAST | |
# undef INTEGER_TYPE | |
#endif | |
@@ -78,14 +68,12 @@ | |
# define PROCESS process_u32 | |
# define TYPE uint32_t | |
# define SCAN_TYPE SCNu32 | |
-# define PRINT_TYPE PRIu32 | |
# define PRINT_CAST uint32_t | |
# define INTEGER_TYPE | |
# include FILE | |
# undef PROCESS | |
# undef TYPE | |
# undef SCAN_TYPE | |
-# undef PRINT_TYPE | |
# undef PRINT_CAST | |
# undef INTEGER_TYPE | |
#endif | |
@@ -94,14 +82,12 @@ | |
# define PROCESS process_u64 | |
# define TYPE uint64_t | |
# define SCAN_TYPE SCNu64 | |
-# define PRINT_TYPE PRIu64 | |
# define PRINT_CAST uint64_t | |
# define INTEGER_TYPE | |
# include FILE | |
# undef PROCESS | |
# undef TYPE | |
# undef SCAN_TYPE | |
-# undef PRINT_TYPE | |
# undef PRINT_CAST | |
# undef INTEGER_TYPE | |
#endif | |
diff --git a/src/stream.c b/src/stream.c | |
@@ -369,6 +369,160 @@ get_pixel_format(const char *specified, const char *curre… | |
} | |
+const char * | |
+nselect_print_format(int status, const char *format, enum encoding encoding, c… | |
+{ | |
+ static char retbuf[512]; | |
+ int with_plus = 0, inttyped = -1; | |
+ const char *f = "", *orig = fmt; | |
+ char *proto = alloca((fmt ? strlen(fmt) : 0) + sizeof("%+#.50llx")), *… | |
+ char *ret = retbuf; | |
+ size_t n, len; | |
+ | |
+ if (!orig) | |
+ goto check_done; | |
+ | |
+ for (; *fmt == '+'; fmt++) | |
+ with_plus = 1; | |
+ f = fmt + strspn(fmt, "0123456789"); | |
+ if (f[0] && f[1]) | |
+ enprintf(status, "invalid format: %s\n", orig); | |
+ | |
+ switch (*f) { | |
+ case '\0': | |
+ inttyped = -1; | |
+ break; | |
+ case 'd': case 'i': | |
+ inttyped = 1; | |
+ break; | |
+ case 'a': case 'A': | |
+ case 'e': case 'E': | |
+ case 'f': case 'F': | |
+ case 'g': case 'G': | |
+ inttyped = 0; | |
+ break; | |
+ default: | |
+ enprintf(status, "invalid format: %s\n", orig); | |
+ } | |
+ | |
+ switch (encoding) { | |
+ case FLOAT: | |
+ case DOUBLE: | |
+ case LONG_DOUBLE: | |
+ if (inttyped == 1) | |
+ enprintf(status, "invalid format `%s' is incompatible … | |
+ inttyped = 0; | |
+ break; | |
+ case UINT8: | |
+ case UINT16: | |
+ case UINT32: | |
+ case UINT64: | |
+ if (*f != *fmt) | |
+ enprintf(status, "invalid format: %s\n", orig); | |
+ if (inttyped == 0) | |
+ enprintf(status, "invalid format `%s' is incompatible … | |
+ inttyped = 1; | |
+ break; | |
+ default: | |
+ abort(); | |
+ } | |
+check_done: | |
+ | |
+ p = proto; | |
+ *p++ = '%'; | |
+ if (with_plus) | |
+ *p++ = '+'; | |
+ | |
+ if (orig && *f != *fmt) { | |
+ *p++ = '.'; | |
+ p = stpncpy(p, fmt, (size_t)(f - fmt)); | |
+ } else if (orig && inttyped && *f != 'a' && *f != 'A') { | |
+ *p++ = '.'; | |
+ *p++ = '2'; | |
+ *p++ = '5'; | |
+ } | |
+ | |
+ inttyped = 1; | |
+ switch (encoding) { | |
+ case FLOAT: | |
+ inttyped = 0; | |
+ break; | |
+ case DOUBLE: | |
+ *p++ = 'l'; | |
+ inttyped = 0; | |
+ break; | |
+ case LONG_DOUBLE: | |
+ *p++ = 'L'; | |
+ inttyped = 0; | |
+ break; | |
+ case UINT8: | |
+ fmt = PRIi8; | |
+ break; | |
+ case UINT16: | |
+ fmt = PRIi16; | |
+ break; | |
+ case UINT32: | |
+ fmt = PRIi32; | |
+ break; | |
+ case UINT64: | |
+ fmt = PRIi64; | |
+ break; | |
+ default: | |
+ abort(); | |
+ } | |
+ | |
+ if (inttyped) | |
+ while (*fmt == 'l') | |
+ *p++ = *fmt++; | |
+ | |
+ switch (orig ? *f : '\0') { | |
+ case '\0': | |
+ *p++ = inttyped ? 'i' : 'f'; | |
+ break; | |
+ case 'd': case 'i': | |
+ *p++ = 'i'; | |
+ break; | |
+ case 'a': case 'A': | |
+ *p++ = 'a'; | |
+ break; | |
+ case 'e': case 'E': | |
+ *p++ = 'e'; | |
+ break; | |
+ case 'f': case 'F': | |
+ *p++ = 'f'; | |
+ break; | |
+ case 'g': case 'G': | |
+ *p++ = 'g'; | |
+ break; | |
+ } | |
+ | |
+ *p = '\0'; | |
+ | |
+ len = strlen(proto); | |
+ for (n = 1, f = format; *f; f++) { | |
+ if (f[0] == '%' && f[1] == '!') { | |
+ f++; | |
+ n += len; | |
+ } else { | |
+ n++; | |
+ } | |
+ } | |
+ | |
+ if (n > sizeof(retbuf)) | |
+ ret = enmalloc(status, n); | |
+ for (p = ret, f = format; *f; f++) { | |
+ if (f[0] == '%' && f[1] == '!') { | |
+ f++; | |
+ p = stpcpy(p, proto); | |
+ } else { | |
+ *p++ = *f; | |
+ } | |
+ } | |
+ | |
+ return ret; | |
+} | |
+ | |
+ | |
int | |
enread_segment(int status, struct stream *stream, void *buf, size_t n) | |
{ | |
diff --git a/src/stream.h b/src/stream.h | |
@@ -43,6 +43,7 @@ | |
#define echeck_dimensions(...) encheck_dimensions(1, __VA_ARGS__) | |
#define echeck_dimensions_custom(...) encheck_dimensions_custom(1, __VA_ARGS__) | |
#define echeck_compat(...) encheck_compat(1, __VA_ARGS__) | |
+#define select_print_format(...) nselect_print_format(1, __VA_ARGS__) | |
#define eread_segment(...) enread_segment(1, __VA_ARGS__) | |
#define eread_frame(...) enread_frame(1, __VA_ARGS__) | |
#define eread_row(...) enread_row(1, __VA_ARGS__) | |
@@ -128,6 +129,7 @@ void eninf_check_fd(int status, int fd, const char *file); | |
void encheck_dimensions(int status, const struct stream *stream, enum dimensio… | |
void encheck_compat(int status, const struct stream *a, const struct stream *b… | |
const char *get_pixel_format(const char *specified, const char *current); | |
+const char *nselect_print_format(int status, const char *format, enum encoding… | |
int enread_segment(int status, struct stream *stream, void *buf, size_t n); | |
size_t ensend_frames(int status, struct stream *stream, int outfd, size_t fram… | |
size_t ensend_rows(int status, struct stream *stream, int outfd, size_t rows, … | |
diff --git a/src/util.c b/src/util.c | |
@@ -6,6 +6,7 @@ char *argv0; | |
void | |
weprintf(const char *fmt, ...) | |
{ | |
+ char end; | |
va_list ap; | |
va_start(ap, fmt); | |
@@ -14,9 +15,12 @@ weprintf(const char *fmt, ...) | |
vfprintf(stderr, fmt, ap); | |
- if (fmt[0] && fmt[strlen(fmt)-1] == ':') { | |
+ end = *fmt ? strchr(fmt, '\0')[-1] : '\n'; | |
+ if (end == ':') { | |
fputc(' ', stderr); | |
perror(NULL); | |
+ } else if (end != '\n') { | |
+ fputc('\n', stderr); | |
} | |
va_end(ap); |