www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1998/03/10/03:00:22

From: qballlives AT aol DOT com (QBallLives)
Newsgroups: comp.os.msdos.djgpp
Subject: Re: Multi palettes in Alegro
Date: 10 Mar 1998 07:45:20 GMT
Lines: 261
Message-ID: <19980310074501.CAA24171@ladder02.news.aol.com>
NNTP-Posting-Host: ladder02.news.aol.com
Organization: AOL http://www.aol.com
References: <199803092349 DOT PAA11509 AT adit DOT ap DOT net>
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp

>At 08:30  3/8/1998 GMT, John & Sue Kissell wrote:
>>    Using a 256 color palette, is it possible to simultaneously use
>>different palettes in different parts of the screen in Allegro without
>>the flicker produced by set_palette()? I tried a hack using memcpy with
>>a temporary palette, but I'm beginning to think that the way a vidieo
>>monitor works makes this unlikely, if not impossible, without some sort
>>of interrupt routine. Any comments?
>
>I'm fairly sure you can only have one palette at a time with standard VGA
>hardware. To eliminate the flicker, aren't you supposed to use `vsync'?
>
>

vsync will definitely help with the snow that comes from with modifying the
palette - but I just learned something that might help Sue out a bit...

A friend of mine showed me how to make a "Clut" palette, which I use to
"simulate" more colors than are actually available to use...

It's opened alot of doors for me, so I hope it opens doors for you as well..
I'll describe it and give code.

There are probably several algorithms that come up with a better choice of
colors than this.

What you do is, you've got your 256 color palette - let's say you want 16
"shades" of those 256 colors

int color_table[256][16];  // <= the declaration

Make an outer loop where you'll extract the RED, GREEN, and BLUE values from
your current palette.

       I'd suggest extracting those values into floating point variables... but
you can get weird sorts of effects using ints too (experiment)

       Double those values (or triple them, whatever) 

       Calculate the change in intensity of each color by dividing the new
values by the # of steps you want to take

  ex:    ri = red/16.0;
           gi = blue/16.0;
           bi = blue/16.0;

      The way this is setup... the lowest intensitys of all colors will be
black (or close to black)

      Now, for an inner loop (yes, there's ANOTHER inner loop too - you should
save your clut palette to disk - especially when you want to simulate ALOT of
shades!)

      In this inner loop, you'll loop from 15 to 0 (start with the highest
intensity) - extract your floating point RED, GREEN, and BLUE values into ints
- and check they're range (between 0 and 63 each)

   ... You're ready for the innermost loop now:

     Loop through all 256 colors in the palette, and, using a calculation a
friend gave to me, select the "best fit" color to the color you'd like to have.

     Here's the code:

// Here is where we make our enhanced palette...

// The limitation in mode13h is having 256 simultaneous colors, and what
// making a "clut" palette (which is what the following routine does), is
// to try to simulate more colors

void Make_Bigger_Palette(void)
{
     rgb_palette a_palette;

     int index1, index2;
     float red, green, blue;
     int send_red, send_green, send_blue;

     float ri, gi, bi;         // increments for colors

     // first, since I don't have a full palette struct floating around
     // in memory, I'll load this one with the current palette

     for (index1=0; index1<256; index1++)
         Get_Palette_Register(index1,
(rgb_color_ptr)&a_palette.colors[index1]);

     Print_String_Mode_Y(10,10,170,"examining current palette",0);

     // loop through all colors

     for (index1=0; index1<256; index1++)
     {
         // extract red, green, and blue factors...

         red=(float)a_palette.colors[index1].red;
         green=(float)a_palette.colors[index1].green;
         blue=(float)a_palette.colors[index1].blue;

         // double the intensities

         red*=2;
         green*=2;
         blue*=2;

         // get the change in red, green, and blue
        // making the 16.0  into 32.0 should make the lowest
        // intensity color the color you started with...

         ri=red/16.0;
         gi=green/16.0;
         bi=blue/16.0;

         // loop through shades we'd like to have
         // we'll start with the 16th position of the table being
         // the highest intensity

         for(index2=15;index2>=0;index2--)
         {
             send_red = red;
             send_green = green;
             send_blue = blue;

             // since 63 would be the maximum if we were
             // talking the actual color palette... we're just testing
             // boundaries here

             if (send_red>63) send_red = 63;
             if (send_green>63) send_green = 63;
             if (send_blue>63) send_blue = 63;

             // call another function to get the color that best fits
             // a shade we would like

             color_table[index1][index2]=Get_Best_Fit_Color(send_red,send_
green,send_blue,(rgb_palette_ptr)&a_palette);

             // decrement red, green, and blue factors

             red-=ri;
             green-=gi;
             blue-=bi;
         }
    }

    // Save the Bigger Palette to the disk so we don't have to wait
    // for the table to be created next time

    Save_Bigger_Palette();
} // end Make_Bigger_Palette

int Get_Best_Fit_Color(int redy, int greeny, int bluey, rgb_palette_ptr pal)
{
    int i;
    int red_dist, green_dist, blue_dist;
    int dist_new, dist_best,color_best;
    int r, g, b;
    char ch_buffer[80];

    dist_best = 63;

    // loop through all colors... ::sigh:: again...

    for(i=0;i<256;i++)
    {
        // get the current rgbs for a color

        r = pal->colors[i].red;
        g = pal->colors[i].green;
        b = pal->colors[i].blue;

        // these "distances" will be used to determine what color
        // would be the best match, in lieu of the color we'd really
        // like to have

        red_dist=redy-r;
        green_dist=greeny-g;
        blue_dist=bluey-b;

        // squaring and adding it all together countermands any
        // negative signs we might have run into... hopefully
        // the current palette contains a color that's pretty close...

        dist_new=red_dist*red_dist+green_dist*green_dist+blue_dist*blue_dist;

        // is it close?

        if(dist_new<=dist_best)
        {
            sprintf(ch_buffer,"making progress...");
            Print_String_Mode_Y(10,20,rand()%255,ch_buffer,0);

            color_best=i;

            dist_best=dist_new;

        }
    }

    // send the closest color back to the calling procedure

    return(color_best);

} // end Get_Best_Fit_Color

Never mind the Print_String_Mode_Y, that's just a routine I made... It's good
to know the thing is working (not locked up), so that's why I use it ; )

Here's a routine to show that new bigger palette:

void Show_Bigger_Palette(void)
{
     // this routine shows the real palette on a single line,
     // and then shows our enhanced palette

     int index1,index2,offset;

     Print_String_Mode_Y(10,50,170,"Special thanks to Dhonn Lushine",0);
     Print_String_Mode_Y(10,60,170,"(dhonn AT usa DOT net) for his help...",0);

     Print_String_Mode_Y(10,80,170,"original palette",0);

     for (index1=0; index1<256; index1++)
     {
         outportb(SEQUENCER, SEQ_PLANE_ENABLE);
         outportb(SEQUENCER+1, (0x01<<(index1 & 0x03) ) );

         video_buffer[(100<<6) + (100<<4) + (index1>>2)] = (unsigned
char)index1;
     }
     Print_String_Mode_Y(10,110,170,"bigger palette",0);

     for (index1=0; index1<256; index1++)
     {
         outportb(SEQUENCER, SEQ_PLANE_ENABLE);
         outportb(SEQUENCER+1, (0x01<<(index1 & 0x03) ) );

         video_buffer[(100<<6) + (100<<4) + (index1>>2)] = (unsigned
char)index1;

         for (index2=0; index2<16; index2++)
         {
              offset = index2 + 130;

              video_buffer[(offset<<6) + (offset<<4) + (index1>>2)] =
                                 (unsigned char)color_table[index1][index2];
         }
     }
} // end Show_Bigger_Palette

I hope this helps you...

It opens the door to textured polys (w/ flat shading!), more "colors" for fake
phong effects, gouraud... this is good!

Have a good one!


Jim the loiterer
aloiterer AT juno DOT com
http://www.fortunecity.com/skyscraper/gigahertz/179/index.html

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019