home *** CD-ROM | disk | FTP | other *** search
- /* dither2x2.c
- * AUTHOR: Cy Booker, cy@cheepnis.demon.co.uk
- * LICENSE: FreeWare, Copyright (c) 1995 Cy Booker
- */
-
- #include "internal.h"
-
- #include <assert.h>
- #include <string.h> /* memset() */
-
- #include "OS:macros.h"
- #include "OS:hourglass.h"
-
-
-
- /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- */
-
- static void calculate_dither2x2(
- int dither[2][2],
- os_colour colour);
-
-
-
- static bits map_palette_entry_to_16bpp_colour(
- os_colour colour);
-
-
-
- /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- */
-
- extern bool process_gif_16bpp_dither2x2_66bit(
- const process_gif *p) {
- byte *rove;
- bits dest;
- int width, height;
- int x, y;
- const os_colour *palette;
- int line_length;
- int index;
- int dither[256][2][2];
-
- assert(p);
- assert(p->pixel_width > 0);
- assert(p->pixel_height > 0);
- assert(p->in_palette.colours);
-
- /*
- * pre-calculate dither table
- * to save a function call in middle loop
- * thus the compiler has more registers to play with
- */
- palette = p->in_palette.colours;
- for (index= p->in_palette.ncolours; (index > 0); ) {
- index--;
- calculate_dither2x2(dither[index], palette[index]);
- }
-
- /*
- * not we pre-load values from the process_gif array
- * because it considerably helps the compiler produce better code
- */
- rove = p->buffer;
- width = (p->pixel_width + 1) & ~1;
- height = p->pixel_height;
- line_length = p->line_length;
-
- for (y= height; (y > 0); y--) {
- if ((y & 7) == 0) {
- xhourglass_percentage((y * 100) / height);
- }
- for (x= width - 1; (x >= 0); x--) {
- assert((x & 1) == 1);
- /*
- * writing one 32-bit word is much faster than two 16-bit shorts
- */
- index = rove[x];
- dest = dither[index][y & 1][x & 1];
- x--;
- index = rove[x];
- dest <<= 16;
- dest |= dither[index][y & 1][x & 1];
- *(((int *)rove) + (((unsigned int)x) >> 1)) = dest;
- }
- rove += line_length;
- }
- return FALSE;
- }
-
-
-
- /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- * strictly speaking, this isn't a 66bit routine!
- * but I can't be arsed to recode it so it is, as the 48 bit routines are faster
- */
-
- static void calculate_dither2x2(
- int dither[2][2],
- os_colour colour) {
- int target_r, target_g, target_b;
- int r, g, b;
- bits tl;
- int tl_r, tl_g, tl_b;
- bits br;
- int br_r, br_g, br_b;
- bits tr;
- int tr_r, tr_g, tr_b;
- bits bl;
-
- /*
- * we now use ``colourtrans'' dithering algorithm, where X is the
- * destination colour, and all values are (r, g, b) tuples
- * topleft <-- X
- * bottomright <-- X - (topleft - X)
- * topright <-- X - (((topleft - X) + (bottomright - X)) / 2)
- * bottomleft <-- X - (((topleft - X) + (bottomright - X) + (topright - X)) / 3)
- *
- * personally, I don't see why the need for divisions, as surely we are using:
- * "OK we missed X by N, therefore compensate by choosing X - N"
- * but colourtrans is doing
- * missed by TL and missed by BR, therefore try X - ((TL+TR)/2)
- *
- * humph, it works, anyway
- */
-
- target_r = 31 * ((colour >> 8) & 0xff);
- target_g = 31 * ((colour >> 16) & 0xff);
- target_b = 31 * ((colour >> 24) & 0xff);
- tl = map_palette_entry_to_16bpp_colour(colour);
- tl_r = 255 * ((tl >> 0) & 0x1f);
- r = MAX((2 * target_r) - tl_r, 0) / 31;
- r = MIN(255, r);
- tl_g = 255 * ((tl >> 5) & 0x1f);
- g = MAX((2 * target_g) - tl_g, 0) / 31;
- g = MIN(255, g);
- tl_b = 255 * ((tl >> 10) & 0x1f);
- b = MAX((2 * target_b) - tl_b, 0) / 31;
- b = MIN(255, b);
- br = map_palette_entry_to_16bpp_colour((r << 8) | (g << 16) | (b << 24));
-
- br_r = 255 * ((br >> 0) & 0x1f);
- r = MAX((2 * 2 * target_r) - (tl_r + br_r), 0) / (2*31);
- r = MIN(255, r);
- br_g = 255 * ((br >> 5) & 0x1f);
- g = MAX((2 * 2 * target_g) - (tl_g + br_g), 0) / (2*31);
- g = MIN(255, g);
- br_b = 255 * ((br >> 10) & 0x1f);
- b = MAX((2 * 2 * target_b) - (tl_b + br_r), 0) / (2*31);
- b = MIN(255, b);
- tr = map_palette_entry_to_16bpp_colour((r << 8) | (g << 16) | (b << 24));
-
- tr_r = 255 * ((tr >> 0) & 0x1f);
- r = MAX((3 * 2 * target_r) - (tl_r + br_r + tr_r), 0) / (3*31);
- r = MIN(255, r);
- tr_g = 255 * ((tr >> 5) & 0x1f);
- g = MAX((3 * 2 * target_g) - (tl_g + br_g + tr_g), 0) / (3*31);
- g = MIN(255, g);
- tr_b = 255 * ((tr >> 10) & 0x1f);
- b = MAX((3 * 2 * target_b) - (tl_b + br_r + tr_b), 0) / (3*31);
- b = MIN(255, b);
- bl = map_palette_entry_to_16bpp_colour((r << 8) | (g << 16) | (b << 24));
-
- dither[0][0] = tl;
- dither[0][1] = tr;
- dither[1][0] = bl;
- dither[1][1] = br;
- }
-
-
-
- static bits map_palette_entry_to_16bpp_colour(
- os_colour colour) {
- int red, grn, blu;
-
- red = ((colour << (2*8)) >> 24) & 0xff; red = ((red * 0x1f) + 0x80) >> 8;
- grn = ((colour << (1*8)) >> 24) & 0xff; grn = ((grn * 0x1f) + 0x80) >> 8;
- blu = ((colour << (0*8)) >> 24) & 0xff; blu = ((blu * 0x1f) + 0x80) >> 8;
- return red | (grn << 5) | (blu << 10);
- }
-
-
-