diff --git a/zrle.c b/zrle.c new file mode 100644 index 0000000..6d66fe6 --- /dev/null +++ b/zrle.c @@ -0,0 +1,126 @@ +#include "rfb-proto.h" + +#include +#include +#include +#include +#include +#include + +#define POPCOUNT(x) __builtin_popcount(x) + +void pixel_format_into_native(struct rfb_pixel_format *fmt) +{ +#if __BYTE_ORDER__ == __LITTLE_ENDIAN__ + if (!fmt->big_endian_flag) + return; + + fmt->big_endian_flag = 0; +#else + if (fmt->big_endian_flag) + return; + + fmt->big_endian_flag = 1; +#endif + + fmt->red_shift = fmt->bits_per_pixel - fmt->red_shift; + fmt->green_shift = fmt->bits_per_pixel - fmt->green_shift; + fmt->blue_shift = fmt->bits_per_pixel - fmt->blue_shift; +} + +void pixel32_to_cpixel(uint8_t *restrict dst, + const struct rfb_pixel_format* dst_fmt, + const uint32_t *restrict src, + const struct rfb_pixel_format* src_fmt, + size_t bytes_per_cpixel, size_t len) +{ + assert(dst_fmt->true_colour_flag); + assert(dst_fmt->bits_per_pixel <= 32); + assert(dst_fmt->depth <= 24); + assert(bytes_per_cpixel <= 3 && bytes_per_cpixel >= 1); + + uint32_t src_red_shift = src_fmt->red_shift; + uint32_t src_green_shift = src_fmt->green_shift; + uint32_t src_blue_shift = src_fmt->blue_shift; + + uint32_t dst_red_shift = dst_fmt->red_shift; + uint32_t dst_green_shift = dst_fmt->green_shift; + uint32_t dst_blue_shift = dst_fmt->blue_shift; + + uint32_t src_red_max = src_fmt->red_max; + uint32_t src_green_max = src_fmt->green_max; + uint32_t src_blue_max = src_fmt->blue_max; + + uint32_t dst_red_max = dst_fmt->red_max; + uint32_t dst_green_max = dst_fmt->green_max; + uint32_t dst_blue_max = dst_fmt->blue_max; + + uint32_t src_red_bits = POPCOUNT(src_fmt->red_max); + uint32_t src_green_bits = POPCOUNT(src_fmt->green_max); + uint32_t src_blue_bits = POPCOUNT(src_fmt->blue_max); + + uint32_t dst_red_bits = POPCOUNT(dst_fmt->red_max); + uint32_t dst_green_bits = POPCOUNT(dst_fmt->green_max); + uint32_t dst_blue_bits = POPCOUNT(dst_fmt->blue_max); + + uint32_t dst_endian_correction; + +#define CONVERT_PIXELS(cpx, px) \ + { \ + uint32_t r, g, b; \ + r = ((px >> src_red_shift) & src_red_max) << dst_red_bits \ + >> src_red_bits << dst_red_shift; \ + g = ((px >> src_green_shift) & src_green_max) << dst_green_bits \ + >> src_green_bits << dst_green_shift; \ + b = ((px >> src_blue_shift) & src_blue_max) << dst_blue_bits \ + >> src_blue_bits << dst_blue_shift; \ + cpx = r | g | b; \ + } + + switch (bytes_per_cpixel) { + case 3: + dst_endian_correction = dst_fmt->big_endian_flag ? 16 : 0; + + while (len--) { + uint32_t cpx, px = *src++; + + CONVERT_PIXELS(cpx, px) + + *dst++ = (cpx >> (0 ^ dst_endian_correction)) & 0xff; + *dst++ = (cpx >> 8) & 0xff; + *dst++ = (cpx >> (16 ^ dst_endian_correction)) & 0xff; + } + break; + case 2: + dst_endian_correction = dst_fmt->big_endian_flag ? 8 : 0; + + while (len--) { + uint32_t cpx, px = *src++; + + CONVERT_PIXELS(cpx, px) + + *dst++ = (cpx >> (0 ^ dst_endian_correction)) & 0xff; + *dst++ = (cpx >> (8 ^ dst_endian_correction)) & 0xff; + } + break; + case 1: + while (len--) { + uint32_t cpx, px = *src++; + + CONVERT_PIXELS(cpx, px) + + *dst++ = cpx & 0xff; + } + break; + default: + abort(); + } + +#undef CONVERT_PIXELS +} + +void zrle_encode_tile(uint8_t* dst, const uint32_t *src, int stride, + int width, int height) +{ + +}