canvas_imp_rgb.cpp 3.71 KB
#include "canvas_imp_rgb.h"
#include <cstdio>

void canvas_imp_rgb::compute_color_resolution(void) {
    for(unsigned rgb=red; rgb<=blue; rgb++) {
       unsigned mask_tmp=col_mask[rgb];

       for(col_shift[rgb]=0; (mask_tmp & 0x01) == 0; col_shift[rgb]++)
           mask_tmp>>=1;
       for(col_max[rgb]=1; mask_tmp & 0x01 == 1; col_max[rgb]*=2)
           mask_tmp>>=1;
       col_max[rgb]--;
    }
}

void canvas_imp_rgb::compute_light_table(void) {
   for(unsigned rgb=red; rgb<=blue; rgb++)
      for(unsigned c=0; c<=col_max[rgb]; c++)
         for(unsigned i=0; i<NUM_LIGHT_LEVELS; i++)
            light_table[rgb][c*NUM_LIGHT_LEVELS+i]=c*i/MAX_LIGHT_LEVELS;
}

void canvas_imp_rgb::compute_fog_table(void) {
   for(unsigned rgb=red; rgb<=blue; rgb++)
      for(unsigned c=0; c<=col_max[rgb]; c++)
         for(unsigned i=0; i<NUM_FOG_LEVELS; i++)
            fog_table[rgb][c*NUM_FOG_LEVELS+i]=
               c+(unsigned)(((float)i/MAX_FOG_LEVELS)*(col_max[rgb]-c));
}

canvas_imp_rgb::canvas_imp_rgb(unsigned long red_mask,
                               unsigned long green_mask,
                               unsigned long blue_mask,
                               char bytes_per_pixel,
                               char bytes_per_rgb) {
    this->col_mask[red]=red_mask;
    this->col_mask[green]=green_mask;
    this->col_mask[blue]=blue_mask;

    this->bytes_per_pixel=bytes_per_pixel;
    this->bytes_per_rgb=bytes_per_rgb;

    ext_max_red=255;
    ext_max_green=255;
    ext_max_blue=255;

    compute_color_resolution();

    light_table[red]=new unsigned[(col_max[red]+1)*NUM_LIGHT_LEVELS];
    light_table[green]=new unsigned[(col_max[green]+1)*NUM_LIGHT_LEVELS];
    light_table[blue]=new unsigned[(col_max[blue]+1)*NUM_LIGHT_LEVELS];
    fog_table[red]=new unsigned[(col_max[red]+1)*NUM_FOG_LEVELS];
    fog_table[green]=new unsigned[(col_max[green]+1)*NUM_FOG_LEVELS];
    fog_table[blue]=new unsigned[(col_max[blue]+1)*NUM_FOG_LEVELS];

    compute_light_table();
    compute_fog_table();
}

unsigned long canvas_imp_rgb::ext_to_native(unsigned red,
                                            unsigned green,
                                            unsigned blue) {
    unsigned long red_rescaled=red * col_max[this->red] / ext_max_red;
    unsigned long green_rescaled=green * col_max[this->green] / ext_max_green;
    unsigned long blue_rescaled=blue * col_max[this->blue] / ext_max_blue;

    return (red_rescaled << col_shift[this->red]) |
           (green_rescaled << col_shift[this->green]) |
           (blue_rescaled << col_shift[this->blue]);
}

void canvas_imp_rgb::light_native(unsigned long* col, unsigned intense) {
  unsigned char* c2=(unsigned char*)col;

  unsigned long color=0;
  unsigned long color_shift=0;

  for(register int p=0; p<bytes_per_rgb; p++) {
     color += (*c2++) << color_shift;
     color_shift += 8;  // 8=BITS_PER_BYTE
  }

  // mögliche restliche bytes zwischen bytes_per_rgb und
  // bytes_per_pixel überspringen (warum muss ich nochmal
  // rausfinden.
  for(register int p=bytes_per_rgb; p<bytes_per_pixel; p++)
     c2++;

  unsigned long r=(color&col_mask[red]) >> col_shift[red];
  unsigned long g=(color&col_mask[green]) >> col_shift[green];
  unsigned long b=(color&col_mask[blue]) >> col_shift[blue];

  color=(light_table[red][r*NUM_LIGHT_LEVELS+intense] << 
         col_shift[red]) |
        (light_table[green][g*NUM_LIGHT_LEVELS+intense] << 
         col_shift[green]) |
        (light_table[blue][b*NUM_LIGHT_LEVELS+intense] << 
         col_shift[blue]);

  {
     register int i;
     unsigned long mask = 255;
     char shift = 0;

     for(c2-=bytes_per_pixel, i=0; i<bytes_per_pixel; i++) {
        *c2 = (color & mask) >> shift;
        c2++;
        mask <<= 8;
        shift += 8;
     }
  }
}