diff options
| author | Mattias Andrée <m@maandree.se> | 2026-03-01 03:56:16 +0100 |
|---|---|---|
| committer | Mattias Andrée <m@maandree.se> | 2026-03-01 03:56:16 +0100 |
| commit | 948b23ca1fabfe65ab36d866031422e92840282f (patch) | |
| tree | 07ff00b4959f734f65761896d39920e27396feb7 | |
| parent | fix typos (diff) | |
| download | liblss16-948b23ca1fabfe65ab36d866031422e92840282f.tar.gz liblss16-948b23ca1fabfe65ab36d866031422e92840282f.tar.bz2 liblss16-948b23ca1fabfe65ab36d866031422e92840282f.tar.xz | |
Fix mistakes, and finish ppmtolss16
Signed-off-by: Mattias Andrée <m@maandree.se>
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | config.mk | 2 | ||||
| -rw-r--r-- | liblss16.h | 6 | ||||
| -rw-r--r-- | liblss16_encode_from_colour_index.c | 70 | ||||
| -rw-r--r-- | liblss16_encoder_init.c | 2 | ||||
| -rw-r--r-- | lss16.5 | 4 | ||||
| -rw-r--r-- | lss16toppm.c | 4 | ||||
| -rw-r--r-- | ppmtolss16.1 | 4 | ||||
| -rw-r--r-- | ppmtolss16.c | 65 |
9 files changed, 126 insertions, 33 deletions
@@ -60,7 +60,7 @@ lss16toppm: lss16toppm.o $(BIN_DEP) $(CC) -o $@ $@.o $(LDFLAGS) $(BIN_LDFLAGS) ppmtolss16: ppmtolss16.o $(BIN_DEP) - $(CC) -o $@ $@.o $(LDFLAGS) $(BIN_LDFLAGS) + $(CC) -o $@ $@.o $(LDFLAGS) $(BIN_LDFLAGS) $(LDFLAGS_LIBQUANTA) liblss16.a: $(OBJ_LIB) @rm -f -- $@ @@ -7,6 +7,8 @@ CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_GNU_SOURCE -DH CFLAGS = LDFLAGS = +LDFLAGS_LIBQUANTA = -lquanta -lj2 -lm + LINKING = dynamic # dynamic: dynamically link included utilities # static: statically link included utilities @@ -224,7 +224,7 @@ struct liblss16_encoder { uint8_t header_position; uint8_t previous; uint8_t nbuffered; - uint8_t buffered[6]; + uint8_t buffered[7]; }; @@ -305,8 +305,8 @@ int liblss16_encoder_init(struct liblss16_encoder *encoder, const struct liblss1 * @param encoder Encoder state, must have been initialised with * `liblss16_encoder_init` before the first call * @param buffer Output buffer for the image data - * @param size Size of `buffer` - * @param written_out The number of bytes written to `size`, must be at least 1 + * @param size Size of `buffer`, must be at least 1 + * @param written_out The number of bytes written to `size` * @param pixels Buffer with pixels to encode; the pixels are to preencoded * (before the function is called) with the colour index of * each pixel. Pixels are input primarily from to the top diff --git a/liblss16_encode_from_colour_index.c b/liblss16_encode_from_colour_index.c index 95b600b..ae3948e 100644 --- a/liblss16_encode_from_colour_index.c +++ b/liblss16_encode_from_colour_index.c @@ -12,11 +12,11 @@ static size_t flush_buffer(struct liblss16_encoder *encoder, uint8_t *buffer, size_t size) { - size_t i; - for (i = 0; size && encoder->nbuffered - i > 1U; i += 2U, size--) - buffer[i] = (uint8_t)(encoder->buffered[i + 0] | (encoder->buffered[i + 1] << 4)); - memmove(&encoder->buffered[0], &encoder->buffered[i], encoder->nbuffered - i); - return i; + size_t i = 0, j = 0; + for (; size && encoder->nbuffered - i > 1U; i += 2U, size--) + buffer[j++] = (uint8_t)(encoder->buffered[i + 0] | (encoder->buffered[i + 1] << 4)); + memmove(&encoder->buffered[0], &encoder->buffered[i], encoder->nbuffered -= (uint8_t)i); + return j; } @@ -26,6 +26,7 @@ liblss16_encode_from_colour_index(struct liblss16_encoder *encoder, void *buffer { uint8_t *buffer = buffer_; size_t n; + unsigned value; *written_out = 0; *nconsumed_out = 0; @@ -35,7 +36,7 @@ liblss16_encode_from_colour_index(struct liblss16_encoder *encoder, void *buffer if (!size--) return LIBLSS16_ENCODE_RUNNING; *buffer++ = (uint8_t)0x3DU; - ++*nconsumed_out; + ++*written_out; encoder->header_position++; /* fall through */ @@ -43,7 +44,7 @@ liblss16_encode_from_colour_index(struct liblss16_encoder *encoder, void *buffer if (!size--) return LIBLSS16_ENCODE_RUNNING; *buffer++ = (uint8_t)0xF3U; - ++*nconsumed_out; + ++*written_out; encoder->header_position++; /* fall through */ @@ -51,7 +52,7 @@ liblss16_encode_from_colour_index(struct liblss16_encoder *encoder, void *buffer if (!size--) return LIBLSS16_ENCODE_RUNNING; *buffer++ = (uint8_t)0x13U; - ++*nconsumed_out; + ++*written_out; encoder->header_position++; /* fall through */ @@ -59,7 +60,7 @@ liblss16_encode_from_colour_index(struct liblss16_encoder *encoder, void *buffer if (!size--) return LIBLSS16_ENCODE_RUNNING; *buffer++ = (uint8_t)0x14U; - ++*nconsumed_out; + ++*written_out; encoder->header_position++; /* fall through */ @@ -67,7 +68,7 @@ liblss16_encode_from_colour_index(struct liblss16_encoder *encoder, void *buffer if (!size--) return LIBLSS16_ENCODE_RUNNING; *buffer++ = (uint8_t)encoder->header.width; - ++*nconsumed_out; + ++*written_out; encoder->header_position++; /* fall through */ @@ -75,7 +76,7 @@ liblss16_encode_from_colour_index(struct liblss16_encoder *encoder, void *buffer if (!size--) return LIBLSS16_ENCODE_RUNNING; *buffer++ = (uint8_t)(encoder->header.width >> 8); - ++*nconsumed_out; + ++*written_out; encoder->header_position++; /* fall through */ @@ -83,7 +84,7 @@ liblss16_encode_from_colour_index(struct liblss16_encoder *encoder, void *buffer if (!size--) return LIBLSS16_ENCODE_RUNNING; *buffer++ = (uint8_t)encoder->header.height; - ++*nconsumed_out; + ++*written_out; encoder->header_position++; /* fall through */ @@ -91,7 +92,7 @@ liblss16_encode_from_colour_index(struct liblss16_encoder *encoder, void *buffer if (!size--) return LIBLSS16_ENCODE_RUNNING; *buffer++ = (uint8_t)(encoder->header.height >> 8); - ++*nconsumed_out; + ++*written_out; encoder->header_position++; /* fall through */ @@ -102,8 +103,8 @@ liblss16_encode_from_colour_index(struct liblss16_encoder *encoder, void *buffer while (encoder->header_position < 8U + 16U * 3U) { if (!size--) return LIBLSS16_ENCODE_RUNNING; - *buffer++ = ((const uint8_t *)encoder->header.colour_map)[encoder->header_position++]; - ++*nconsumed_out; + *buffer++ = ((const uint8_t *)encoder->header.colour_map)[encoder->header_position - 8U]; + ++*written_out; encoder->header_position++; } @@ -121,8 +122,24 @@ liblss16_encode_from_colour_index(struct liblss16_encoder *encoder, void *buffer } } + if (!encoder->x_rem) + goto end_of_image; + while (npixels--) { if (*pixels == encoder->previous) { + if (encoder->repetition == 255U + 16U) { + encoder->buffered[encoder->nbuffered++] = encoder->previous; + encoder->buffered[encoder->nbuffered++] = 0; + encoder->buffered[encoder->nbuffered++] = (uint8_t)15U; + encoder->buffered[encoder->nbuffered++] = (uint8_t)15U; + + n = flush_buffer(encoder, buffer, size); + buffer = &buffer[n]; + size -= n; + *written_out += n; + + encoder->repetition = 0U; + } encoder->repetition++; } else { if (!encoder->repetition) { @@ -131,7 +148,7 @@ liblss16_encode_from_colour_index(struct liblss16_encoder *encoder, void *buffer encoder->buffered[encoder->nbuffered++] = encoder->previous; encoder->buffered[encoder->nbuffered++] = (uint8_t)encoder->repetition; } else { - unsigned value = encoder->repetition - 16U; + value = encoder->repetition - 16U; encoder->buffered[encoder->nbuffered++] = encoder->previous; encoder->buffered[encoder->nbuffered++] = 0; encoder->buffered[encoder->nbuffered++] = (uint8_t)(value & 15U); @@ -145,13 +162,28 @@ liblss16_encode_from_colour_index(struct liblss16_encoder *encoder, void *buffer buffer = &buffer[n]; size -= n; *written_out += n; - if (encoder->nbuffered > 1U) - return LIBLSS16_ENCODE_RUNNING; } ++pixels; ++*nconsumed_out; + --encoder->x_rem; + if (encoder->nbuffered > 1U) + return LIBLSS16_ENCODE_RUNNING; + + if (!encoder->x_rem) { + end_of_image: + if (!encoder->repetition) { + /* do nothing */ + } else if (encoder->repetition < 16U) { + encoder->buffered[encoder->nbuffered++] = encoder->previous; + encoder->buffered[encoder->nbuffered++] = (uint8_t)encoder->repetition; + } else { + value = encoder->repetition - 16U; + encoder->buffered[encoder->nbuffered++] = encoder->previous; + encoder->buffered[encoder->nbuffered++] = 0; + encoder->buffered[encoder->nbuffered++] = (uint8_t)(value & 15U); + encoder->buffered[encoder->nbuffered++] = (uint8_t)(value >> 4); + } - if (!--encoder->x_rem) { encoder->previous = 0; encoder->repetition = 0; encoder->x_rem = encoder->header.width; diff --git a/liblss16_encoder_init.c b/liblss16_encoder_init.c index d94d4fa..ca99cfa 100644 --- a/liblss16_encoder_init.c +++ b/liblss16_encoder_init.c @@ -9,7 +9,7 @@ int liblss16_encoder_init(struct liblss16_encoder *encoder, const struct liblss16_header *header, - int rgb6, enum liblss16_encode_error *error_out) + int rgb6, enum liblss16_encode_error *error_out) { int i; @@ -16,7 +16,7 @@ Header format: Image width (number of pixels horizontally): unsigned 16-bit integer, little endian. -Image height (number of pixels horizontally): unsigned 16-bit integer, little endian, +Image height (number of pixels vertically): unsigned 16-bit integer, little endian, however the most significant bit must be cleared. Colour palette: 16 RGB-tuples, each tuple is 3 bytes: red, green, blue. @@ -32,7 +32,7 @@ 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, +If a nibble has 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 diff --git a/lss16toppm.c b/lss16toppm.c index 48c9b93..e44860c 100644 --- a/lss16toppm.c +++ b/lss16toppm.c @@ -82,7 +82,7 @@ main(int argc, char *argv[]) for (off = 0; off < n;) { state = liblss16_decode_to_colour_index(&decoder, &buf[off], n - off, &consumed, - pixels, sizeof(pixels) / sizeof(*pixels), &npixels, &error); + pixels, sizeof(pixels) / sizeof(*pixels), &npixels, &error); off += consumed; if (state == LIBLSS16_DECODE_ERROR) { goto error; @@ -123,7 +123,7 @@ main(int argc, char *argv[]) writeall(wbuf, pending); state = liblss16_decode_to_colour_index(&decoder, NULL, 0, &consumed, pixels, - sizeof(pixels) / sizeof(*pixels), &npixels, &error); + sizeof(pixels) / sizeof(*pixels), &npixels, &error); if (state == LIBLSS16_DECODE_ERROR) { error: fprintf(stderr, "%s: %s\n", argv0, liblss16_decode_strerror(error)); diff --git a/ppmtolss16.1 b/ppmtolss16.1 index edfad63..299a15a 100644 --- a/ppmtolss16.1 +++ b/ppmtolss16.1 @@ -86,6 +86,10 @@ Early versions of SYSLINUX's implementation of only supported raw Portable Pixmap (P6 PPM) files without comments. +.SH NOTES +This implementation is significantly more capable of +producing good images than SYSLINUX's implementation. + .SH SEE ALSO .BR lss16 (5), .BR lss16toppm (1), diff --git a/ppmtolss16.c b/ppmtolss16.c index 1f2ec1a..5db4a39 100644 --- a/ppmtolss16.c +++ b/ppmtolss16.c @@ -7,6 +7,7 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <libquanta.h> #if defined(__clang__) # pragma clang diagnostic ignored "-Wunsafe-buffer-usage" @@ -31,7 +32,7 @@ static int invert; static void -writeall(char *data, size_t n) +writeall(const char *data, size_t n) { ssize_t r; @@ -121,6 +122,7 @@ static size_t read_dimension(size_t p, size_t *value) { size_t digit; + *value = 0; for (;;) { if (p == len) { if (eof) @@ -437,6 +439,55 @@ read_image_bits(void) } +static void +quantise(struct liblss16_header *header, int coloured) +{ + size_t i, nchannels = coloured ? 3U : 1U; + struct libquanta_channel channels[3]; + struct libquanta_palette *palette; + struct libquanta_image *image; + + memset(channels, 0, sizeof(channels)); + + for (i = 0; i < nchannels; i++) { + channels[i].bits_in = 6; + channels[i].bits_out = 6; + channels[i].image_width = width; + channels[i].image_height = height; + channels[i].image_row_size = nchannels * width; + channels[i].image_cell_size = nchannels; + channels[i].image = &buf[i]; + } + + palette = libquanta_malloc_palette(16, nchannels); + if (!palette) { + fprintf(stderr, "%s: libquanta_malloc_palette: %s\n", argv0, strerror(errno)); + exit(3); + } + + image = libquanta_quantise(palette, &channels[0], coloured ? &channels[1] : NULL, &channels[2], NULL); + if (!image) { + fprintf(stderr, "%s: libquanta_quantise: %s\n", argv0, strerror(errno)); + exit(3); + } + + for (i = 0; i < len; i++) + buf[i] = (char)image->image[i]; + + for (i = 0; i < palette->size; i++) { + header->colour_map[i].r = (uint8_t)palette->palette[i * nchannels + (coloured ? 0U : 0U)]; + header->colour_map[i].g = (uint8_t)palette->palette[i * nchannels + (coloured ? 1U : 0U)]; + header->colour_map[i].b = (uint8_t)palette->palette[i * nchannels + (coloured ? 2U : 0U)]; + } + memset(&header->colour_map[palette->size], + header->colour_map[palette->size - 1U].b, + (16U - palette->size) * sizeof(*header->colour_map)); + + free(image); + free(palette); +} + + int main(int argc, char *argv[]) { @@ -541,19 +592,23 @@ main(int argc, char *argv[]) header.colour_map[!invert].g = 63U; header.colour_map[!invert].b = 63U; } else if (maptype == 2) { - /* TODO convert to 16 colours -- greyscale values [0, 63], quantize to 16 colours and map Y to (Y, Y, Y) */ + quantise(&header, 0); } else { - /* TODO convert to 16 colours -- [0, 63]-triplet values, quantize to 16 colours */ + if (len % 3) + not_pnm(); + len /= 3; + quantise(&header, 1); } liblss16_optimise(&header, (uint8_t *)buf); if (liblss16_encoder_init(&encoder, &header, 1, &error)) { - fprintf(stderr, "%s:liblss16_encoder_init: %s\n", argv0, liblss16_encode_strerror(error)); + fprintf(stderr, "%s: liblss16_encoder_init: %s\n", argv0, liblss16_encode_strerror(error)); exit(3); } off = 0; + do { - state = liblss16_encode_from_colour_index(&encoder, wbuf, sizeof(buf), &written, + state = liblss16_encode_from_colour_index(&encoder, wbuf, sizeof(wbuf), &written, (const uint8_t *)&buf[off], len - off, &consumed); off += consumed; writeall(wbuf, written); |
