Skip to content

Instantly share code, notes, and snippets.

@uobikiemukot
Last active August 29, 2015 14:07
Show Gist options
  • Save uobikiemukot/7adab29310caf0be6f7a to your computer and use it in GitHub Desktop.
Save uobikiemukot/7adab29310caf0be6f7a to your computer and use it in GitHub Desktop.
support variable color bitfield
commit 956bd5e8ddc913ad69ccc878eb0c321ca23ae4b5
Author: uobikiemukot <uobikiemukot@gmail.com>
Date: Mon Oct 6 23:26:31 2014 +0900
add sixel_normalize_bitfield()
diff --git a/include/sixel.h.in b/include/sixel.h.in
index 1ad4c62..73f648c 100644
--- a/include/sixel.h.in
+++ b/include/sixel.h.in
@@ -81,6 +81,18 @@ enum builtinDither {
BUILTIN_XTERM256 = 3, /* xterm 256color */
};
+/* bitfield type of input image */
+enum colorBitfield {
+ COLOR_RGB555 = 0, /* 15 bpp */
+ COLOR_RGB565 = 1, /* 16 bpp */
+ COLOR_RGB888 = 2, /* 24 bpp */
+ COLOR_ARGB8888 = 3, /* 32 bpp */
+ COLOR_RGBA8888 = 4, /* 32 bpp */
+ GRAYSCALE_G8 = 5, /* 8 bpp grayscale */
+ GRAYSCALE_AG88 = 6, /* 16 bpp grayscale + alpha */
+ GRAYSCALE_GA88 = 7, /* 16 bpp grayscale + alpha */
+};
+
#ifndef LIBSIXEL_DITHER_H
/* dither context object */
@@ -163,7 +175,7 @@ sixel_dither_initialize(sixel_dither_t *dither, /* dither context objec
unsigned char /* in */ *data, /* sample image */
int /* in */ width, /* image width */
int /* in */ height, /* image height */
- int /* in */ depth, /* pixel depth, now only '3' is supported */
+ int /* in */ bitfield, /* one of enum colorBitfield */
int /* in */ method_for_largest, /* method for finding the largest dimention */
int /* in */ method_for_rep, /* method for choosing a color from the box */
int /* in */ quality_mode); /* quality of histgram processing */
@@ -202,7 +214,7 @@ int
sixel_encode(unsigned char /* in */ *pixels, /* pixel bytes */
int /* in */ width, /* image width */
int /* in */ height, /* image height */
- int /* in */ depth, /* pixel depth */
+ int /* in */ bitfield, /* one of enum colorBitfield */
sixel_dither_t /* in */ *dither, /* dither context */
sixel_output_t /* in */ *context); /* output context */
diff --git a/src/dither.c b/src/dither.c
index 4f777e2..f4b82b3 100644
--- a/src/dither.c
+++ b/src/dither.c
@@ -218,24 +218,108 @@ sixel_dither_get(int builtin_dither)
}
+static inline void
+get_rgb(unsigned char *data, int const bitfield, int depth,
+ unsigned char *r, unsigned char *g, unsigned char *b)
+{
+ unsigned int pixels = 0, low, high;
+ int count = 0;
+
+ while (count < depth) {
+ pixels = *(data + count) | (pixels << 8);
+ count++;
+ }
+
+ /* XXX: we should swap bytes (only necessary on LSByte first hardware?) */
+ if (depth == 2) {
+ low = pixels & 0xFF;
+ high = (pixels >> 8) & 0xFF;
+ pixels = (low << 8) | high;
+ }
+
+ if (bitfield == GRAYSCALE_G8 || bitfield == GRAYSCALE_AG88) {
+ *r = *g = *b = pixels & 0xFF;
+ } else if (bitfield == GRAYSCALE_GA88) {
+ *r = *g = *b = (pixels >> 8) & 0xFF;
+ } else if (bitfield == COLOR_RGB555) {
+ *r = ((pixels >> 10) & 0x1F) << 3;
+ *g = ((pixels >> 5) & 0x1F) << 3;
+ *b = ((pixels >> 0) & 0x1F) << 3;
+ } else if (bitfield == COLOR_RGB565) {
+ *r = ((pixels >> 11) & 0x1F) << 3;
+ *g = ((pixels >> 5) & 0x3F) << 2;
+ *b = ((pixels >> 0) & 0x1F) << 3;
+ } else if (bitfield == COLOR_RGBA8888) {
+ *r = (pixels >> 24) & 0xFF;
+ *g = (pixels >> 16) & 0xFF;
+ *b = (pixels >> 8) & 0xFF;
+ } else if (bitfield == COLOR_ARGB8888) {
+ *r = (pixels >> 16) & 0xFF;
+ *g = (pixels >> 8) & 0xFF;
+ *b = (pixels >> 0) & 0xFF;
+ }
+}
+
+
+void
+sixel_normalize_bitfield(unsigned char *dst, unsigned char *src, int width, int height, int const bitfield)
+{
+ int x, y, dst_offset, src_offset, depth;
+ unsigned char r, g, b;
+
+ if (bitfield == GRAYSCALE_G8)
+ depth = 1;
+ else if (bitfield == COLOR_RGB565 || bitfield == COLOR_RGB555
+ || bitfield == GRAYSCALE_GA88 || bitfield == GRAYSCALE_AG88)
+ depth = 2;
+ else /* COLOR_RGBA8888 or COLOR_ARGB8888 */
+ depth = 4;
+
+ for (y = 0; y < height; y++) {
+ for (x = 0; x < width; x++) {
+ src_offset = depth * (y * width + x);
+ dst_offset = 3 * (y * width + x);
+ get_rgb(src + src_offset, bitfield, depth, &r, &g, &b);
+
+ *(dst + dst_offset + 0) = r;
+ *(dst + dst_offset + 1) = g;
+ *(dst + dst_offset + 2) = b;
+ }
+ }
+}
+
int
sixel_dither_initialize(sixel_dither_t *dither, unsigned char *data,
- int width, int height, int depth,
+ int width, int height, int const bitfield,
int method_for_largest, int method_for_rep,
int quality_mode)
{
- unsigned char *buf;
+ unsigned char *buf, *normalized_pixels;
+
+ /* normalize bitfield */
+ normalized_pixels = malloc(width * height * 3);
+ if (normalized_pixels == NULL) {
+ return (-1);
+ }
+
+ if (bitfield != COLOR_RGB888) {
+ sixel_normalize_bitfield(normalized_pixels, data, width, height, bitfield);
+ } else {
+ memcpy(normalized_pixels, data, width * height * 3);
+ }
- buf = LSQ_MakePalette(data, width, height, depth,
+ buf = LSQ_MakePalette(normalized_pixels, width, height, 3,
dither->reqcolors, &dither->ncolors,
&dither->origcolors,
dither->method_for_largest,
dither->method_for_rep,
dither->quality_mode);
if (buf == NULL) {
+ free(normalized_pixels);
return (-1);
}
- memcpy(dither->palette, buf, dither->ncolors * depth);
+ memcpy(dither->palette, buf, dither->ncolors * 3);
+ free(normalized_pixels);
free(buf);
dither->optimized = 1;
diff --git a/src/dither.h b/src/dither.h
index 8d7a16e..fac84f4 100644
--- a/src/dither.h
+++ b/src/dither.h
@@ -47,6 +47,9 @@ extern "C" {
unsigned char * sixel_apply_palette(unsigned char *pixels, int width, int height,
sixel_dither_t *dither);
+void sixel_normalize_bitfield(unsigned char *dst, unsigned char *src,
+ int width, int height, int const bitfield);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/tosixel.c b/src/tosixel.c
index 8d841b2..2fe4bac 100644
--- a/src/tosixel.c
+++ b/src/tosixel.c
@@ -363,19 +363,33 @@ sixel_encode_impl(unsigned char *pixels, int width, int height,
int sixel_encode(unsigned char /* in */ *pixels, /* pixel bytes */
int /* in */ width, /* image width */
int /* in */ height, /* image height */
- int /* in */ depth, /* pixel depth */
+ int const /* in */ bitfield, /* color bitfield */
sixel_dither_t /* in */ *dither, /* dither context */
sixel_output_t /* in */ *context) /* output context */
{
int ret;
- unsigned char *paletted_pixels;
+ unsigned char *paletted_pixels, *normalized_pixels;
sixel_dither_ref(dither);
+ /* normalize bitfield */
+ normalized_pixels = malloc(width * height * 3);
+ if (normalized_pixels == NULL) {
+ sixel_dither_unref(dither);
+ return (-1);
+ }
+
+ if (bitfield != COLOR_RGB888) {
+ sixel_normalize_bitfield(normalized_pixels, pixels, width, height, bitfield);
+ } else {
+ memcpy(normalized_pixels, pixels, width * height * 3);
+ }
+
/* apply palette */
- paletted_pixels = sixel_apply_palette(pixels, width, height, dither);
+ paletted_pixels = sixel_apply_palette(normalized_pixels, width, height, dither);
if (paletted_pixels == NULL) {
sixel_dither_unref(dither);
+ free(normalized_pixels);
return (-1);
}
@@ -384,6 +398,7 @@ int sixel_encode(unsigned char /* in */ *pixels, /* pixel bytes */
dither->keycolor, context);
sixel_dither_unref(dither);
+ free(normalized_pixels);
free(paletted_pixels);
return 0;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment