[comp.graphics] Displaying 256 color GIFs on 16 color device

sminkin@bbn.com (Scott Minkin) (12/08/89)

Greetings,

I've recently written a program to display GIF files on DEC VT340
terminals using color sixel.  The 16 color GIF files come out beutifully,
but I don't really have a scheme for converting 256 colors down to
16 (which is the limitation of the VT340).  Is there a preferred 
algorithm for doing this?  Averaging RGB values? Picking the 16 most
commonly used colors and trying to map the remaining colors to them?  

I've seen the source code to some other GIF decoders which handle the stripping
of color bits, but that seems to deal with devices with a limited resolution
for each color, rather than a limited number of colors.

Of course, the possibility that I'm misunderstanding this issue is also
a distinct possibility.

Any friendly advice would be greatly appreciated.

Thanks.
Scott
sminkin@bbn.com

aceman@walt.cc.utexas.edu (acy james stapp) (12/08/89)

In article <49396@bbn.COM> sminkin@BBN.COM () writes:
>I've recently written a program to display GIF files on DEC VT340
>terminals using color sixel.  The 16 color GIF files come out beutifully,
>but I don't really have a scheme for converting 256 colors down to
>16 (which is the limitation of the VT340).  Is there a preferred 

Try this algorithm:
read row(0)
convert row(0) to array[length+1] of signed int; (or less, this is what I use)
until eof() do
    read row(1) from file
    convert row(1) to array of int
    for every element of row(0) do
        newrow(element)=newrow(element)+(red>>7)>>3
        row(0)(element+1)(red)=(red+1)>>1
        row(1)(element)(red)=red>>1
        newrow(element)=newrow(element)+(green>>6)<<1
        row(0)(element+1)(green)=(green+1)>>1
        row(1)(element)(green)=green>>1
        newrow(element)=newrow(element)+(blue>>7)
        row(0)(element+1)(blue)=(blue+1)>>1
        row(1)(element)(blue)=blue>>1
    enddo
    write row(0) to file
    row(0)=row(1) /* HaHaHa to all you C programmers! Try doing this with
                     one statement! */
enddo
>> means shift into nothingness, << means shift into overflowingness

use the following color map to display your final thingythingy
Val	R	G	B
0	0	0	0
1	0	0	255
2	0	85	0
3	0	85	255
4	0	170	0
5	0	170	255
6	0	255	0
7	0	255	255
8-15	255	as above-8

email me for an explanation if you're too stupid to figure it out yourself.

<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>
<*>Acy Stapp   email: aceman@walt.cc.utexas.edu   `NO SMOKING IN CORRIDORS' <*>
<*>"Learn to love your anger now, anger here is all you posess" Duran Duran <*>
<*>Disclaimer: The opinions presented above are true and correct, and if *>*<*>
<*>*<anyone disagrees with them, then that's their problem. <*>*<*>*<*>*<*>*<*>
<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>

aceman@walt.cc.utexas.edu (acy james stapp) (12/09/89)

In article <22099@ut-emx.UUCP> I write:
>In article <49396@bbn.COM> sminkin@BBN.COM () writes:
>>I've recently written a program to display GIF files on DEC VT340
>>terminals using color sixel.  The 16 color GIF files come out beutifully,
>>but I don't really have a scheme for converting 256 colors down to
>>16 (which is the limitation of the VT340).  Is there a preferred 
>
>Try this algorithm:
>   [ awesome but non-functional algorithm deleted ]
I committed a gross stupidity.  Forgive me, It was late at night and I 
probably cost USENET hundreds if not thousands of dollars.  The correct
algorithm follows: (if you're interested)

row:[2][width+1][3] integer
output:[width] char
red:constant integer=0
green:contant integer=1
blue:constant integer=2
temp:integer
colmap:[16][3] char=((0,0,0),(0,0,255),(0,85,0),(0,85,255),/
                     (0,170,0),(0,170,255),(0,255,0),(0,255,255),/
		     (255,0,0),(255,0,255),(255,85,0),(255,85,255),/
                     (255,170,0),(255,170,255),(255,255,0),(255,255,255))
x:range integer=(0,width-1,1)
tempp:^[]
fixem:[3][2] integer=((128,32),(192,64),(128,128))
read first row from file into row[0][0..width-1][R..B] /* 0..255 Intensity */
while not eof(), do {
	read next row from file into row[1][0..width-1][R..B]
	instance x, do {
		color:range integer=(r,b,1)
		instance color, do {
			temp=row[0][x][color]
			output[x]=(temp .and fixem[color][0])/fixem[color][1]
			temp=temp-colmap[output[x]][color]
			row[0][x+1][color] += (temp+1)/2
        	        row[1][x][color] += temp/2
		}
	}
	write output[0..length] to your output file
	tempp=&row[0]
	&row[0]=&row[1]
	&row[1]=&row[0]
}
/* this is in DRIZZLE, a language I am developing.  It should be fairly self-
explanatory and easy to read.  I hope so.  I just noticed that I forgot to put
statement separators.  Damn.  I welcome any comments on the style of the
language.  I developed this algorithm myself, but I think it's already been 
done by someone else.  Notes: .<boolean op> makes it bitwise, otherwise it's
logical.  range is a type (min,max,delta).  instancing a range evaluates
the do succesively with the variable evaluating as the range supertype.  e.g.
x:range(1,10,1); instance x, do write(_<x,2>_); would write  1 2 3 4 5 6 7 8
 910.  I hope it makes sense to you.  I like it.*/

/* p.s. The color mapping table is now defined in the program.  Values in each
triplet are Red, Green, and Blue succesively, ranging from 0..255.  This
program attempts to keep the average color intensities correct by propogating
the differences between displayed and actual value down and to the right.
One possible Change is to change the percentage of propogation right, down,
and down&right depending on the original color.  This will give you different
patterns for colors with the same brightness.  I gave green two bits since
it is about twice as bright as red, the delta(brightness) should be fairly
consistent. */

<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>
<*>Acy Stapp   email: aceman@walt.cc.utexas.edu   `NO SMOKING IN CORRIDORS' <*>
<*>"Learn to love your anger now, anger here is all you posess" Duran Duran <*>
<*>Disclaimer: The opinions presented above are true and correct, and if *>*<*>
<*>*<anyone disagrees with them, then that's their problem. <*>*<*>*<*>*<*>*<*>
<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>*<*>