Hi Richard,
Oops, I got a message saying
that email was too big.
Yes I remember the old
true colour mode and it was not much use as it only gave shades of blue as
no translation was done to the iteration count. My true colour algorithm creates
3 sinusoidal values for each of the red, green and blue colour streams and makes
a true colour palette. All that is required is the starting point in each
sine wave and the frequency. I.e., 6 integers specify the true colour palette.
These are spread out according to the max iteration count. The only problem is
that it is not reversible like the 256 colour map, so a separate matrix of 16
bit integers needs to be kept for the solid guessing etc to work.
Image deleted to
reduce file size
This was the colour
control dialogue box.
Here is how the palette is
generated:
WORD RedStartInt, GreenStartInt,
BlueStartInt, RedIncInt, GreenIncInt, BlueIncInt;
BYTE TRUE_PALETTE[MAXTHRESHOLD *
3]; // for maximum palette
/**************************************************************************
Initialise
True Colour
Palette
**************************************************************************/
void InitTrueColourPalette(BYTE RandFlag)
{
long i, cycle,
temp;
DOUBLE RedStart, GreenStart, BlueStart, RedInc, GreenInc,
BlueInc;
float size;
static WORD Randomise;
if
(RandFlag)
{
srand((unsigned)time(NULL) + Randomise);// Seed the random-number generator with
current time so
// that the
numbers will be different every time we run.
if
(RandomColourFlag)
{
RedIncInt
= rand() /
RandomDivisor;
GreenIncInt
= rand() /
RandomDivisor;
BlueIncInt
= rand() /
RandomDivisor;
RedStartInt
= rand() /
RandomDivisor;
GreenStartInt
= rand() /
RandomDivisor;
BlueStartInt
= rand() /
RandomDivisor;
}
Randomise =
rand(); // to prevent the same value within the
second!!
}
RedStart = (float)(RedStartInt)
/ 100.0;
GreenStart = (float)(GreenStartInt) / 100.0;
BlueStart =
(float)(BlueStartInt) / 100.0;
RedInc = (float)(RedIncInt) /
100.0;
GreenInc = (float)(GreenIncInt) / 100.0;
BlueInc =
(float)(BlueIncInt) / 100.0;
temp = ((long)
StartColourCycling > threshold) ? threshold : StartColourCycling;
for (i =
1L; i < threshold; ++i)
{
cycle =
temp + i;
if (cycle >
threshold)
cycle
-= threshold;
size = (float) cycle / (float) ((logval !=
0) ? 256 : threshold);
TRUE_PALETTE[i * 3 + 0] = (BYTE)(127.0 *
sin(TWO_PI * (size + RedStart) * RedInc)) + 128;
TRUE_PALETTE[i * 3 + 1] = (BYTE)(127.0 * sin(TWO_PI * (size + GreenStart) *
GreenInc)) + 128;
TRUE_PALETTE[i * 3 + 2] = (BYTE)(127.0 *
sin(TWO_PI * (size + BlueStart) * BlueInc)) + 128;
}
*(TRUE_PALETTE + threshold * 3
+ 0) = (BYTE)InsideBlue;
*(TRUE_PALETTE + threshold * 3 + 1) =
(BYTE)InsideGreen;
*(TRUE_PALETTE + threshold * 3 + 2) =
(BYTE)InsideRed;
}
Here is the basic plotting routine
(cut down for simplicity):
Note that BYTE *pixels is the
array of rgb triplets for the image to screen and WORD *wpixels is the array of
iteration counts (16 bit)
/**************************************************************************
Get
values of r, g,
b
**************************************************************************/
BYTE *GetRGB(DWORD
colour)
{
DWORD j;
static BYTE rgb[3];
j = (TrueColourFlag) ? colour +
colour + colour : (DWORD)((colour % 256L) * 3L);
*(rgb + 0) = *(PalettePtr +
j + 2);
*(rgb + 1) = *(PalettePtr + j + 1);
*(rgb + 2) = *(PalettePtr + j
+ 0);
return (rgb);
}
/**************************************************************************
Plot
correct pixel according to count, i,
j
**************************************************************************/
void outpoint(WORD x, WORD y,
DWORD colour)
{
long i;
long local_width;
if (colour >
(DWORD)threshold) // don't write past end of
palette
{
if
(TrueColourFlag)
colour = (DWORD)threshold;
else
if (colour >= 255L)
colour = 255L;
}
// first do screen
if (x < 0 || x >= width || y < 0 || y >=
height)
return;
local_width = WIDTHBYTES((DWORD)width *
(DWORD)bits_per_pixel);
i = ((long) (height - 1 - y) * (long) (local_width +
3 - ((local_width - 1) % 4)) + (long)(x * 3));
if (colour ==
(DWORD)threshold) // handle inside colour
{
*(pixels + i + 0) =
(BYTE)InsideBlue;
*(pixels + i + 1) =
(BYTE)InsideGreen;
*(pixels + i + 2) =
(BYTE)InsideRed;
}
// memcpy(pixels +
i, VGA_PALETTE + inside_colour * 3, 3);
else
memcpy(pixels + i, GetRGB(colour), 3);
//
Now do reference
i = ((long) (height - 2 - y) * (long) (width + 3 - ((width -
1) % 4))) + (long) x;
if (x >= 0 && x < xdots - 1 && y
>= 0 && y < ydots - 1)
*(wpixels + i) =
(WORD) colour;
}
/**************************************************************************
Read
pixel
colour
**************************************************************************/
DWORD ingetcolor(WORD x, WORD
y)
{
long i;
long local_width;
if (x < 0 || x >= width || y < 0 || y >=
height)
return 0L;
local_width =
WIDTHBYTES((DWORD)width * (DWORD)bits_per_pixel);
i = ((long) (height - 1 -
y) * (long) (local_width + 3 - ((local_width - 1) % 4)) + (long)(x * 3));i =
((long) (ydots - 2 - y) * (long) (xdots + 3 - ((xdots - 1) % 4))) + (long)
x;
if (x >= 0 && x < xdots
&& y >= 0 && y < ydots - 1)
return ((DWORD)((*(wpixels + i)) &
0xffff));
else
return 0L;
}
Let me know what you think
:)
Seeya,