Xojo Conferences
MBSSep2018MunichDE
XDCMay2019MiamiUSA

[MBS] gamma fade problem (MBS Xojo Plugin Mailinglist archive)

Back to the thread list
Previous thread: [MBS] Window Placement Bug
Next thread: [MBS] HTML encoding example


Re: [MBS] HTML encoding example   -   Christian Schmitz
  [MBS] gamma fade problem   -   Mike D.
   Re: [MBS] gamma fade problem   -   Christian Schmitz
    Re: [MBS] gamma fade problem   -   Mike D.
     Re: [MBS] gamma fade problem   -   Christian Schmitz
      Re: [MBS] gamma fade problem   -   Mike D.
       Re: [MBS] gamma fade problem   -   Christian Schmitz
        Re: [MBS] gamma fade problem   -   Mike D.
         Re: [MBS] gamma fade problem   -   Christian Schmitz

[MBS] gamma fade problem
Date: 25.01.03 23:18 (Sat, 25 Jan 2003 14:18:37 -0800)
From: Mike D.
I just tried the gamma fade code on my mom's sony vaio laptop running
XP, and it also shows the 50% problem (won't go darker than 50%).

I'm thinking the problem must lie in Windows XP (since my two XP
machines fail, but it works fine under Win 98)

Re: [MBS] gamma fade problem
Date: 27.01.03 01:34 (Mon, 27 Jan 2003 01:34:56 +0100)
From: Christian Schmitz
> I just tried the gamma fade code on my mom's sony vaio laptop running
> XP, and it also shows the 50% problem (won't go darker than 50%).
>
> I'm thinking the problem must lie in Windows XP (since my two XP
> machines fail, but it works fine under Win 98)

Some notes for SetDeviceGammaRamp, which is the Windows function used by
the plugin:

"SetDeviceGammaRamp doesn't allow all gamma ramps. It checks the gamma
ramp; if it is too complex, such as the red flash when the player is
shot in Quake, it rejects it.
SetDeviceGammaRamp will not currently make use of a gamma calibrator.
This may change in future versions of Image Color Management (ICM), but
for Windows 2000, only the DirectDraw API supports the gamma
calibrators.
The existing gamma entry points is already used by GetDeviceGammaRamp
and SetDeviceGammaRamp. Therefore, the display driver doesn't need to do
anything special to support this new interface, as long as it already
supports the Win32 Get/SetDeviceGammaRamp functions.
In addition to getting and setting gamma ramps, the new DirectDraw
interface allows the new gamma ramp to be calibrated-if a gamma
calibrator is installed. The mechanism that DirectDraw uses to register
and communicate with the gamma calibrator is an interim mechanism that
will be changed in future releases.
DirectDraw looks for an installed software calibrator and passes the
gamma value to the software calibrator; the software calibrator in turn
adjusts the gamma ramp according to the measured response of the
monitor. The calibrator passes the gamma ramp back to DirectDraw, which
passes it to the SetDeviceGammaRamp device driver interface (DDI). The
result is that the game looks as intended.
For DirectDraw to use the gamma calibrator, the calibrator must register
itself with DirectDraw using a registry key; DirectDraw will call it if
the application wants the gamma ramp to be calibrated.
In the future, both the method by which DirectDraw communicates with the
gamma calibrator, through the DDI, and the method gamma calibrators use
to register themselves in the registry will change. But every part of
the DirectDraw API is permanent.
ICM is the color management system in Windows; all system-level color
management should be handled by ICM. For this reason, downloadable gamma
ramp support will be rolled into ICM in the future, making current
solutions for gamma calibrators obsolete. Until such time, we have
provided a method by which applications can take advantage of the
installed base of software calibrators and graphics adapters that
support downloadable gamma ramps."

I add this text to the help. So for Windows XP it seems you have to life
with this fact...

Mfg
Christian

Re: [MBS] gamma fade problem
Date: 27.01.03 02:27 (Sun, 26 Jan 2003 17:27:28 -0800)
From: Mike D.
> > I just tried the gamma fade code on my mom's sony vaio laptop running
>> XP, and it also shows the 50% problem (won't go darker than 50%).
>>
>> I'm thinking the problem must lie in Windows XP (since my two XP
>> machines fail, but it works fine under Win 98)
>
>Some notes for SetDeviceGammaRamp, which is the Windows function used by
>the plugin:
>
>[...]
>I add this text to the help. So for Windows XP it seems you have to life
>with this fact...
>
>Mfg
>Christian

Strange. I'm still not convinced that we shouldn't be able to do a
full gamma fade under windows XP. The fact that we can get from 100%
to 50% just fine, but not below 50%, still seems to me like it must
be a sign/unsigned integer bug.

Would you be willing to post the source code, either on or off this
list? Maybe we can help debug it? I'm not a bad C-programmer (but
too lazy, which is why I use RB :-)

Here's some more info I found that could help...
The first is in German :-) so I don't know if it is helpful...

from http://www.metz-furniere.de/jens/vbsource.html

Die Helligkeit kann mit ein paar Zeilen geändert werden:
In den Deklarationen der Form:
Private Ramp1(0 To 255, 0 To 2) As Integer
Private Ramp2(0 To 255, 0 To 2) As Integer
Private Declare Function GetDeviceGammaRamp Lib "gdi32" (ByVal hdc As
Long, lpv As Any) As Long
Private Declare Function SetDeviceGammaRamp Lib "gdi32" (ByVal hdc As
Long, lpv As Any) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory"
(Destination As Any, Source As Any, ByVal Length As Long)

Public Function Int2Lng(IntVal As Integer) As Long
CopyMemory Int2Lng, IntVal, 2
End Function
Public Function Lng2Int(Value As Long) As Integer
CopyMemory Lng2Int, Value, 2
End Function
Private Sub Form_Unload(Cancel As Integer)
SetDeviceGammaRamp Me.hdc, Ramp1(0, 0) 'Beim Beenden wieder
normale Helligkeit
End Sub
Dort, wo es dunkel werden soll:
Dim iCtr As Integer
Dim lVal As Long
GetDeviceGammaRamp Me.hdc, Ramp1(0, 0)
For iCtr = 0 To 255
lVal = Int2Lng(Ramp1(iCtr, 0))
Ramp2(iCtr, 0) = Lng2Int(Int2Lng(Ramp1(iCtr, 0)) / 2)
Ramp2(iCtr, 1) = Lng2Int(Int2Lng(Ramp1(iCtr, 1)) / 2)
Ramp2(iCtr, 2) = Lng2Int(Int2Lng(Ramp1(iCtr, 2)) / 2)
Next iCtr
SetDeviceGammaRamp Me.hdc, Ramp2(0, 0)
Sie können auch die Farbe verändern wenn sie die entsprechenden
Zeilen auskommentieren.



from http://apollo.iwt.uni-bielefeld.de/~ml_robot/OpenGL-04-2000/0058.html

I finally figured out gamma correction for Win32, so I thought
I should write a brief description for any who may be interested. I
wanted to represent gamma correction to the user as three floating
point component values for red, green, and blue gamma correction. I
also wanted to allow the user to get and set the current gamma
component values.

As you may already know, the gamma ramps are essentially a
curve from 0.0 to 1.0 for each color component, mapping the
specified color value to the actual color value displayed on the
monitor. The actual color value is determined according to the
following formula:

A = B^C

where:
A is the actual color value,
B is the specified color value, and
C is the component value

The default component value of 1.0 yeilds an exact match between
specified and actual color values. For a given color, higher
component values decrease intensity of mid range values, and lower
component values increase the intensity. The ends of the curve are
always fixed at 0 and 1.

The actual representation of the gamma ramps under Win32 is
an array of WORD[3 * 256]. This single array represents all three
gamma ramps in sequence, respectively red, green, and blue.
According to MSDN:

"The gamma ramp is specified in three arrays of 256
WORD elements each, which contain the mapping between
RGB values in the frame buffer and digital-analog-
converter (DAC) values."

Values in the array range from 0 to 65536. Obviously some
logical conversion is necessary. The appropriate values for the red
gamma ramp can be set as follows:

WORD* ramp = new WORD[256 * 3];
for (int i = 0; i < 255; i++)
ramp[i] = pow((i / 256.0), redGamma) * 65536;

Where redGamma is a floating point value >= 0.0. The final code for
SetGamma() is:
____________________________________________________________

typedef RGB float[3];

bool SetGamma(RGB rgb)
// Accept: rgb - component gamma values >= 0.0
// Return: true if successful, false otherwise
{
WORD *ramp = new WORD[256 * 3];
for (int i = 0; i < 3; i++)
{
int min = 256 * i;
int max = min + 256;
for (int j = min; j < max; j++)
ramp[j] = pow(((j % 256) / 256.0), rgb[i]) * 65536;
}
if (SetDeviceGammaRamp(GetDC(NULL), ramp)) return true;
else return false;
}

RGB GdkVideo::GetGamma()
{
WORD *ramp = new WORD[256 * 3];
GetDeviceGammaRamp(GetDC(NULL), ramp);
RGB rgb = {1.0,1.0,1.0};
for (int i = 0; i < 3; i++)
{
float Csum = 0.0;
int Ccount = 0;
int min = 256 * i;
int max = min + 256;
for (int j = min; j < max; j++)
{
if (j != 0 && ramp[j] != 0 && ramp[j] != 65536)
{
double B = (j % 256) / 256.0;
double A = ramp[j] / 65536.0;
float C = (float) ( log(A) / log(B) );
Csum += C;
Ccount++;
}
}
rgb[i] = Csum / Ccount;
}
return rgb;
}

--

Re: [MBS] gamma fade problem
Date: 27.01.03 16:15 (Mon, 27 Jan 2003 16:15:44 +0100)
From: Christian Schmitz
> Strange. I'm still not convinced that we shouldn't be able to do a
> full gamma fade under windows XP. The fact that we can get from 100%
> to 50% just fine, but not below 50%, still seems to me like it must
> be a sign/unsigned integer bug.

How should it be?
I convert the singles to a word with multiplying by 65536.0.
So if it's 0, the resulting value will be 0.
I'll try to find a Windows XP machine to test this.

Mfg
Christian

Re: [MBS] gamma fade problem
Date: 27.01.03 18:01 (Mon, 27 Jan 2003 09:01:03 -0800)
From: Mike D.
> > Strange. I'm still not convinced that we shouldn't be able to do a
>> full gamma fade under windows XP. The fact that we can get from 100%
>> to 50% just fine, but not below 50%, still seems to me like it must
>> be a sign/unsigned integer bug.
>
>How should it be?
>I convert the singles to a word with multiplying by 65536.0.
>So if it's 0, the resulting value will be 0.
>I'll try to find a Windows XP machine to test this.
>
>Mfg
>Christian

I just did my own gamma fade tests using code I wrote myself, and I
get the exact same results. I can fade from 100% to 50% just fine,
but below 50% SetDeviceGammaRamp() returns FALSE. Therefore, I no
longer think it is a bug in your code.

There are some notes in the Microsoft documentation that
SetDeviceGammaRamp() will fail if it decides your gamma tables are
"too complex". But of course there is no more documentation.
(Reminds me why I prefer working on Macs...)

I'm sure that full gamma fading is possible on a windows machine;
perhaps one must use DirectX for it to work?

Is there any chance that you could write a new gamma fade method that
uses DirectX instead (weak-linked as appropriate?)

Anyway, here is my code for reference...

Function FadeGammaTo(percent as double, originalGamma as memoryBlock) As string
// see http://apollo.iwt.uni-bielefeld.de/~ml_robot/OpenGL-04-2000/0058.html
dim mb as memoryBlock
dim i,j as integer
dim ignore as integer
dim screenDC as integer
dim v as integer

Declare Function SetDeviceGammaRamp Lib "gdi32" (hdc As integer,
lpv As Ptr) As integer
Declare Function GetDC lib "User32" (hdc as integer) as integer
Declare Function ReleaseDC lib "User32" (hdc as integer) as integer

mb = newMemoryBlock(256*3*2)

' if no original gamma table, then make a linear ramp
if originalGamma = nil then
for i = 0 to 2
for j = 0 to 255
mb.byte(i*256+j) = j*percent
next
next
else
' scale the original one by percent
for i = 0 to (256*3*2) - 1
v = originalGamma.byte(i)
mb.byte(i) = v

next
end if

screenDC = GetDC(0)
if SetDeviceGammaRamp(screenDC, mb) = 0 then
releaseDC(screenDC)
return "FAILED"
else
releaseDC(screenDC)
return "OK"
end if

End Function

Function GetGammaRamp() As memoryBlock
// see http://apollo.iwt.uni-bielefeld.de/~ml_robot/OpenGL-04-2000/0058.html
dim mb as memoryBlock
dim i,j as integer
dim ignore as integer
dim screenDC as integer
dim s as string
Declare Function GetDeviceGammaRamp Lib "gdi32" (hdc As integer,
lpv As Ptr) As integer
Declare Function GetDC lib "User32" (hdc as integer) as integer
Declare Function ReleaseDC lib "User32" (hdc as integer) as integer

mb = newMemoryBlock(256*3*2)
screenDC = GetDC(0)
if GetDeviceGammaRamp(screenDC, mb) = 0 then
releaseDC(screenDC)
msgBox "returned false"
end if

releaseDC(screenDC)
for i = 0 to 3
s = hexstring(mb.stringValue(i*512,512),2,64,"<", ">"+chr(10),"","0")
msgBox s
next

return mb

End Function

Re: [MBS] gamma fade problem
Date: 27.01.03 18:24 (Mon, 27 Jan 2003 18:24:54 +0100)
From: Christian Schmitz
> I just did my own gamma fade tests using code I wrote myself, and I
> get the exact same results. I can fade from 100% to 50% just fine,
> but below 50% SetDeviceGammaRamp() returns FALSE. Therefore, I no
> longer think it is a bug in your code.

Fine :-)

> There are some notes in the Microsoft documentation that
> SetDeviceGammaRamp() will fail if it decides your gamma tables are
> "too complex". But of course there is no more documentation.
> (Reminds me why I prefer working on Macs...)

Well, strange that you use .byte on the memoryblocks.
But calling SetDeviceGammaRamp with an empty memoryblock should also set
it to black, but this seems to fail.

> I'm sure that full gamma fading is possible on a windows machine;
> perhaps one must use DirectX for it to work?

Maybe.

> Is there any chance that you could write a new gamma fade method that
> uses DirectX instead (weak-linked as appropriate?)

Sorry. I've no knowledge of DirectX.
Never used it.

Mfg
Christian

Re: [MBS] gamma fade problem
Date: 27.01.03 19:19 (Mon, 27 Jan 2003 10:19:04 -0800)
From: Mike D.
>Well, strange that you use .byte on the memoryblocks.

The gamma values are words, but each value is stored only in the high
byte of each word. I used .byte to avoid sign errors.

>But calling SetDeviceGammaRamp with an empty memoryblock should also set
>it to black, but this seems to fail.

I agree. it's as if windows won't let you make the screen too dark!

> > Is there any chance that you could write a new gamma fade method that
>> uses DirectX instead (weak-linked as appropriate?)
>
>Sorry. I've no knowledge of DirectX.
>Never used it.

If I have the time to write a gamma fade that uses directx, would you
be interested in including it in MBS? I'll look into what would be
involved.

I also have some messages out on usenet seeking help with the
SetDeviceGammaRamp() call...

Re: [MBS] gamma fade problem
Date: 27.01.03 19:36 (Mon, 27 Jan 2003 19:36:11 +0100)
From: Christian Schmitz
> If I have the time to write a gamma fade that uses directx, would you
> be interested in including it in MBS? I'll look into what would be
> involved.
>
> I also have some messages out on usenet seeking help with the
> SetDeviceGammaRamp() call...

Sure. Send whatever you want. If it works better, I include it.

Mfg
Christian