/**************************************************************************/ /* */ /* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ /* Copyright (c) 2008-2014 Oleksandr Shneyder */ /* Copyright (c) 2014-2016 Ulrich Sibiller */ /* Copyright (c) 2014-2016 Mihai Moldovan */ /* Copyright (c) 2011-2016 Mike Gabriel */ /* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ /* */ /* NXCOMPEXT, NX protocol compression and NX extensions to this software */ /* are copyright of the aforementioned persons and companies. */ /* */ /* Redistribution and use of the present software is allowed according */ /* to terms specified in the file LICENSE which comes in the source */ /* distribution. */ /* */ /* All rights reserved. */ /* */ /* NOTE: This software has received contributions from various other */ /* contributors, only the core maintainers and supporters are listed as */ /* copyright holders. Please contact us, if you feel you should be listed */ /* as copyright holder, as well. */ /* */ /**************************************************************************/ #include #include #include #include "Mask.h" #define PANIC #define WARNING #undef TEST #undef DEBUG /* * Try first to reduce to a white or black * pixel. If not possible, apply the mask. * Note that correction is applied at the * time pixel is unpacked. */ #define MaskPixel(red, green, blue, mask) \ \ if (red > mask -> white_threshold && \ green > mask -> white_threshold && \ blue > mask -> white_threshold) \ { \ red = green = blue = 0xff; \ } \ else if (red < mask -> black_threshold && \ green < mask -> black_threshold && \ blue < mask -> black_threshold) \ { \ red = green = blue = 0x00; \ } \ else \ { \ red = red & mask -> color_mask; \ green = green & mask -> color_mask; \ blue = blue & mask -> color_mask; \ } int MaskImage(const ColorMask *mask, XImage *src_image, XImage *dst_image) { unsigned long pixel; register unsigned int red; register unsigned int green; register unsigned int blue; register unsigned long data_size; register unsigned int i; data_size = (src_image -> bytes_per_line * src_image -> height) >> 2; #ifdef TEST fprintf(stderr, "******MaskImage: Going to mask image with [%d] bits per pixel.\n", src_image -> bits_per_pixel); #endif if (src_image -> bits_per_pixel == 24 || src_image -> bits_per_pixel == 32) { register unsigned char *pixel_addr; for (i = 0; i < data_size; i++) { pixel = ((unsigned long *) src_image -> data)[i]; pixel_addr = (unsigned char *) &pixel; red = pixel_addr[2]; green = pixel_addr[1]; blue = pixel_addr[0]; #ifdef DEBUG fprintf(stderr, "******MaskImage: 24/32 bits original R [%d] G [%d] B [%d] A [%d].\n", red, green, blue, pixel_addr[3]); #endif MaskPixel(red, green, blue, mask); #ifdef DEBUG fprintf(stderr, "******MaskImage: 24/32 bits masked R [%d] G [%d] B [%d] A [%d].\n", red, green, blue, pixel_addr[3]); #endif #ifdef DEBUG fprintf(stderr, "******MaskImage: 24/32 bits pixel 0x%lx", pixel); #endif pixel_addr[2] = red; pixel_addr[1] = green; pixel_addr[0] = blue; ((unsigned long*)dst_image -> data)[i] = pixel; #ifdef DEBUG fprintf(stderr, " -> 0x%lx\n", pixel); #endif } return 1; } else if (src_image -> bits_per_pixel == 16) { /* * FIXME: Masking doesn't work in 16 bpp. * unsigned long src_addr, *dst_addr; unsigned short *src_pixels_addr, *dst_pixels_addr; for (i = 0; i < data_size; i++) { src_addr = ((unsigned long *)src_image -> data)[i]; dst_addr = (unsigned long *)((unsigned long *)dst_image -> data + i); src_pixels_addr = ((unsigned short *) &src_addr); dst_pixels_addr = ((unsigned short *) dst_addr); red = (src_pixels_addr[0] & src_image -> red_mask) >> 8; green = (src_pixels_addr[0] & src_image -> green_mask) >> 3; blue = (src_pixels_addr[0] & src_image -> blue_mask) << 3; #ifdef DEBUG fprintf(stderr, "******MaskImage: 16 bits original R [%d] G [%d] B [%d].\n", red, green, blue); #endif MaskPixel(red, green, blue, mask); #ifdef DEBUG fprintf(stderr, "******MaskImage: 16 bits masked R [%d] G [%d] B [%d].\n", red, green, blue); #endif dst_pixels_addr[0] = ((red << 8) & src_image -> red_mask) | ((green << 3) & src_image -> green_mask) | ((blue >> 3) & src_image -> blue_mask); #ifdef DEBUG fprintf(stderr, "******MaskImage: 16 bits pixel 0x%x", dst_pixels_addr[0]); #endif red = (src_pixels_addr[1] & src_image -> red_mask) >> 8; green = (src_pixels_addr[1] & src_image -> green_mask) >> 3; blue = (src_pixels_addr[1] & src_image -> blue_mask) << 3; #ifdef DEBUG fprintf(stderr, "******MaskImage: 16 bits original R [%d] G [%d] B [%d].\n", red, green, blue); #endif MaskPixel(red, green, blue, mask); #ifdef DEBUG fprintf(stderr, "******MaskImage: 16 bits masked R [%d] G [%d] B [%d].\n", red, green, blue); #endif dst_pixels_addr[1] = ((red << 8) & src_image -> red_mask) | ((green << 3) & src_image -> green_mask) | ((blue >> 3) & src_image -> blue_mask); #ifdef DEBUG fprintf(stderr, "******MaskImage: 16 bits pixel 0x%x", dst_pixels_addr[0]); #endif } if (dst_image -> width & 0x00000001) { int card32_per_line; int i; card32_per_line = dst_image -> bytes_per_line >> 2; for (i = 0; i < dst_image -> height;) { ((CARD32 *) dst_image -> data)[(++i * card32_per_line) - 1] &= 0x0000ffff; } } * * End of FIXME. */ } else { #ifdef TEST fprintf(stderr, "******MaskImage: PANIC! Cannot apply mask with [%d] bits per pixel.\n", src_image -> bits_per_pixel); #endif return 0; } return 1; } int MaskInPlaceImage(const ColorMask *mask, XImage *image) { unsigned long pixel; register unsigned int red; register unsigned int green; register unsigned int blue; register unsigned int i; register unsigned long data_size; data_size = (image -> bytes_per_line * image -> height)>>2; #ifdef TEST fprintf(stderr, "******MaskInPlaceImage: Going to mask image with [%d] bits per pixel.\n", image -> bits_per_pixel); #endif if (image -> bits_per_pixel == 24 || image -> bits_per_pixel == 32) { register unsigned char *pixel_addr; for (i = 0; i < data_size; i++) { pixel = ((unsigned long *) image -> data)[i]; pixel_addr = (unsigned char *) &pixel; red = pixel_addr[2]; green = pixel_addr[1]; blue = pixel_addr[0]; #ifdef DEBUG fprintf(stderr, "******MaskInPlaceImage: 24/32 bits original R [%d] G [%d] B [%d] A [%d].\n", red, green, blue, pixel_addr[3]); #endif MaskPixel(red, green, blue, mask); #ifdef DEBUG fprintf(stderr, "******MaskInPlaceImage: 24/32 bits masked R [%d] G [%d] B [%d] A [%d].\n", red, green, blue, pixel_addr[3]); #endif #ifdef DEBUG fprintf(stderr, "******MaskInPlaceImage: 24/32 bits pixel 0x%lx", pixel); #endif pixel_addr[2] = red; pixel_addr[1] = green; pixel_addr[0] = blue; ((unsigned long *) image -> data)[i] = pixel; #ifdef DEBUG fprintf(stderr, " -> 0x%lx\n", pixel); #endif } return 1; } else if (image -> bits_per_pixel == 16) { /* * FIXME: Mask doesn't still work for 16 bits. * unsigned long addr; register unsigned short *pixels_addr; for (i = 0; i < data_size; i++) { addr = ((unsigned long *) image -> data)[i]; pixels_addr = ((unsigned short *) &addr); red = (pixels_addr[0] & image -> red_mask) >> 8; green = (pixels_addr[0] & image -> green_mask) >> 3; blue = (pixels_addr[0] & image -> blue_mask) << 3; #ifdef DEBUG fprintf(stderr, "******MaskInPlaceImage: 16 bits original R [%d] G [%d] B [%d].\n", red, green, blue); #endif MaskPixel(red, green, blue, mask); #ifdef DEBUG fprintf(stderr, "******MaskInPlaceImage: 16 bits masked R [%d] G [%d] B [%d].\n", red, green, blue); #endif pixels_addr[0] = ((red << 8) & image -> red_mask) | ((green << 3) & image -> green_mask) | ((blue >> 3) & image -> blue_mask); #ifdef DEBUG fprintf(stderr, "******MaskInPlaceImage: 16 bits pixel 0x%x", pixels_addr[0]); #endif red = (pixels_addr[1] & image -> red_mask) >> 8; green = (pixels_addr[1] & image -> green_mask) >> 3; blue = (pixels_addr[1] & image -> blue_mask) << 3; #ifdef DEBUG fprintf(stderr, "******MaskInPlaceImage: 16 bits original R [%d] G [%d] B [%d].\n", red, green, blue); #endif MaskPixel(red, green, blue, mask); #ifdef DEBUG fprintf(stderr, "******MaskInPlaceImage: 16 bits masked R [%d] G [%d] B [%d].\n", red, green, blue); #endif pixels_addr[1] = ((red << 8) & image -> red_mask) | ((green << 3) & image -> green_mask) | ((blue >> 3) & image -> blue_mask); #ifdef DEBUG fprintf(stderr, "******MaskInPlaceImage: 16 bits pixel 0x%x", pixels_addr[1]); #endif } if (image -> width & 0x00000001) { int card32_per_line; int i; card32_per_line = image -> bytes_per_line >> 2; for (i = 0; i < image -> height;) { ((CARD32 *) image -> data)[(++i * card32_per_line) - 1] &= 0x0000ffff; } } * * End of FIXME. */ } else { #ifdef TEST fprintf(stderr, "******MaskImage: PANIC! Cannot apply mask with [%d] bits per pixel.\n", image -> bits_per_pixel); #endif return 0; } return 1; } static int Pack16To8(unsigned int src_data_size, XImage *src_image, XImage *dst_image) { unsigned short *src_pixel = (unsigned short *) src_image -> data; unsigned char *dst_pixel = (unsigned char *) dst_image -> data; #ifdef DEBUG unsigned int counter = 0; #endif while (src_pixel < ((unsigned short *) (src_image -> data + src_data_size))) { #ifdef DEBUG fprintf(stderr, "******PackImage: Pixel [%d] value [0x%x] red [0x%x] green [0x%x] blue [0x%x].\n", counter, *src_pixel, (*src_pixel & 0xc000) >> 8, ((*src_pixel & 0x600) >> 3), (*src_pixel & 0x18) << 3); #endif if (*src_pixel == 0x0) { *dst_pixel = 0x0; } else if (*src_pixel == 0xffff) { *dst_pixel = 0xff; } else { *dst_pixel = ((*src_pixel & 0xc000) >> 10) | ((*src_pixel & 0x600) >> 7) | ((*src_pixel & 0x18) >> 3); } #ifdef DEBUG fprintf(stderr, "******PackImage: Pixel [%d] destination [0x%x].\n", counter++, *dst_pixel); #endif src_pixel++; dst_pixel++; } return 1; } static int Pack24To8(unsigned int src_data_size, XImage *src_image, XImage *dst_image) { unsigned char *src_pixel = (unsigned char *) src_image -> data; unsigned char *dst_pixel = (unsigned char *) dst_image -> data; int i; unsigned int bytes_per_line = src_image -> bytes_per_line; unsigned char *end_of_line = (unsigned char *) (src_pixel + bytes_per_line); #ifdef DEBUG unsigned int counter = 0; #endif for (i = 0; i < src_image -> height; i++ ) { #ifdef DEBUG fprintf(stderr, "******PackImage: Pixel [%d] value [0x%x%x%x] red [0x%x] green [0x%x] blue [0x%x].\n", counter, src_pixel[0], src_pixel[1], src_pixel[2], src_pixel[0] & 0xc0, src_pixel[1] & 0xc0, src_pixel[2] & 0xc0); #endif while(src_pixel < end_of_line - 2) { if (src_pixel[0] == 0x00 && src_pixel[1] == 0x00 && src_pixel[2] == 0x00) { *dst_pixel = 0x0; } else if (src_pixel[0] == 0xff && src_pixel[1] == 0xff && src_pixel[2] == 0xff) { *dst_pixel = 0xff; } else { /* * Pixel layout: * * 24 bit RRRRR000 GGGGG000 BBBBB000 -> 8 bit 00RRGGBB */ *dst_pixel = (src_pixel[0] & 0xc0) >> 2 | ((src_pixel[1] & 0xc0) >> 4) | ((src_pixel[2] & 0xc0) >> 6); } #ifdef DEBUG fprintf(stderr, "******PackImage: Pixel [%d] destination [0x%x].\n", counter++, *dst_pixel); #endif src_pixel += 3; dst_pixel += 1; } src_pixel = end_of_line; end_of_line += bytes_per_line; } return 1; } static int Pack24To16(unsigned int src_data_size, XImage *src_image, XImage *dst_image) { unsigned char *src_pixel = (unsigned char *) src_image -> data; unsigned short *dst_pixel = (unsigned short *) dst_image -> data; int i; unsigned int bytes_per_line = src_image -> bytes_per_line; unsigned char *end_of_line = (unsigned char *) (src_pixel + bytes_per_line); #ifdef DEBUG unsigned int counter = 0; #endif for (i = 0; i < src_image -> height; i++ ) { while(src_pixel < end_of_line - 2) { #ifdef DEBUG fprintf(stderr, "******PackImage: Pixel [%d] value [0x%x%x%x] red [0x%x] green [0x%x] blue [0x%x].\n", counter, src_pixel[0], src_pixel[1], src_pixel[2], src_pixel[0] & 0xf8, src_pixel[1] & 0xf8, src_pixel[2] & 0xf8); #endif if (src_pixel[0] == 0x00 && src_pixel[1] == 0x00 && src_pixel[2] == 0x00) { *dst_pixel = 0x0; } else if (src_pixel[0] == 0xff && src_pixel[1] == 0xff && src_pixel[2] == 0xff) { *dst_pixel = 0xffff; } else { /* * Pixel layout: * * 24 bit RRRRR000 GGGGG000 BBBBB000 -> 16 bit 0RRRRRGG GGGBBBBB */ *dst_pixel = ((src_pixel[0] & 0xf8) << 7) | ((src_pixel[1] & 0xf8) << 2) | ((src_pixel[2] & 0xf8) >> 3); } #ifdef DEBUG fprintf(stderr, "******PackImage: Pixel [%d] destination [0x%x].\n", counter++, *dst_pixel); #endif src_pixel += 3; dst_pixel += 1; } src_pixel = end_of_line; end_of_line += bytes_per_line; } return 1; } static int Pack32To8(unsigned int src_data_size, XImage *src_image, XImage *dst_image) { unsigned int *src_pixel = (unsigned int *) src_image -> data; unsigned char *dst_pixel = (unsigned char *) dst_image -> data; #ifdef DEBUG unsigned int counter = 0; #endif while (src_pixel < ((unsigned int *) (src_image -> data + src_data_size))) { #ifdef DEBUG fprintf(stderr, "******PackImage: Pixel [%d] value [0x%x] red [0x%x] green [0x%x] blue [0x%x].\n", counter, *src_pixel, (*src_pixel & 0xc00000), (*src_pixel & 0xc000), (*src_pixel & 0xc0)); #endif if (*src_pixel == 0x0) { *dst_pixel = 0x0; } else if (*src_pixel == 0xffffff) { *dst_pixel = 0xff; } else { *dst_pixel = ((*src_pixel & 0xc00000) >> 18) | ((*src_pixel & 0xc000) >> 12) | ((*src_pixel & 0xc0) >> 6); } #ifdef DEBUG fprintf(stderr, "******PackImage: Pixel [%d] destination [0x%x].\n", counter++, *dst_pixel); #endif src_pixel++; dst_pixel++; } return 1; } static int Pack32To16(unsigned int src_data_size, XImage *src_image, XImage *dst_image) { unsigned int *src_pixel = (unsigned int *) src_image -> data; unsigned short *dst_pixel = (unsigned short *) dst_image -> data; #ifdef DEBUG unsigned int counter = 0; #endif while (src_pixel < ((unsigned int *) (src_image -> data + src_data_size))) { #ifdef DEBUG fprintf(stderr, "******PackImage: Pixel [%d] value [0x%x] red [0x%x] green [0x%x] blue [0x%x].\n", counter, *src_pixel, (*src_pixel & 0xf80000), (*src_pixel & 0xf800), (*src_pixel & 0xf8)); #endif if (*src_pixel == 0x0) { *dst_pixel = 0x0; } else if (*src_pixel == 0xffffff) { *dst_pixel = 0xffff; } else { *dst_pixel = ((*src_pixel & 0xf80000) >> 9) | ((*src_pixel & 0xf800) >> 6) | ((*src_pixel & 0xf8) >> 3); } #ifdef DEBUG fprintf(stderr, "******PackImage: Pixel [%d] destination [0x%x].\n", counter++, *dst_pixel); #endif src_pixel++; dst_pixel++; } return 1; } static int Pack32To24(unsigned int src_data_size, XImage *src_image, XImage *dst_image) { unsigned int *src_pixel = (unsigned int *) src_image -> data; unsigned char *dst_pixel = (unsigned char *) dst_image -> data; #ifdef DEBUG unsigned int counter = 0; #endif while (src_pixel < ((unsigned int *) (src_image -> data + src_data_size))) { #ifdef DEBUG fprintf(stderr, "******PackImage: Pixel [%d] value [0x%x] red [0x%x] green [0x%x] blue [0x%x].\n", counter, *src_pixel, ((*src_pixel & 0xff0000) >> 16), ((*src_pixel & 0x00ff00) >> 8), (*src_pixel & 0xff)); #endif if (*src_pixel == 0x0) { dst_pixel[0] = dst_pixel[1] = dst_pixel[2] = 0x0; } else if (*src_pixel == 0xffffff) { dst_pixel[0] = dst_pixel[1] = dst_pixel[2] = 0xff; } else { dst_pixel[0] = (*src_pixel & 0xff0000) >> 16; dst_pixel[1] = (*src_pixel & 0x00ff00) >> 8; dst_pixel[2] = (*src_pixel & 0x0000ff); } #ifdef DEBUG fprintf(stderr, "******PackImage: Pixel [%d] destination [0x%x], [0x%x], [0x%x].\n", counter++, dst_pixel[0], dst_pixel[1], dst_pixel[2]); #endif src_pixel += 1; dst_pixel += 3; } return 1; } int PackImage(unsigned int method, unsigned int src_data_size, XImage *src_image, unsigned int dst_data_size, XImage *dst_image) { unsigned int src_bits_per_pixel; unsigned int dst_bits_per_pixel; src_bits_per_pixel = src_image -> bits_per_pixel; dst_bits_per_pixel = MethodBitsPerPixel(method); #ifdef TEST fprintf(stderr, "******PackImage: Source bits per pixel [%d], destination bits per pixel [%d].\n", src_bits_per_pixel, dst_bits_per_pixel); fprintf(stderr, "******PackImage: Source data size [%d], destination data size [%d].\n", src_data_size, dst_data_size); #endif if (dst_bits_per_pixel >= src_bits_per_pixel) { #ifdef PANIC fprintf(stderr, "******PackImage: PANIC! Cannot pack image from [%d] to [%d] bytes per pixel.\n", src_bits_per_pixel, dst_bits_per_pixel); #endif return 0; } switch (src_bits_per_pixel) { case 16: { switch (dst_bits_per_pixel) { case 8: { return Pack16To8(src_data_size, src_image, dst_image); } default: { return 0; } } } case 24: { switch (dst_bits_per_pixel) { case 8: { return Pack24To8(src_data_size, src_image, dst_image); } case 16: { return Pack24To16(src_data_size, src_image, dst_image); } default: { return 0; } } } case 32: { switch (dst_bits_per_pixel) { case 8: { return Pack32To8(src_data_size, src_image, dst_image); } case 16: { return Pack32To16(src_data_size, src_image, dst_image); } case 24: { return Pack32To24(src_data_size, src_image, dst_image); } default: { return 0; } } } default: { return 0; } } } /* * Replace the ffs() call that may be not * present on some systems. */ int FindLSB(int word) { int t = word; int m = 1; int i = 0; for (; i < sizeof(word) << 3; i++, m <<= 1) { if (t & m) { return i + 1; } } return 0; }