Last active
August 29, 2015 14:07
-
-
Save uobikiemukot/7adab29310caf0be6f7a to your computer and use it in GitHub Desktop.
support variable color bitfield
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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