aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--Makefile2
-rw-r--r--config.mk2
-rw-r--r--liblss16.h6
-rw-r--r--liblss16_encode_from_colour_index.c70
-rw-r--r--liblss16_encoder_init.c2
-rw-r--r--lss16.54
-rw-r--r--lss16toppm.c4
-rw-r--r--ppmtolss16.14
-rw-r--r--ppmtolss16.c65
9 files changed, 126 insertions, 33 deletions
diff --git a/Makefile b/Makefile
index 0de3e2d..8e457cd 100644
--- a/Makefile
+++ b/Makefile
@@ -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 -- $@
diff --git a/config.mk b/config.mk
index 166cb80..d66022d 100644
--- a/config.mk
+++ b/config.mk
@@ -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
diff --git a/liblss16.h b/liblss16.h
index b02b338..3747c2f 100644
--- a/liblss16.h
+++ b/liblss16.h
@@ -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;
diff --git a/lss16.5 b/lss16.5
index fad1dd8..0740e4f 100644
--- a/lss16.5
+++ b/lss16.5
@@ -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);