diff options
author | Mattias Andrée <m@maandree.se> | 2025-03-03 16:43:19 +0100 |
---|---|---|
committer | Mattias Andrée <m@maandree.se> | 2025-03-03 16:44:37 +0100 |
commit | e114123df2a05650f0f7e34044c1e8f829c50a44 (patch) | |
tree | 48c408b469d5fc3f1acdf4468ad6f22da8a65370 | |
parent | m (diff) | |
download | liblss16-e114123df2a05650f0f7e34044c1e8f829c50a44.tar.gz liblss16-e114123df2a05650f0f7e34044c1e8f829c50a44.tar.bz2 liblss16-e114123df2a05650f0f7e34044c1e8f829c50a44.tar.xz |
misc
Signed-off-by: Mattias Andrée <m@maandree.se>
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Makefile | 23 | ||||
-rw-r--r-- | README | 50 | ||||
-rw-r--r-- | TODO | 3 | ||||
-rw-r--r-- | config.mk | 6 | ||||
-rw-r--r-- | liblss16.7 | 62 | ||||
-rw-r--r-- | liblss16.h | 44 | ||||
-rw-r--r-- | liblss16_decode_strerror.3 | 43 | ||||
-rw-r--r-- | liblss16_decode_strerror.c | 2 | ||||
-rw-r--r-- | liblss16_decode_to_colour_index.3 | 221 | ||||
-rw-r--r-- | liblss16_decode_to_colour_index.c | 8 | ||||
-rw-r--r-- | liblss16_decoder_init.3 | 41 | ||||
-rw-r--r-- | liblss16_encode_from_colour_index.3 | 108 | ||||
-rw-r--r-- | liblss16_encode_from_colour_index.c | 16 | ||||
-rw-r--r-- | liblss16_encode_strerror.3 | 43 | ||||
-rw-r--r-- | liblss16_encode_strerror.c | 5 | ||||
-rw-r--r-- | liblss16_encoder_init.3 | 125 | ||||
-rw-r--r-- | liblss16_encoder_init.c | 4 | ||||
-rw-r--r-- | liblss16_optimise.3 | 81 | ||||
-rw-r--r-- | liblss16_optimise.c | 8 | ||||
-rw-r--r-- | lss16.5 | 61 | ||||
-rw-r--r-- | lss16toppm.1 | 98 | ||||
-rw-r--r-- | lss16toppm.c | 9 | ||||
-rw-r--r-- | mk/dynamic.mk | 2 | ||||
-rw-r--r-- | mk/static.mk | 2 | ||||
-rw-r--r-- | ppmtolss16.1 | 93 |
26 files changed, 1112 insertions, 47 deletions
@@ -13,3 +13,4 @@ *.gcno *.gcda /lss16toppm +/ppmtolss16 @@ -37,19 +37,26 @@ HDR =\ LOBJ = $(OBJ_LIB:.o=.lo) +MAN1 = $(BIN:=.1) +MAN3 = $(OBJ_LIB:.o=.3) +MAN5 = lss16.5 +MAN7 = liblss16.7 + all: liblss16.a liblss16.$(LIBEXT) $(BIN) $(OBJ): $(HDR) $(LOBJ): $(HDR) +include mk/$(LINKING).mk + .c.o: $(CC) -c -o $@ $< $(CFLAGS) $(CPPFLAGS) .c.lo: $(CC) -fPIC -c -o $@ $< $(CFLAGS) $(CPPFLAGS) -lss16toppm: lss16toppm.o liblss16.a - $(CC) -o $@ lss16toppm.o liblss16.a $(LDFLAGS) +lss16toppm: lss16toppm.o $(BIN_DEP) + $(CC) -o $@ $@.o $(LDFLAGS) $(BIN_LDFLAGS) liblss16.a: $(OBJ_LIB) @rm -f -- $@ @@ -70,6 +77,14 @@ install: liblss16.a liblss16.$(LIBEXT) ln -sf -- liblss16.$(LIBMINOREXT) "$(DESTDIR)$(PREFIX)/lib/liblss16.$(LIBMAJOREXT)" ln -sf -- liblss16.$(LIBMAJOREXT) "$(DESTDIR)$(PREFIX)/lib/liblss16.$(LIBEXT)" cp -- liblss16.h "$(DESTDIR)$(PREFIX)/include/" + mkdir -p -- "$(DESTDIR)$(MANPREFIX)/man1" + mkdir -p -- "$(DESTDIR)$(MANPREFIX)/man3" + mkdir -p -- "$(DESTDIR)$(MANPREFIX)/man5" + mkdir -p -- "$(DESTDIR)$(MANPREFIX)/man7" + cp -- $(MAN1) "$(DESTDIR)$(MANPREFIX)/man1/" + cp -- $(MAN3) "$(DESTDIR)$(MANPREFIX)/man3/" + cp -- $(MAN5) "$(DESTDIR)$(MANPREFIX)/man5/" + cp -- $(MAN7) "$(DESTDIR)$(MANPREFIX)/man7/" uninstall: -cd -- "$(DESTDIR)$(PREFIX)/bin/" && rm -f -- $(BIN) @@ -78,6 +93,10 @@ uninstall: -rm -f -- "$(DESTDIR)$(PREFIX)/lib/liblss16.$(LIBMINOREXT)" -rm -f -- "$(DESTDIR)$(PREFIX)/lib/liblss16.$(LIBEXT)" -rm -f -- "$(DESTDIR)$(PREFIX)/include/liblss16.h" + -cd -- "$(DESTDIR)$(MANPREFIX)/man1/" && rm -f -- $(MAN1) + -cd -- "$(DESTDIR)$(MANPREFIX)/man3/" && rm -f -- $(MAN3) + -cd -- "$(DESTDIR)$(MANPREFIX)/man5/" && rm -f -- $(MAN5) + -cd -- "$(DESTDIR)$(MANPREFIX)/man7/" && rm -f -- $(MAN7) clean: -rm -f -- *.o *.a *.lo *.su *.so *.so.* *.dll *.dylib @@ -0,0 +1,50 @@ +NAME + liblss16 - Library for the SYSLINUX "ad hoc" LSS16 image format + +DESCRIPTION + liblss16 is a C library for encoding and decode the LSS16 image file + format, which is a SYSLINUX "ad hoc" lossless, compressed, low-fidelity + image file format optimised bootloaders in low-end graphics + environments. + + liblss16 provides the following functions for decoding LSS16 images: + + liblss16_decoder_init(3) + Prepare state for liblss16_decode_to_colour_index(3). + + liblss16_decode_to_colour_index(3) + Decode an file. The colour of each pixel is output with + the index of the colour in the colour palette. + + liblss16_decode_strerror(3) + Get error description for error code returned by + liblss16_decode_to_colour_index(3). + + liblss16 provides the following functions for encoding LSS16 images: + + liblss16_optimise(3) + Optimise an image for optimal compression with LSS16. + + liblss16_encoder_init(3) + Prepare state for liblss16_encode_from_colour_index(3). + + liblss16_encode_from_colour_index(3) + Encode an file. The colour of each pixle is input as the + index of the colour in the colour palette. + + liblss16_encode_strerror(3) + Get error description for error code returned by + liblss16_encoder_init(3) or + liblss16_encode_from_colour_index(3). + +EXTENDED DESCRIPTION + The liblss16 project also implements the following utilities: + + lss16toppm(1) + Convert an LSS16 file to a Portable Pixmap (PPM) file. + + ppmtolss16(1) + Convert a Portable Anymap (PNM) file to an LSS16 file. + +SEE ALSO + lss16(5), syslinux(1) @@ -1,3 +0,0 @@ -Write ppmtolss16 -Write man pages -Write README @@ -3,6 +3,10 @@ MANPREFIX = $(PREFIX)/share/man CC = c99 -CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_GNU_SOURCE +CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_GNU_SOURCE -DHARDEN CFLAGS = LDFLAGS = + +LINKING = dynamic +# dynamic: dynamically link included utilities +# static: statically link included utilities diff --git a/liblss16.7 b/liblss16.7 new file mode 100644 index 0000000..10c063c --- /dev/null +++ b/liblss16.7 @@ -0,0 +1,62 @@ +.TH LIBLSS16 7 LIBLSS16 +.SH NAME +liblss16 \- Library for the SYSLINUX \(dqad hoc\(dq LSS16 image format + +.SH DESCRIPTION +.B liblss16 +is a C library for encoding and decode the LSS16 image file +format, which is a SYSLINUX \(dqad hoc\(dq lossless, compressed, +low-fidelity image file format optimised bootloaders in low-end +graphics environments. +.PP +.B liblss16 +provides the following functions for decoding LSS16 images: +.RS +.TP +.BR liblss16_decoder_init (3) +Prepare state for +.BR liblss16_decode_to_colour_index (3). +.TP +.BR liblss16_decode_to_colour_index (3) +Decode an file. The colour of each pixel is output with +the index of the colour in the colour palette. +.TP +.BR liblss16_decode_strerror (3) +Get error description for error code returned by +.BR liblss16_decode_to_colour_index (3). +.RE +.PP +.B liblss16 +provides the following functions for encoding LSS16 images: +.RS +.TP +.BR liblss16_optimise (3) +Optimise an image for optimal compression with LSS16. +.TP +.BR liblss16_encoder_init (3) +Prepare state for +.BR liblss16_encode_from_colour_index (3). +.TP +.BR liblss16_encode_from_colour_index (3) +Encode an file. The colour of each pixle is input as +the index of the colour in the colour palette. +.TP +.BR liblss16_encode_strerror (3) +Get error description for error code returned by +.BR liblss16_encoder_init (3). +.RE + +.SH EXTENDED DESCRIPTION +The +.B liblss16 +project also implements the following utilities: +.TP +.BR lss16toppm (1) +Convert an LSS16 file to a Portable Pixmap (PPM) file. +.TP +.BR ppmtolss16 (1) +Convert a Portable Pixmap (PPM) file to an LSS16 file. + +.SH SEE ALSO +.BR lss16 (5), +.BR syslinux (1) @@ -6,6 +6,12 @@ #include <stdint.h> +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wpadded" +#endif + + /** * Image decoding state */ @@ -115,12 +121,7 @@ enum liblss16_encode_state { /** * Encodig done */ - LIBLSS16_ENCODE_DONE, - - /** - * Error occured while encoding - */ - LIBLSS16_ENCODE_ERROR + LIBLSS16_ENCODE_DONE }; @@ -139,12 +140,7 @@ enum liblss16_encode_error { * 6 bits, however at least one colour value * had at least one of it it high bits set */ - LIBLSS16_ENCODE_BAD_COLOUR, - - /** - * Colour index above 15 specified for a pixel - */ - LIBLSS16_ENCODE_BAD_COLOUR_INDEX + LIBLSS16_ENCODE_BAD_COLOUR }; @@ -270,10 +266,9 @@ void liblss16_decoder_init(struct liblss16_decoder *decoder); * is set to `LIBLSS16_DECODE_BAD_HEADER` */ enum liblss16_decode_state liblss16_decode_to_colour_index( - struct liblss16_decoder *decoder, - const void *data, size_t length, size_t *consumed_out, - uint8_t *pixels, size_t pixels_size, size_t *npixels_out, - enum liblss16_decode_error *error_out); + struct liblss16_decoder *decoder, const void *data, size_t length, + size_t *consumed_out, uint8_t *pixels, size_t pixels_size, + size_t *npixels_out, enum liblss16_decode_error *error_out); /** @@ -319,16 +314,13 @@ int liblss16_encoder_init(struct liblss16_encoder *encoder, const struct liblss1 * @param npixels The number of provided pixels * @param nconsumed_out Output parameter for the number of pixels consumed into * to state of the encoder - * @param error_out Output parameter for the error; only set if - * `LIBLSS16_ENCODE_ERROR` is returned; may be `NULL` * @return The processing state: normally `LIBLSS16_ENCODE_RUNNING`, - * but `LIBLSS16_ENCODE_DONE` when the image has been - * fully encoded, and `LIBLSS16_ENCODE_ERROR` on error + * but `LIBLSS16_ENCODE_DONE` when the image has been fully + * encoded */ enum liblss16_encode_state liblss16_encode_from_colour_index( - struct liblss16_encoder *encoder, void *buffer, size_t size, - size_t *written_out, const uint8_t *pixels, size_t npixels, - size_t *nconsumed_out, enum liblss16_encode_error *error_out); + struct liblss16_encoder *encoder, void *buffer, size_t size, size_t *written_out, + const uint8_t *pixels, size_t npixels, size_t *nconsumed_out); /** @@ -347,7 +339,7 @@ const char *liblss16_encode_strerror(enum liblss16_encode_error error); * Optimise and image * * @param header The image metadata - * @param pixel Buffer with pixels; the pixels are to encoded with the + * @param pixels Buffer with pixels; the pixels are to encoded with the * colour index of each pixel. Pixels are encoded primarily * from to the top down and secondarily from left to right. * @@ -357,4 +349,8 @@ const char *liblss16_encode_strerror(enum liblss16_encode_error error); void liblss16_optimise(struct liblss16_header *header, uint8_t *pixels); +#if defined(__clang__) +# pragma clang diagnostic pop +#endif + #endif diff --git a/liblss16_decode_strerror.3 b/liblss16_decode_strerror.3 new file mode 100644 index 0000000..ee011ed --- /dev/null +++ b/liblss16_decode_strerror.3 @@ -0,0 +1,43 @@ +.TH LIBLSS16_DECODE_STRERROR 3 LIBLSS16 +.SH NAME +liblss16_decode_strerror \- Get error description for an LSS16 decoding error + +.SH SYNOPSIS +.nf +#include <liblss16.h> + +enum liblss16_decode_error { /* values omitted */ }; + +const char *liblss16_decode_strerror(enum liblss16_decode_error \fIerror\fP); +.fi +.PP +Link with +.IR -llss16 . + +.SH DESCRIPTION +The +.BR liblss16_decode_strerror () +function returns a stirng the describes +.IR error . +.PP +The function is used for decoding errors, which may be +received from the +.BR liblss16_decode_to_colour_index (3) +function. + +.SH RETURN VALUE +The +.BR liblss16_decode_strerror () +function returns a statically allocated single-line +of text (not LF-terminated) describing the error, in +sentence case, single-sentence (not period-terminated). +If the error code is not recognised, a generic text +is returned. + +.SH ERRORS +The +.BR liblss16_decode_strerror () +function cannot fail. + +.SH SEE ALSO +.BR liblss16 (7) diff --git a/liblss16_decode_strerror.c b/liblss16_decode_strerror.c index 3bd3c5a..cf2d8aa 100644 --- a/liblss16_decode_strerror.c +++ b/liblss16_decode_strerror.c @@ -5,7 +5,7 @@ const char * liblss16_decode_strerror(enum liblss16_decode_error error) { - switch (error) { + switch ((int)error) { case LIBLSS16_DECODE_TRUNCATED_MAGIC: return "Short file: magic number truncated"; diff --git a/liblss16_decode_to_colour_index.3 b/liblss16_decode_to_colour_index.3 new file mode 100644 index 0000000..797c4f5 --- /dev/null +++ b/liblss16_decode_to_colour_index.3 @@ -0,0 +1,221 @@ +.TH LIBLSS16_DECODE_TO_COLOUR_INDEX 3 LIBLSS16 +.SH NAME +liblss16_decode_to_colour_index \- Decode an LSS16 image file + +.SH SYNOPSIS +.nf +#include <liblss16.h> + +enum liblss16_decode_state { + LIBLSS16_DECODE_RUNNING, + LIBLSS16_DECODE_END_OF_IMAGE, + LIBLSS16_DECODE_ERROR +}; + +enum liblss16_decode_error { + LIBLSS16_DECODE_TRUNCATED_MAGIC, + LIBLSS16_DECODE_BAD_MAGIC, + LIBLSS16_DECODE_TRUNCATED_HEADER, + LIBLSS16_DECODE_BAD_IMAGE_SIZE, + LIBLSS16_DECODE_BAD_COLOUR, + LIBLSS16_DECODE_BAD_ROW_PADDING, + LIBLSS16_DECODE_EXCESSIVE_RUN_LENGTH, + LIBLSS16_DECODE_TRUNCATED_IMAGE +}; + +struct liblss16_colour { + uint8_t \fIr\fP; + uint8_t \fIg\fP; + uint8_t \fIb\fP; +}; + +struct liblss16_header { + uint16_t \fIwidth\fP; + uint16_t \fIheight\fP; + struct liblss16_colour \fIcolour_map\fP[16]; +}; + +struct liblss16_decoder { + struct liblss16_header \fIimage\fP; + /* internal fields omitted */ +}; + +enum liblss16_decode_state liblss16_decode_to_colour_index( + struct liblss16_decoder *\fIdecoder\fP, + const void *\fIdata\fP, size_t \fIlength\fP, size_t *\fIconsumed_out\fP, + uint8_t *\fIpixels\fP, size_t \fIpixels_size\fP, size_t *\fInpixels_out\fP, + enum liblss16_decode_error *\fIerror_out\fP); +.fi +.PP +Link with +.IR -llss16 . + +.SH DESCRIPTION +The +.BR liblss16_decode_to_colour_index () +function decodes an image encoded in the LSS16 file format. +Before the decoding of a file is started +.I decoder +must be initialised with the +.BR liblss16_decoder_init (3) +function. The function is then repeatedly while it returns +.IR LIBLSS16_DECODE_RUNNING . +.PP +For each call, currently available file content is input in the +.I data +parameter, and the number of available bytes is input in the +.I length +parameter. After each call, the application shall discard the +.I *consumed_out +first bytes of +.I data +and decrease +.I length +by the same amount, but it may also append newly available +data, and increase +.I length +correspondingly. +.PP +The call shall provide a buffer for at least one pixel in the +.I pixels +parameter, and specify the number of pixels the buffer can +store in the +.I pixels_size +parameter. The function will set +.I *npixels_out +to the number of pixels output to the beginning of +.IR pixels . +Each pixel is encoded with a colour index, which is a non-negative +integer 15 or less. The function will set +.I decoder->image +the first time it sets +.I *npixels_out +to a non-zero value, or earlier. At this time, the width or height +of the image, in number of pixels, can be looked up in +.I decoder->image.width +and +.I decoder->image.height +respectively. Additionally the colour palette is also set, so the +colours of the returned pixels can be looked up. If the value +.I P +is returned for a pixel, +.I decoder->image.colour_map[P] +is a +.B struct liblss16_colour +that describes the pixel's colour; +.I .r +is an unsigned 8-bit integer value for the red component +of the pixel's sRGB colour, likewise +.I .g +is the green value and +.I .b +is the blue value. +.PP +.I decoder +must not be +.IR NULL . +.PP +.I data +may only be +.I NULL +if +.I length +is 0, which is used while still decoding +after then end of the file has been reached. +.PP +.I consumed_out +must not be +.IR NULL . +.PP +.I pixels +must not be null +.IR NULL , +and +.I pixels_size +must not be 0. +.PP +.I npixels_out +must not be +.IR NULL . +.PP +.I error_out +shall either be +.I NULL +or a pointer to where the error code shall be +stored should the function fail. + +.SH RETURN VALUE +The +.BR liblss16_decode_to_colour_index () +function will returns the following values: +.TP +.B LIBLSS16_DECODE_RUNNING +The end of the image has not yet been reached. +The file if truncated if the end of the file is reached. +.TP +.B LIBLSS16_DECODE_END_OF_IMAGE +The end of the image is reched. +If the end of the file has not yet been reached, it +contains extraneous data. +.TP +.B LIBLSS16_DECODE_ERROR +A decoding error has occured, and processing most be +aborted. This always indicate that the file is corrupted +or not an LSS16 file. +.I *error_out +will be se to indicate the error unless +.I error_out +is +.IR NULL . +.PP +Note that +.I *npixels_out +and +.I *consumed_out +are always set. + +.SH ERRORS +The +.BR liblss16_decode_to_colour_index () +function fails for the following reasons: +.TP +.B LIBLSS16_DECODE_TRUNCATED_MAGIC +The file contains up to the first three bytes of the +LSS16 magic number, but is truncated and does not +contain the fourth byte. +.TP +.B LIBLSS16_DECODE_BAD_MAGIC +The file does not begin with the LSS16 magic number. +.TP +.B LIBLSS16_DECODE_TRUNCATED_HEADER +The file is too short to contain the full header. +.TP +.B LIBLSS16_DECODE_BAD_IMAGE_SIZE +The image width is 0, the image height is 0, or +the image height exceeds 32767. + +.I decoder->image.width +and +.I decoder->image.height +will be set so each of the reasons apply can be +determined. +.TP +.B LIBLSS16_DECODE_BAD_COLOUR +The file is corrupt and the colour palette contains +a value greater than 63. +.TP +.B LIBLSS16_DECODE_BAD_ROW_PADDING +The file is corrupt and contains non-zero row padding. +.TP +.B LIBLSS16_DECODE_EXCESSIVE_RUN_LENGTH +The file is corrupt and contains a run length +crossing two or more rows of pixels. +.TP +.B LIBLSS16_DECODE_TRUNCATED_IMAGE +The file contains the full header, but is truncated +and does not contain the full image data. + +.SH SEE ALSO +.BR liblss16_decode_strerror (3), +.BR liblss16_encode_from_colour_index (3), +.BR liblss16 (7) diff --git a/liblss16_decode_to_colour_index.c b/liblss16_decode_to_colour_index.c index a552289..e1845e9 100644 --- a/liblss16_decode_to_colour_index.c +++ b/liblss16_decode_to_colour_index.c @@ -2,6 +2,11 @@ #include "liblss16.h" #include <string.h> +#if defined(__clang__) +# pragma clang diagnostic ignored "-Wimplicit-fallthrough" +# pragma clang diagnostic ignored "-Wunsafe-buffer-usage" +#endif + enum liblss16_decode_state liblss16_decode_to_colour_index(struct liblss16_decoder *decoder, @@ -210,11 +215,10 @@ liblss16_decode_to_colour_index(struct liblss16_decoder *decoder, } else if (decoder->internal.state == 2U) { decoder->internal.state = (uint8_t)(n | 128U); } else { - m = (uint16_t)((n << 4) + (decoder->internal.state & 15U) + 16U); + m = (uint16_t)((unsigned)(n << 4) + (decoder->internal.state & 15U) + 16U); goto put_m_pixels; } } - break; } return LIBLSS16_DECODE_RUNNING; diff --git a/liblss16_decoder_init.3 b/liblss16_decoder_init.3 new file mode 100644 index 0000000..262fc07 --- /dev/null +++ b/liblss16_decoder_init.3 @@ -0,0 +1,41 @@ +.TH LIBLSS16_DECODER_INIT 3 LIBLSS16 +.SH NAME +liblss16_decoder_init \- Prepare state for decoding LSS16 image file + +.SH SYNOPSIS +.nf +#include <liblss16.h> + +struct liblss16_decoder { /* fields omitted */ }; + +void liblss16_decoder_init(struct liblss16_decoder *\fIdecoder\fP); +.fi +.PP +Link with +.IR -llss16 . + +.SH DESCRIPTION +The +.BR liblss16_decoder_init () +function initialises +.I *decoder +for the first call to the +.BR liblss16_decode_to_colour_index (3) +function. +.PP +.I decoder +must not be +.IR NULL . +.PP +There is no corresponding deallocator as no dynamic resources are allocated. + +.SH RETURN VALUE +None. + +.SH ERRORS +The +.BR liblss16_decoder_init () +function cannot fail. + +.SH SEE ALSO +.BR liblss16 (7) diff --git a/liblss16_encode_from_colour_index.3 b/liblss16_encode_from_colour_index.3 new file mode 100644 index 0000000..9a55c09 --- /dev/null +++ b/liblss16_encode_from_colour_index.3 @@ -0,0 +1,108 @@ +.TH LIBLSS16_ENCODE_FROM_COLOUR_INDEX 3 LIBLSS16 +.SH NAME +liblss16_encode_from_colour_index \- Encode an LSS16 image file + +.SH SYNOPSIS +.nf +#include <liblss16.h> + +enum liblss16_encode_state { + LIBLSS16_ENCODE_RUNNING, + LIBLSS16_ENCODE_DONE +}; + +struct liblss16_encoder { /* fields omitted */ }; + +enum liblss16_encode_state liblss16_encode_from_colour_index( + struct liblss16_encoder *\fIencoder\fP, void *\fIbuffer\fP, size_t \fIsize\fP, + size_t *\fIwritten_out\fP, const uint8_t *\fIpixels\fP, size_t \fInpixels\fP, + size_t *\fInconsumed_out\fP); +.fi +.PP +Link with +.IR -llss16 . + +.SH DESCRIPTION +The +.BR liblss16_encode_from_colour_index () +function encodes an image as in LSS16 file. +Before beginning the encoding, the application +must first initalise +.I encoder +with its initial state and image meta data +using the +.BR liblss16_encoder_init (3) +function. After than, the +.BR liblss16_encode_from_colour_index () +function is called repeatedly until it returns +.BR LIBLSS16_ENCODE_DONE . +.PP +The application shall provide an array of pixels +in the +.I pixels +parameter, with the number of provided pixels +specified in the +.I npixels +parameter. After each call, the application shall +discard the first +.I *nconsumed_out +pixels but may append additional pixels. +.I npixels +shall be decreased by +.I *nconsumed_out +and increased by the number of new pixels. +The application shall also provide a file content +output buffer in the +.I buffer +parameter and the size, in bytes, of the buffer +in the +.I size +parameter. After each call, the application shall +shall write the first +.I *written_out +bytes from +.I buffer +to the output file. +.PP +.IR encoder , +.IR buffer , +.IR written_out , +and +.IR nconsumed_out +must not be +.IR NULL , +and +.I size +must be at least 1. +.PP +.I pixels +may only be +.I NULL +if +.I npixels +is 0. + +.SH RETURN VALUE +The +.BR liblss16_encode_from_colour_index () +function returns +.B LIBLSS16_ENCODE_RUNNING +until the last byte for the LSS16 file +hsa been written. Once the last byte +has been written, it returns +.BR LIBLSS16_ENCODE_DONE . +Note that +.I *written_out +and +.I *nconsumed_out +are always set. + +.SH ERRORS +The +.BR liblss16_encode_from_colour_index () +function cannot fail. + +.SH SEE ALSO +.BR liblss16_encode_strerror (3), +.BR liblss16_decode_to_colour_index (3), +.BR liblss16 (7) diff --git a/liblss16_encode_from_colour_index.c b/liblss16_encode_from_colour_index.c index 1efff36..95b600b 100644 --- a/liblss16_encode_from_colour_index.c +++ b/liblss16_encode_from_colour_index.c @@ -1,7 +1,12 @@ /* See LICENSE file for copyright and license details. */ #include "liblss16.h" -#include <string.h> #include <stdlib.h> +#include <string.h> + +#if defined(__clang__) +# pragma clang diagnostic ignored "-Wimplicit-fallthrough" +# pragma clang diagnostic ignored "-Wunsafe-buffer-usage" +#endif static size_t @@ -16,9 +21,8 @@ flush_buffer(struct liblss16_encoder *encoder, uint8_t *buffer, size_t size) enum liblss16_encode_state -liblss16_encode_from_colour_index(struct liblss16_encoder *encoder, void *buffer_, size_t size, - size_t *written_out, const uint8_t *pixels, size_t npixels, - size_t *nconsumed_out, enum liblss16_encode_error *error_out) +liblss16_encode_from_colour_index(struct liblss16_encoder *encoder, void *buffer_, size_t size, size_t *written_out, + const uint8_t *pixels, size_t npixels, size_t *nconsumed_out) { uint8_t *buffer = buffer_; size_t n; @@ -120,10 +124,6 @@ liblss16_encode_from_colour_index(struct liblss16_encoder *encoder, void *buffer while (npixels--) { if (*pixels == encoder->previous) { encoder->repetition++; - } else if (*pixels > 15U) { - if (error_out) - *error_out = LIBLSS16_ENCODE_BAD_COLOUR_INDEX; - return LIBLSS16_ENCODE_ERROR; } else { if (!encoder->repetition) { /* do nothing */ diff --git a/liblss16_encode_strerror.3 b/liblss16_encode_strerror.3 new file mode 100644 index 0000000..758c887 --- /dev/null +++ b/liblss16_encode_strerror.3 @@ -0,0 +1,43 @@ +.TH LIBLSS16_ENCODE_STRERROR 3 LIBLSS16 +.SH NAME +liblss16_encode_strerror \- Get error description for an LSS16 encoding error + +.SH SYNOPSIS +.nf +#include <liblss16.h> + +enum liblss16_encode_error { /* values omitted */ }; + +const char *liblss16_encode_strerror(enum liblss16_encode_error \fIerror\fP); +.fi +.PP +Link with +.IR -llss16 . + +.SH DESCRIPTION +The +.BR liblss16_encode_strerror () +function returns a stirng the describes +.IR error . +.PP +The function is used for encoding errors, which may be +received from the +.BR liblss16_encoder_init (3) +function. + +.SH RETURN VALUE +The +.BR liblss16_encode_strerror () +function returns a statically allocated single-line +of text (not LF-terminated) describing the error, in +sentence case, single-sentence (not period-terminated). +If the error code is not recognised, a generic text +is returned. + +.SH ERRORS +The +.BR liblss16_encode_strerror () +function cannot fail. + +.SH SEE ALSO +.BR liblss16 (7) diff --git a/liblss16_encode_strerror.c b/liblss16_encode_strerror.c index a5fcd49..e4d1ab9 100644 --- a/liblss16_encode_strerror.c +++ b/liblss16_encode_strerror.c @@ -5,16 +5,13 @@ const char * liblss16_encode_strerror(enum liblss16_encode_error error) { - switch (error) { + switch ((int)error) { case LIBLSS16_ENCODE_BAD_IMAGE_SIZE: return "Unencodable image: unsupported image size"; case LIBLSS16_ENCODE_BAD_COLOUR: return "Invalid colour map: 6-bit colours encoded with additional bits"; - case LIBLSS16_ENCODE_BAD_COLOUR_INDEX: - return "Invalid image: colour index out of range"; - default: return "Unrecognised error"; } diff --git a/liblss16_encoder_init.3 b/liblss16_encoder_init.3 new file mode 100644 index 0000000..b5f37f9 --- /dev/null +++ b/liblss16_encoder_init.3 @@ -0,0 +1,125 @@ +.TH LIBLSS16_ENCODER_INIT 3 LIBLSS16 +.SH NAME +liblss16_encoder_init \- Prepare state for encoding LSS16 image file + +.SH SYNOPSIS +.nf +#include <liblss16.h> + +enum liblss16_encode_error { + LIBLSS16_ENCODE_BAD_IMAGE_SIZE, + LIBLSS16_ENCODE_BAD_COLOUR +}; + +struct liblss16_colour { + uint8_t \fIr\fP; + uint8_t \fIg\fP; + uint8_t \fIb\fP; +}; + +struct liblss16_header { + uint16_t \fIwidth\fP; + uint16_t \fIheight\fP; + struct liblss16_colour \fIcolour_map\fP[16]; +}; + +struct liblss16_encoder { /* fields omitted */ }; + +int liblss16_encoder_init(struct liblss16_encoder *\fIencoder\fP, + const struct liblss16_header *\fIheader\fP, int \fIrgb6\fP, + enum liblss16_encode_error *\fIerror_out\fP); +.fi +.PP +Link with +.IR -llss16 . + +.SH DESCRIPTION +The +.BR liblss16_encoder_init () +function initialises +.I *encoder +for the first call to the +.BR liblss16_encode_from_colour_index (3) +function. +.PP +.I header->width +shall be the width, in pixels, of the image. +.PP +.I header->height +shall be the height, in pixels, of the image. +.PP +.I header->colour_map +shall be the image's colour palette. Each +.B struct liblss16_colour +is encoded in sRGB with either 6 bits per channel +or 8 bits per channel +.RI ( .r +for the red channel, +.I .g +for the green channel, and +.I .b +for the blue channel). +.PP +If +.I rgb6 +is zero, each +.B struct liblss16_colour is encoded with 8 bits +per channel, and scaled down to 6 bits by the +function (the scaled down value will be stored in +.I *header +and output when ending the file). +.PP +If +.I rgb6 +is non-zero, each +.B struct liblss16_colour is encoded with 6 bits +per channel, and the function will validate that +the 2 highest bits in each value is cleared. +.PP +.I error_out +shall either be +.I NULL +or a pointer to where the error code shall be +stored should the function fail. +.PP +Before calling the +.BR liblss16_encoder_init () +function, the application may choose to call the +.BR liblss16_optimise (3) +function. + +.SH RETURN VALUE +The +.BR liblss16_encoder_init () +function returns 0 upon successful +completion. On failure, returns -1 +and sets +.I *error_out +(unless +.I error_out +is +.IR NULL ) +to indicate the error. + +.SH ERRORS +The +.BR liblss16_encoder_init () +function will fail for the following reasons: +.TP +.B LIBLSS16_ENCODE_BAD_IMAGE_SIZE +The image width was 0. +.TP +.B LIBLSS16_ENCODE_BAD_IMAGE_SIZE +The image height was 0. +.TP +.B LIBLSS16_ENCODE_BAD_IMAGE_SIZE +The image height was greater than 32767. +.TP +.B LIBLSS16_ENCODE_BAD_COLOUR +.I rgb6 +was non-zero, and one of the colour values +was create than 63. + +.SH SEE ALSO +.BR liblss16_encode_strerror (3), +.BR liblss16 (7) diff --git a/liblss16_encoder_init.c b/liblss16_encoder_init.c index 037cd8e..d94d4fa 100644 --- a/liblss16_encoder_init.c +++ b/liblss16_encoder_init.c @@ -2,6 +2,10 @@ #include "liblss16.h" #include <string.h> +#if defined(__clang__) +# pragma clang diagnostic ignored "-Wunsafe-buffer-usage" +#endif + int liblss16_encoder_init(struct liblss16_encoder *encoder, const struct liblss16_header *header, diff --git a/liblss16_optimise.3 b/liblss16_optimise.3 new file mode 100644 index 0000000..0a9d6e5 --- /dev/null +++ b/liblss16_optimise.3 @@ -0,0 +1,81 @@ +.TH LIBLSS16_OPTIMISE 3 LIBLSS16 +.SH NAME +liblss16_optimise \- Optimise an image for best compression with LSS16 + +.SH SYNOPSIS +.nf +#include <liblss16.h> + +struct liblss16_colour { + uint8_t \fIr\fP; + uint8_t \fIg\fP; + uint8_t \fIb\fP; +}; + +struct liblss16_header { + uint16_t \fIwidth\fP; + uint16_t \fIheight\fP; + struct liblss16_colour \fIcolour_map\fP[16]; +}; + +void liblss16_optimise(struct liblss16_header *\fIheader\fP, uint8_t *\fIpixels\fP); +.fi +.PP +Link with +.IR -llss16 . + +.SH DESCRIPTION +The +.BR liblss16_optimise () +function reorders and deduplicates the colour palette +for an image so that it will compress optimally with LSS16. +.PP +.I header->width +shall be the width, in pixels, of the image. +.PP +.I header->height +shall be the height, in pixels, of the image. +.PP +.I header->colour_map +shall be the image's colour palette. +.PP +.I pixels +shall be a buffer of the colour index for +.I header->width*header->height +pixels. Ordered primarily from the top down +and secondarily from left to right. The colour +of a pixel encoded with the value +.I P +is determined by +.IR header->colour_map[P] . +Each +.B struct liblss16_colour +is encoded in sRGB with either 6 bits per channel +or 8 bits per channel +.RI ( .r +for the red channel, +.I .g +for the green channel, and +.I .b +for the blue channel). +.PP +Values in +.I pixels +must be 15 or less. The function will not validate the input. + +.PP +The function will rewrite +.I header->colour_map +and +.IR pixels . + +.SH RETURN VALUE +None. + +.SH ERRORS +The +.BR liblss16_optimise () +function cannot fail. + +.SH SEE ALSO +.BR liblss16 (7) diff --git a/liblss16_optimise.c b/liblss16_optimise.c index 5e69d85..f532a94 100644 --- a/liblss16_optimise.c +++ b/liblss16_optimise.c @@ -2,6 +2,10 @@ #include "liblss16.h" #include <string.h> +#if defined(__clang__) +# pragma clang diagnostic ignored "-Wunsafe-buffer-usage" +#endif + void liblss16_optimise(struct liblss16_header *header, uint8_t *pixels) @@ -37,6 +41,10 @@ liblss16_optimise(struct liblss16_header *header, uint8_t *pixels) width = (unsigned)header->width; width = width < 17U ? width : 17U; for (y = 0, p = 0; y < (unsigned)header->height; y++) { +#ifdef HARDEN + for (x = 0; x < (unsigned)header->width; x++) + pixels[p + x] &= 15U; +#endif colour = remap[pixels[p]]; count = 1U; for (x = 1U; x < width; x++, p++) { @@ -0,0 +1,61 @@ +.TH LSS16 5 LIBLSS16 +.SH NAME +lss16 \- SYSLINUX \(dqad hoc\(dq 16-colour, 6-bit channel-depth image file format LSS16 + +.SH DESCRIPTION +LSS16 is run-length encoding compressed, lossless an image file format +using a 16-colour palette and sRGB 6-6-6. LSS16 is designed for bootloader splash +images which may be displayed on low-end legacy devices with limited image quality +capabilities. LSS16 does not support transparency. +.PP +LSS16 file consists how two parts: a 56 byte header followed by the pixel encoding. +.PP +Header format: +.RS +4-byte magic number: 3Dh, F3h, 13h, 14h. + +Image width (number of pixels horizontally): unsigned 16-bit integer, little endian. + +Image height (number of pixels horizontally): unsigned 16-bit integer, little endian, +however the most significant bit most be cleared. + +Colour palette: 16 RGB-tuples, each tuple is 3 bytes: red, green, blue. +The two most significant bits in each byte must be cleared. +.RE +.PP +Pixel encoding format: +.RS +The pixels are encoded, row by row, from the top down, in a sequence of nibble. Each +row is encoded from left to right, and odd-nibble rows are padded with a zero-nibble. +Each encoded byte, is split into two nibbles; the lower part of the byte makes up the +first nibble, and the higher part of the byte makes up the second nibble. + +At the beginning of each row, the previous pixel is assumed to use the 0-indexed colour. + +If a nibble as the value of the the previous pixel colour index, a run-length is encoded, +otherwise the next pixel has the colour with the index encoded in the nibble. + +If the nibble encodes a run-length, it can either be 0 or the number of times the +previous pixel is repeated (excluding the already existing pixels). If the nibble +is 0, the next two nibbles, encodes in little-endian, a value +.IR N , +and the previous pixel is repeated +.IR N +16 +times (excluding the already existing pixels). +.RE +.PP +A 6-bit colour-channel +value +.I N +is mapped to 8-bits with the function +.I (N*255+31)/63 +(linear scaling). +.PP +LSS16 image files usually have the filename suffix +.RB \(dq .lss \(dq +or +.RB \(dq .16 \(dq. + +.SH SEE ALSO +.BR liblss16 (7), +.BR syslinux (1) diff --git a/lss16toppm.1 b/lss16toppm.1 new file mode 100644 index 0000000..560a76b --- /dev/null +++ b/lss16toppm.1 @@ -0,0 +1,98 @@ +.TH LSS16TOPPM 1 LIBLSS16 +.SH NAME +lss16toppm \- Convert an LSS16 file to a Portable Pixmap (PPM) file + +.SH SYNPOSIS +.B lss16toppm +.RB [ -map ] +.RI "< " lss16-file +.RI "> " ppm-file + +.SH DESCRIPTION +The +.B lss16toppm +utility converts the LSS16 image file +.I lss16-file +to a Portable Pixmap (PPM) file, storing it to +.IR ppm-file . +.PP +The PPM file will be raw (P6) and use full 8-bit colours +per channel (0-255). This means that the colours are +scaled up from 6-bits to 8-bits, per channel, as LSS16 +only uses 6 bits per channel. + +.SH OPTIONS +The +.B lss16toppm +utility parses each argument as an option, including +.RB \(dq -- \(dq. +.PP +The following option is supported: +.TP +.B -map +Output the image's colour palette to the standard error. +The image has 16 mapped colours, will be printed in order, +from index 0 up, in the format + +.nf +\fB\(dq#%02x%02x%02x=%u\(dq, \fP<\fIred\fP>\fB, \fP<\fIgreen\fP>\fB, \fP<\fIblue\fP>\fB, \fP<\fIcolour index\fP>. +.fi + +Although LSS16 uses 6 bit per colour channel, the output +colours are scaled up to and output as 8 bit per colour +channel. + +.SH OPERANDS +None. + +.SH STDIN +The standard input shall be the LSS16 file to convert. + +.SH INPUT FILES +None. + +.SH STDOUT +The image will be printed as a 8-bit raw Portable Pixmap +(P6 PPM) to the standard output. + +.SH STDERR +The standard error is used for diagnostic purposes. If the +.B -map +option is used, the colour palette will also be printed to +the standard error, apart from this, nothing is output to +the standard error if the exist value of the process is +.BR 0 . + +.SH OUTPUT FILES +None. + +.SH EXIT STATUS +The following exit values are returned: +.TP +0 +Successful completion. +.TP +1 +The standard input is not an valid LSS16 file. +.TP +2 +An error occured. + +.SH NOTES +The SYSLINUX implementation of the +.BR lss16toppm +utility does used the exit value +.BR 2 , +but instead always returns 1 on failure. + +.SH RATIONALE +The invocation syntax is inherited from the SYSLINUX +implementation of +.BR lss16toppm . +As is the output as raw 8-bit PPM (P6). + +.SH SEE ALSO +.BR lss16 (5), +.BR ppmtolss16 (1), +.BR liblss16 (7), +.BR syslinux (1) diff --git a/lss16toppm.c b/lss16toppm.c index 6dcff62..48c9b93 100644 --- a/lss16toppm.c +++ b/lss16toppm.c @@ -6,6 +6,10 @@ #include <string.h> #include <unistd.h> +#if defined(__clang__) +# pragma clang diagnostic ignored "-Wunsafe-buffer-usage" +#endif + static const char *argv0 = "lss16toppm"; @@ -41,7 +45,7 @@ main(int argc, char *argv[]) enum liblss16_decode_error error; int head_printed = 0; int print_colour_map = 0; - int have_stdout, len; + int have_stdout = 0, len; size_t i; /* cmdline syntax is inherited from the SYSLINUX implementation, @@ -52,11 +56,12 @@ main(int argc, char *argv[]) argc--; } - for (; argc; argc--, argv++) { + for (; argc--; argv++) { if (!strcmp(*argv, "-map")) { print_colour_map = 1; } else { fprintf(stderr, "%s: Unknown option: %s\n", argv0, *argv); + return 2; } } diff --git a/mk/dynamic.mk b/mk/dynamic.mk new file mode 100644 index 0000000..3960a59 --- /dev/null +++ b/mk/dynamic.mk @@ -0,0 +1,2 @@ +BIN_DEP = liblss16.$(LIBEXT) +BIN_LDFLAGS = -L. -llss16 diff --git a/mk/static.mk b/mk/static.mk new file mode 100644 index 0000000..cf32c17 --- /dev/null +++ b/mk/static.mk @@ -0,0 +1,2 @@ +BIN_DEP = liblss16.a +BIN_LDFLAGS = liblss16.a diff --git a/ppmtolss16.1 b/ppmtolss16.1 new file mode 100644 index 0000000..7bb3516 --- /dev/null +++ b/ppmtolss16.1 @@ -0,0 +1,93 @@ +.TH PPMTOLSS16 1 LIBLSS16 +.SH NAME +ppmtolss16 \- Convert a Portable Anymap (PNM) file to an LSS16 file + +.SH SYNPOSIS +.B ppmtolss16 +.RI "< " pnm-file +.RI "> " lss16-file + +.SH DESCRIPTION +The +.B ppmtolss16 +utility converts the Portable Anymap (PNM) image file +.I pnm-file +to an LSS16 image file, and stores it as +.IR lss16-file. +.PP +Despite the name +.BR ppmtolss16 , +the +.N ppmtolss16 +utility supports Portable Bitmap (PBM) and Portable Greymap (PGM) +in addition to Portable Pixmaps (PPM). Both plain (P1, P2, P3) +and raw (P4, P5, P6) files are supported. + +.SH OPTIONS +None, not even +.RB \(dq -- \(dq. + +.SH OPERANDS +None. + +.SH STDIN +The standard input shall be the Portable Anymap file to convert. + +.SH INPUT FILES +None. + +.SH STDOUT +The image will be printed as an LSS16 file to the standard output. + +.SH STDERR +The standard error is used for diagnostic purposes. + +.SH OUTPUT FILES +None. + +.SH EXIT STATUS +The following exit values are returned: +.TP +0 +Successful completion. +.TP +1 +The standard input is not an valid P1-P6 Portable Anymap file. +.TP +2 +The image is too large to be encoded with LSS16. +.TP +3 +An error occured. + +.SH NOTES +The SYSLINUX implementation of the +.BR ppmtolss16 +utility does used the exit valuess +.B 2 +and +.BR 3 , +but instead always returns 1 on failure. + +.SH RATIONALE +The invocation syntax and the name of the utility is +inherited from the SYSLINUX implementation of +.BR ppmtolss16 . +.PP +SYSLINUX's implementation of +.BR ppmtolss16 +supports forcing the colour palette, however because this +feature was poorly documented, misleading, and not generally +useful, this implementation does not support this. + +.SH HISTORY +Early versions of SYSLINUX's implementation of +.BR ppmtolss16 +only supported raw Portable Pixmap (P6 PPM) files +without comments. + +.SH SEE ALSO +.BR lss16 (5), +.BR lss16toppm (1), +.BR liblss16 (7), +.BR syslinux (1) |