[comp.graphics] VGA Colors

brown@m.cs.uiuc.edu (11/10/89)

Written  1:03 pm  Nov  8, 1989 by jrn@csd4.csd.uwm.edu in comp.graphics:
>I changed the color palette to
>all shades of grey.  What I got was 4 sections of colors where each section
>had the same colors as the all other sections.
>
>I did something like this
>      
>      for i:=0 to 255 do
>         SetRGBPalette(i,i,i,i);
>
>I would assume that I should have gotten 256 varying shades of grey.
>But I didn't.  I got 4 sections of 64 shades of grey,  were each section
>had the same 64 colors.

    The problem that you've run into is a limitation of the VGA hardware:
the VGA digital to analog converters are only six bit devices.  While you're
specifying the desired value as an eight bit quantity, only the top six bits
are used--the bottom two are ignored.  Because of this, there are only 64
distinct shades of red, 64 of blue, and 64 of green available (64*64*64 =
262144 or the total number of colors in the VGA palette).  

>How would I get 256 DIFFERENT shades of grey?

    With the VGA, I'm afraid that you can't.  


	William Brown
	brown@cs.uiuc.edu
	University of Illinois at Urbana-Champaign

kendalla@pooter.WV.TEK.COM (Kendall Auel;685-2425;61-028;;pooter) (11/10/89)

In article <824@uwm.edu> jrn@csd4.csd.uwm.edu (James Ray Norton) writes:
>
>I've got another question.
>
>I am using Turbo Pascal v5.0 and I did a test.  I changed the color palette to
>all shades of grey.  What I got was 4 sections of colors where each section
>had the same colors as the all other sections.
>

As mentioned earlier, the VGA has 6-bit DAC's so you cannot get 256
shades of gray from hardware.  But you can get 256 shades of gray by
using a simple 2x2 dither pattern, and I personally think the shading
looks BETTER with dithering than with 8-bit DAC's.  (When shading
a region).  For vector drawing, you are better staying away from
dithering and just using the 64 available shades.

Kendall Auel   kendalla@pooter.wv.tek.com

mcdonald@uxe.cso.uiuc.edu (11/10/89)

>>How would I get 256 DIFFERENT shades of grey?

>    With the VGA, I'm afraid that you can't.  

Not for the hardware hacker. In fact it is easy. First you
take a pair of scissors and cut your monitor cable in half ......

The rest is too long to post, but it can be done.

magore@watserv1.waterloo.edu (Mike Gore, Institute Computer Research - ICR) (11/11/89)

Hi,

In article <824@uwm.edu> jrn@csd4.csd.uwm.edu (James Ray Norton) writes:
[ re: VGA palette ]
>I've got another question.
...
>      for i:=0 to 255 do
>         SetRGBPalette(i,i,i,i);
>
>I would assume that I should have gotten 256 varying shades of grey.
>But I didn't.  I got 4 sections of 64 shades of grey,  were each section
>had the same 64 colors.
>
>How would I get 256 DIFFERENT shades of grey?

	Although the DACs on each of THE R B G channels are 6 bits you can 
fudge the palettes to get a better aproximation the 64 with just a bit of color
offset for some entries. 

	If you keep each of the 64 palette entries for R G & B within
+/-1 of each other and then consider the sum of R G & B as the actual output 
you can get 192 values out of 256. This works because near output values of 0
the colors resulting from the offsets are so dark as not to be very visible 
and for high values of output the color offset does not contribute much to the 
overall brightness.
	I have used this method with good results. For better results
one should adapt the palette for the monitor being used since each
channel of R G & B on most all monitors have slightly differing transfer 
functions for each channel anyway. In otherwords given a pure gray signal you
will still likely get slight changes of color in the "grey" with just changes 
in brightness alone - tweeking the palette can avoid most of this.

Good luck!,

# Mike Gore, Technical Support, Institute for Computer Research
# Internet: magore@watserv1.waterloo.edu   or   magore@watserv1.uwaterloo.ca
# UUCP:     uunet!watmath!watserv1!magore
# These ideas/concepts do *not* imply views held by the University of Waterloo.

mfinegan@uceng.UC.EDU (michael k finegan) (11/11/89)

For those who wanted a grey scale palette on the VGA - here is
a combination of C and assembler that loads a LUT into the VGA
(256 color) palette. I used MASM and MSC v. 5.1, but should
work, with minor changes, for turboc, etc.

The same ideas work for 'superVGA' - just change the set_size_color()
routine to select your favorite mode and resolution. You could try
loading a modified palette, as someone suggested, with colors that
were close to grey - the dark greys are very similar.

				Hope this is what you wanted ...
					Mike Finegan
					mfinegan@uceng.UC.EDU
------------------------ cut here for start of C file --------------------------
/* vgapals.c
 *
 * (c) 1989 Michael K. Finegan, Jr.
 *
 * Simplistic, and inefficient, way to display
 * unsigned char image on 320x200 vga display,
 * but illustrates use of LoadPals() with display
 * of centered 200 x 256 image - a grey scale ramp.
 *
 * assuming masm 'loadpals.asm;' was previously executed:
 * compiled using `cl /AL /c vgapals.c followed by
 *		  `link vgademo+loadpals;'
 *
 * for small model - change all "far" to "near" in loadpals.asm ...
 */
#include <stdio.h>
#include <conio.h>
#include <dos.h>
#include <io.h>

#define FALSE 0
#define TRUE 1
#define SAVE_LOAD 1
#define RESTORE 0


/* used by LoadPals */
extern unsigned char far NewLut[], far OldLut[];

main()
{
    int i, x, y;
    void LoadPals();	/* LoadPals is large model (far return) assembler */
    int  GetChar();	/* also far return assembler ... */
    void setvmode(), set_size_colors(), writepix();


   /* Load palette with reduced (64 level) gray scale (R = G = B).
    *
    * Only the 6 least signifigant bits of R,G,B bytes are
    * used for the output Look Up Table.
    *
    * NOTE: you could load your LUT (256*3 bytes), maybe
    * previously saved to file, into NewLut, instead ...
    */
    for(i=0;i<256;i++) {
	NewLut[3*i + 0] = (unsigned char)(i/4);	/* R */
	NewLut[3*i + 1] = (unsigned char)(i/4);	/* G */
	NewLut[3*i + 2] = (unsigned char)(i/4);	/* B */
    }

    setvmode(0x13);	/* 0x13 <==> 256 color 320 by 200 VGA */
    set_size_colors(320,200,256);
    LoadPals(SAVE_LOAD);

   /*
    * draw a grey scale 'ramp'
    *
    * "x + 32" shifts 256 column image to center of screen.
    */
    for(y=0;y<200;y++) {
         for(x=0;x<256;x++)
	     writepix(x + 32,y,(unsigned char)x);
    }
    
    GetChar();		/* i.e. wait for keystroke before quitting ... */
    
    LoadPals(RESTORE);
    setvmode(0x3);	/* 0x3 <==> text; should restore previous mode ... */
}


void set_size_colors(max_x,max_y,colors)
int max_x, max_y, colors;
{
    union REGS inregs, outregs;

    inregs.x.ax = 0x7e;
    inregs.x.bx = (unsigned)max_x;
    inregs.x.cx = (unsigned)max_y;
    inregs.x.dx = (unsigned)colors;
    int86(0x10,&inregs,&outregs);
}


void setvmode(mode)
int mode;
{
    union REGS inregs, outregs;

    inregs.h.ah = 0;
    inregs.h.al = mode;
    int86(0x10,&inregs,&outregs);
}


void writepix(x,y,value)
int x, y;
unsigned char value;
{
    union REGS inregs, outregs;

   /* simple video bios call, could write directly to memory ...
    *
    * image processing coordinate system - 0,0 @ upper left corner
    */
    inregs.h.al = value;
    inregs.h.ah = 0x0C;		/* write dot */
    inregs.h.bh = 0;		/* assume page 0 */
    inregs.x.cx = (unsigned)x;
    inregs.x.dx = (unsigned)y;
    int86(0x10,&inregs,&outregs);
}
------------------------ cut here for end of C file ----------------------------
------------------------ cut here for start of asm file ------------------------


	TITLE 'BIOS load of palette'
	NAME LoadPals
	PAGE 55,132

_DATA	SEGMENT
_NewLut	db	800	dup	(?)
_OldLut	db	800	dup	(?)
_DATA	ENDS
_BSS	SEGMENT
_BSS	ENDS
CONST	SEGMENT
CONST	ENDS

DGROUP GROUP CONST,_BSS,_DATA
_TEXT	SEGMENT	byte public 'CODE'
	ASSUME	cs:_TEXT,ds:DGROUP,es:DGROUP,ss:DGROUP

PUBLIC _NewLut, _OldLut

;	(c) 1989 Michael K. Finegan, Jr.
;
;	LoadPals      Load VGA 256 color palette
;
;	Call with AX = [3,2,1,0]	(for MSC, LoadPals(AX) )
;		Where:
;		      3 ==> Just Load pals
;		      1 ==> Save current pals, then Load new pals
;		      2 ==> Just Restore pals
;		      0 ==> Save current pals, then Restore old pals
;		Assume:
;		      NewLut filled with new LUT; OldLut holds saved LUT,
;		      depending on calling sequence.
;
;	LoadPals(1) followed by LoadPals(2) leaves palette unchanged ...
;
	PUBLIC	_LoadPals
_LoadPals	PROC	far
        test ax,1
	jz restore
        cmp ax,3
	je load
	mov ah,10h	; set palette reg.s/intensity/blink function
	mov al,17h	; read a block of DAC color registers
	mov bx,0	; start with register 0
	mov cx,100h	; and read all 256
	push es
	mov dx, seg _OldLut
	mov es,dx
	mov dx, offset _OldLut
	push bp		; int 10h can modify
	int 10h		; assume same data segment
	pop bp
	pop es

load:
	mov ah,10h	; set palette reg.s/intensity/blink function
	mov al,12h	; update a block of DAC color registers
	mov bx,0	; start with register 0
	mov cx,100h	; and change all 256
	push es
	mov dx, seg _NewLut
	mov es,dx
	mov dx, offset _NewLut
	push bp		; int 10h can modify
	int 10h		; assume same data segment
	pop bp
	pop es
	jmp finished
restore:
; *** check values written to registers to debug ***
        cmp ax,2
	je just_restore
	mov ah,10h	; set palette reg.s/intensity/blink function
	mov al,17h	; read a block of DAC color registers
	mov bx,0	; start with register 0
	mov cx,100h	; and read all 256
	push es
	mov dx, seg _NewLut
	mov es,dx
	mov dx, offset _NewLut
	push bp		; int 10h can modify
	int 10h		; assume same data segment
	pop bp
	pop es

just_restore:
	; restore the pal values read into _Outputlist by a previous
	; call to _LoadPals(RESTORE)
	mov ah,10h	; set palette reg.s/intensity/blink function
	mov al,12h	; update a block of DAC color registers
	mov bx,0	; start with register 0
	mov cx,100h	; and change all 256
	push es
	mov dx, seg _OldLut
	mov es,dx
	mov dx, offset _OldLut
	push bp		; int 10h can modify
	int 10h		; assume same data segment
	pop bp
	pop es

finished:
	ret

_LoadPals	ENDP

; GetChar reads char from keyboard, with no Cntrl-Brk
; check, no echo, and the <scan code,char> returned in <ah,al>.
	PUBLIC	_GetChar
_GetChar		PROC	far
		mov ah,0
		INT 16h
		ret

_GetChar		ENDP

_TEXT		ENDS

		END
------------------------ cut here for end of asm file --------------------------

mjb@nucleus.UUCP (Mark Bobak) (11/11/89)

In article <824@uwm.edu> jrn@csd4.csd.uwm.edu (James Ray Norton) writes:
>
>I am using Turbo Pascal v5.0 and I did a test.  I changed the color palette to
>all shades of grey.  What I got was 4 sections of colors where each section
>had the same colors as the all other sections.
> (Text deleted...)
>How would I get 256 DIFFERENT shades of grey?


To the best of my knowledge, the VGA will support only 64 shades of grey.




-- 
Mark Bobak
The Nucleus Public Access Unix, Clarkston, Mi.
mjb@nucleus.mi.org
mjb@m-net.ann-arbor.mi.us

U5569462@ucsvc.ucs.unimelb.edu.au (DAVID CLUNIE) (11/12/89)

> I would assume that I should have gotten 256 varying shades of grey.
> But I didn't.  I got 4 sections of 64 shades of grey,  were each section
> had the same 64 colors.
> 
> How would I get 256 DIFFERENT shades of grey?

As others have already pointed out you can't because of the 6 bit DAC's in the
vga. Interestingly, someone mailed me a palette that aims to simulate more than 
64 shades of grey by using colors very close to grey. I have tried it and
really can't perceive the difference between it and just using a 6 bit grey
scale.

Which brings me to the point that I have read somewhere recently (can't
remember where) that the human eye CAN'T distinguish any more than 64 different
shades of grey. Is this so ? Do people beleive it ?

Regards ... David

nn86302@tut.fi (Neuvo Niilo Anselmi) (11/14/89)

In article <391@ucsvc.ucs.unimelb.edu.au> U5569462@ucsvc.ucs.unimelb.edu.au (DAVID CLUNIE) writes:
>
>Which brings me to the point that I have read somewhere recently (can't
>remember where) that the human eye CAN'T distinguish any more than 64 different
>shades of grey. Is this so ? Do people beleive it ?
>

	Nope. Nope. I'm not 100% certain about grey scales, but with other
	colors I can see the difference. Try drawing two squares (on
	a VGA(Ah forbidden word)) which are colored with two different
	colors very close(like colors (50,0,0) and (49,0,0)) to each
	other and you should be able to see a 'line' in the junction
	of the boxes.

-- 
      NN   NN  NN   NN  NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
    NNNN    N  NN    N  NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
  NNNNNN  N    NN  N    NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
NNNNNNNN  NN   NN  NN   NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN

myers@hpfcdj.HP.COM (Bob Myers) (11/15/89)

>Which brings me to the point that I have read somewhere recently (can't
>remember where) that the human eye CAN'T distinguish any more than 64 different
>shades of grey. Is this so ? Do people beleive it ?

As a first approximation, this probably isn't too far off for most people,
at least within the confines of the average-sized computer display.  One
factor which affects the discrimination of the gray levels or colors is the
area involved; for example, the human eye has much poorer spatial resolution
for color than for monochrome images, meaning that you will be unable to
distinguish very small areas which are of different colors but similar in
apparent brightness.  On the other hand, those same details will be apparent
if they are rendered as differring in brightness.  This fact is used in the
NTSC color encoding process (and others), in which the color bandwidth is
purposely limited relative to the luminance bandwidth.


Bob Myers  KC0EW   HP Graphics Tech. Div.|  Opinions expressed here are not
                   Ft. Collins, Colorado |  those of my employer or any other
myers%hpfcla@hplabs.hp.com               |  sentient life-form on this planet.

brian@hpfcdj.HP.COM (Brian Rauchfuss) (11/15/89)

/ hpfcdj:comp.graphics / U5569462@ucsvc.ucs.unimelb.edu.au (DAVID CLUNIE) /  4:27 pm  Nov 11, 1989 /
>Which brings me to the point that I have read somewhere recently (can't
>remember where) that the human eye CAN'T distinguish any more than 64 different
>shades of grey. Is this so ? Do people beleive it ?
>
>Regards ... David
>----------

Everyone around here can distinquish 256 shades of gray, but a dark room is
required.  64 shades are very easy to distinquish.

Brian Rauchfuss

fleming@balboa (Dennis Paul Fleming) (11/23/89)

In article <17400014@hpfcdj.HP.COM> brian@hpfcdj.HP.COM (Brian Rauchfuss) writes:
>
>Everyone around here can distinquish 256 shades of gray, but a dark room is
>required.  64 shades are very easy to distinquish.
>
>Brian Rauchfuss

Your ability to distinguish probably depends on two gray levels being
neighbors.  If they are seperated then one's ability is curtailed.
There are two experements which point this out:
	1) Grossberg in his book on Neural Nets looks at an image 
	with the folowing greylevel pattern:

                           |\
                           | \
                           |  \
------------------------\  |   \-----------------------
                         \ |
                          \|
                           \

	The resulting perception is that the 2 grey patches on either
	side of the dicontinuity appear to be different grey levels.

	2) McCann and Land in their paper on the Retinex theory
	Journal of Optical Scientist (?) had an experiment where
	light was cast onto a sheet of paper with two areas of
	different reflectance.  The energy comming off of the paper
	was as follows:

                                      _____________________________
         \       |\                   |             |             |
          \      | \                  |             |             |
           \     |  \              /  |             |             |
            \    |   \            )-  |             |             |
             \   |    \            \  |     40%     |    80%      |
              \  |     \              | reflectance | reflectance |
               \ |      \             |             |             |
                \|       \            |___________________________|
	

	The result of this experiment was that when a pencil or
	other obstruction was places at the dicontinuity both
	grey areas appeared the same value.  because of the position
	of the light and the relative values the total energy
	coming from each grea patch was the same, and so percieved
	as such.

Dennis Fleming
Dept of Electrical and Computer Engineering
University of California, Irvine