|
Well, a memory leak is the opposite thing and happens when a pointer goes out of scope or is overwritten before the allocated memory was released.
What you have is a faulty lifcycle management. You can't release an object and then try to use it again. Your program must make sure that pointers are initialized before being used and also that those pointers are not forgotten or overwritten.
Begin with setting all pointers to NULL immediately after releasing the memory. This way you can at least check wether the pointer is NULL or contains a valid pointer before using it. To completely solve it, you should implement a better lifecycle management for your objects.
The language is JavaScript. that of Mordor, which I will not utter here
This is Javascript. If you put big wheels and a racing stripe on a golf cart, it's still a f***ing golf cart.
"I don't know, extraterrestrial?"
"You mean like from space?"
"No, from Canada."
If software development were a circus, we would all be the clowns.
|
|
|
|
|
Running with a memory leak detector can help?
|
|
|
|
|
According to the documentation included with this snippet I should be able to replace the placeholder function with my own.
I am not knowledgeable enough to decipher what exactly is the code trying to accomplish and how to replace it with real function.
A reference would also work, but since I have no idea what is this called I do not know what to Google for. Since this is not working code, code tags were not used.
Appreciate your help
Vaclav
/**
* SysTick hook
*
* This function is called from SysTick handler, before the default
* handler provided by Arduino.
*/
static int __false() {
// Return false
return 0;
}
int sysTickHook(void) __attribute__ ((weak, alias("__false")));
|
|
|
|
|
|
Yes, it is the last part of code implementing system timer ( ARM processor)
It is in what Arduino calls "core " code and I don';t really want to modify that code.
I just do not understand the syntax.
I read about GCC attributes, but it did not provide full answer.
What I am hoping for is some equivalent to function overload to replace the default function which does nothing and actually returns wrong value.
The return would be the easy part to fix.
|
|
|
|
|
Well
If this is found in a Cpp File,
it first of al defines a static Function, named 'false() returning an int.
Vaclav_Sal wrote: int sysTickHook(void) __attribute ((weak, alias("__false"))); Your Quoted Text has a Serious Bracket Imbalance, 'weak' and 'alias' are not CPP keywords.
I am not aware of any API called 'sysTickHook()' I think you are in the wrong forum.
Bram van Kampen
|
|
|
|
|
First lets give you what you are dealing with
Weak symbol - Wikipedia, the free encyclopedia[^]
The instructions you don't recognize are linker instructions to the compiler and will be absolutely required.
In the old days we used to have to compile units individually into ELF or OBJ files and then manually put them together, the syntax as they developed allow for automation of that process. Almost every C/C++ compiler on the market will have a way to pass instructions out to the linker and will be non standard but essential.
If you are trying to provide weak linking instructions on Visual Studio it is
__declspec(selectany)
Microsoft Visual Studio - selectany[^]
If you are trying to write portable code or ANSI compliant code you will need to refer to your special section in your compliance documentation on the use of linker instructions. I write ANSI compliant code for a number of companies and all they prefer to deal with them in different ways. Some insist you need it all in a specific implementation file and document, some will make you put it into a macro in an implementation file (with all other similar MACROS so they can easily look for conflicts).
Finally what the documentation is saying is you can provide the function
int sysTickHook(void){
}
That will be a timer tick function which is generally used to do things like update time etc. They just provide a dummy function which does nothing in case you don't need it there other code assumes you might and so they have a function call which must go somewhere.
In all normal O/S's linux, DOS, Windows they all have a kernel timertick which generally does a basic function like update the system time. They are allowing you to have the same.
In vino veritas
modified 9-Sep-16 0:59am.
|
|
|
|
|
I am not sure why all these tags , but I just want to let the forum know I found a reference.
Basically two "features" - attribute and weak / strong function declaration , in my case used by GCC.
Yet another neat way to extend K&R creation.
Thanks for all the help, I appreciate it.
<a href="http://www.valvers.com/programming/c/gcc-weak-function-attributes/">GCC Weak Function Attributes &#8211; Valvers</a>[<a href="http://www.valvers.com/programming/c/gcc-weak-function-attributes/" target="_blank" title="New Window">^</a>]
|
|
|
|
|
In reference to the widely used CalculateRamp code:
public static void CalculateRamp(double level, double gamma, double brightness, double contrast)
{
ramp.Red = new ushort[256];
ramp.Green = new ushort[256];
ramp.Blue = new ushort[256];
gamma /= 10;
brightness = 1 + (((brightness - 50) / 100) * 65535);
contrast = 1 + ((contrast - 50) / 100);
level = 1 + ((level - 50) / 100);
for (int i = 0; i < 256; i++)
{
double value = i * 256;
value = (Math.Pow(value / 65535, 1 / gamma) * 65535) + 0.5;
value = ((((value / 65535) - 0.5) * contrast) + 0.5) * 65535;
value = value += brightness;
value *= level;
ramp.Red[i] = ramp.Green[i] = ramp.Blue[i] =
(ushort)Math.Min((double)65535, Math.Max((double)0, value));
}
SetDeviceGammaRamp(GetDC(IntPtr.Zero), ref ramp);
}
How would you calculate the input values (arguments) for this method directly from the existing Gamma Ramp? In other words, what would be the reverse method?
If I am going to provide these utilities to the user, I need to present them with their current settings prior to their making the adjustments.
I have tried for three days to come up with a solution, and must admit that this is beyond my capabilities.
Update Sept 8, 2016 - My best solution...
While I worked long and hard looking for a mathematical solution, I finally went back and played around with the iteration method.
A blunt force iteration that calculates each and every possible setting and then checks for a match will run for more than 20 minutes; which is unacceptable.
I found that I could take a single sample point in the middle of the array and quickly iterate through all possible settings to find a match for that one sample; and then perform all 256 of the calculations for the array to see if we had a complete match. This operation generally runs in less than a second.
But I realized that there was yet another problem. If the Gamma Ramp was not programmed using the CalculateRamp algorithm (such as factory setting) then it is unlikely that we will find an exact match for our settings; and our solution will fail.
So I devised a backup plan that uses four sample points from across the gamma ramp array; and then set up a "span" of acceptable values that would provide a close approximation for our settings. The criteria for "span" would broaden after each failure, and re-enter the search. This scenario will produce an approximation of the Gamma Ramp Settings usually within about three seconds. This is acceptable since my main program can perform this operation during the program startup sequence.
Here is my C++ solution...
int __fastcall TForm1::Round( double flt ){
int num = (int) flt;
if( flt >= 0 ){
if( flt - num >= .5 ){ num++;}
}else{
if( flt - num <= -.5 ){ num--;}
}
return( num );
}
void __fastcall TForm1::GetGammaRampSettings(void){
double i,j,k,m;
double gamma,bright,cntrst,level;
double v1,v2,v3,v4;
double c1,c2,c3,c4;
double a1,a2,a3,a4,b1,b2,b3,b4; int x1,x2,x3,x4,x5;
int d,n;
WORD span = 8;
bool tog = false;
TDateTime strt, end;
WORD GammaArray[3][256]; WORD CompArray[256];
HDC GammaDC = GetDC( NULL ); GetDeviceGammaRamp( GammaDC, GammaArray );
ReleaseDC( NULL, GammaDC );
strt=Now();
for( x1 = 0; x1 < 256; x1++ ){
if( GammaArray[0][x1] > 0 ){ break;}
}
for( x2 = 0; x2 < 256; x2++ ){
if( GammaArray[0][x2] == 65535 ){ break;}
}
if( x2 == 256 ){ x2 = 255; }
x5 = x1 + Round( (double)( x2 - x1 ) / 2.0 );
Memo1->Lines->Add( "x1 = " + IntToStr( x1 )); Memo1->Lines->Add( "x2 = " + IntToStr( x2 )); Memo1->Lines->Add( "x5 = " + IntToStr( x5 ));
for(n=0;n<=40;){ if( n < 9 ){ if( tog ){ i = ( 10 - n );
tog = false; n++;
if( i == 10 ){ continue;}
}else{
i = ( 10 + n );
tog = true;
}
}else{
i = ( 10 + n++ );
}
gamma = i / 10;
v1 = ( pow( (double)(x5 * 256) / 65535, 1 / gamma) * 65535) + 0.5;
for( j = 2; j < 101 ; j++ ){ level = 1 + ((j - 50) / 100);
for( k = 0; k < 101; k++ ){ bright = 1 + (((k - 50) / 100) * 65535);
for( m = 0; m < 101; m++ ){ cntrst = 1 + ((m - 50) / 100);
c1 = (((( v1 / 65535 ) - 0.5) * cntrst) + 0.5) * 65535;
c1 = c1 += bright;
c1 *= level;
if( c1 > 65535){ c1 = 65535; }
if( c1 < 0 ){ c1 = 0; }
if( (WORD) c1 == GammaArray[0][x5] ){
for( d = 0; d < 256; d++ ){
c1 = ( pow( (double)(d * 256) / 65535, 1 / gamma) * 65535) + 0.5;
c1 = ((( (c1 / 65535) - 0.5) * cntrst) + 0.5) * 65535;
c1 = c1 += bright;
c1 *= level;
if( c1 > 65535 ){ c1 = 65535;}
if( c1 < 0 ){ c1 = 0;}
CompArray[d] = (WORD) c1;
}
if(memcmp( &CompArray[0], &GammaArray[0][0], 2*256) == 0){
goto ENDIT;
}
}
}
}
}
}
Memo1->Lines->Add("Values NOT Discovered!!!");
Memo1->Lines->Add("Widening the Search....");
x3 = x1 + Round( (double)( x2 - x1 ) / 4.0 );
x4 = x1 + Round(( (double)( x2 - x1 ) / 4.0 )*3);
Memo1->Lines->Add( "x1 = " + IntToStr( x1 )); Memo1->Lines->Add( "x2 = " + IntToStr( x2 )); Memo1->Lines->Add( "x3 = " + IntToStr( x3 )); Memo1->Lines->Add( "x4 = " + IntToStr( x4 ));
BROADEN:
a1 = GammaArray[0][x1]+span; b1 = GammaArray[0][x1]-span; a2 = GammaArray[0][x2]+span;
b2 = GammaArray[0][x2]-span; a3 = GammaArray[0][x3]+span; b3 = GammaArray[0][x3]-span;
a4 = GammaArray[0][x4]+span;
b4 = GammaArray[0][x4]-span;
tog=false;
for(n=0;n<=40;){ if( n < 9 ){ if( tog ){ i = ( 10 - n );
tog = false; n++;
if( i == 10 ){ continue;} }else{
i = ( 10 + n );
tog = true;
}
}else{
i = ( 10 + n++ );
}
gamma = i / 10;
v1 = ( pow( (double)(x1 * 256) / 65535, 1 / gamma) * 65535) + 0.5;
v2 = ( pow( (double)(x2 * 256) / 65535, 1 / gamma) * 65535) + 0.5;
v3 = ( pow( (double)(x3 * 256) / 65535, 1 / gamma) * 65535) + 0.5;
v4 = ( pow( (double)(x4 * 256) / 65535, 1 / gamma) * 65535) + 0.5;
for( j = 2; j < 101 ; j++ ){ level = 1 + ((j - 50) / 100);
for( k = 0; k < 101; k++ ){ bright = 1 + (((k - 50) / 100) * 65535);
for( m = 0; m < 101; m++ ){ cntrst = 1 + ((m - 50) / 100);
c1 = (((( v1 / 65535 ) - 0.5) * cntrst) + 0.5) * 65535;
c1 = c1 += bright;
c1 *= level;
c2 = (((( v2 / 65535 ) - 0.5) * cntrst) + 0.5) * 65535;
c2 = c2 += bright;
c2 *= level;
c3 = (((( v3 / 65535 ) - 0.5) * cntrst) + 0.5) * 65535;
c3 = c3 += bright;
c3 *= level;
c4 = (((( v4 / 65535 ) - 0.5) * cntrst) + 0.5) * 65535;
c4 = c4 += bright;
c4 *= level;
if( c1 <= a1 && c1 >= b1 && c2 <= a2 && c2 >= b2 &&
c3 <= a3 && c3 >= b3 && c4 <= a4 && c4 >= b4 ){
Memo1->Lines->Add("Best Estimate +/- " + IntToStr( span ));
goto ENDIT;
}
}
}
}
}
if( span < 256){
span *= 2;
goto BROADEN;
}else if( span <= 4096 ){ span += 128; goto BROADEN; }
Memo1->Lines->Add("Values STILL NOT Discovered.");
Memo1->Lines->Add("GetGammaRampSettings Failed.");
return;
ENDIT:
end=Now();
Memo1->Lines->Add("Execution duration was "+
FormatDateTime("nn:ss:zzz",end-strt));
Memo1->Lines->Add("Bright = " + IntToStr( (int) k ));
Memo1->Lines->Add("Cntrst = " + IntToStr( (int) m ));
Memo1->Lines->Add("Level = " + IntToStr( (int) j ));
Memo1->Lines->Add("Gamma = " + IntToStr( (int) i ));
}
modified 8-Sep-16 14:53pm.
|
|
|
|
|
Keith Davis wrote: the widely used CalculateRamp code Widely used by whom, and for what purpose? It also look like this is C# code not C++.
|
|
|
|
|
Yes this is C# code but I have found it on the Internet in C++ as well. The math is essentially the same either way.
This algorithm is used to adjust (or program) your graphic's card's gamma ramp with inputs for Brightness, Contrast, Level, and Gamma. It works well.
For test purposes I created a graph that plots the resulting gamma ramp. This helps me to visualize the changes made to the gamma ramp array; but I can't figure out how to work the problem from the existing gamma ramp array back to what would be the input arguments for Brightness, Contrast, Level, and Gamma.
It is simply beyond me.
|
|
|
|
|
Here is my C++ implementation of the algorythm:
void __fastcall TForm1::SetRamp(double level, double gamma, double bright, double cntrst){
HDC GammaDC=GetDC(NULL);
WORD GammaArray[3][256];
gamma /= 10;
bright = 1 + (((bright - 50) / 100) * 65535);
cntrst = 1 + ((cntrst - 50) / 100);
level = 1 + ((level - 50) / 100);
for(DWORD i=0;i<256;i++){
double value = i * 256;
value = (pow(value / 65535, 1 / gamma) * 65535) + 0.5;
value = ((((value / 65535) - 0.5) * cntrst) + 0.5) * 65535;
value = value += bright;
value *= level;
if(value>65535){value=65535;}
if(value<0){value=0;}
GammaArray[0][i]=GammaArray[1][i]=GammaArray[2][i]=(WORD)value;
}
if(!SetDeviceGammaRamp(GammaDC,GammaArray)){
Memo1->Lines->Add("SetDeviceGammaRamp Failed");
GraphIt(&GammaArray[0][0], false);
}else{
GraphIt(&GammaArray[0][0], true);
}
ReleaseDC(NULL,GammaDC);
}
|
|
|
|
|
All the gamma ramp or inv ramp does is stretch or compress the greyscale representation of the color range map.
So two simplest shapes you play with is exponential and 1-exponential graphs. A simple google of the two functions
will give you the formula and code for them. The above is an exponential hence the power function. Really you only
need the exponential form because 1-exp will give you the reverse code.
So if the above code works as you want 1 - (the exponential result) is the inverse it really is that simple as the
code result must be in the range between 0-1 you should be able to see why it inverts the graph. If you can't see
the logic google exp function and 1-exp function for the explaination.
In vino veritas
|
|
|
|
|
Hi Leon,
I understand what is going on with the Gamma Ramp. My question is really a math problem, and thus far the solution is beyond my skill level.
The algorithm previously posted works very well, and gives good control of the gamma ramp. What I don't understand concerning this algorithm is why my question has not been asked before. It seems that the first thing you would want to do is interpret the current settings from the gamma ramp array; and present the current settings to the user so that he can then begin to make adjustments by using the algorithm that I previously posted.
I'm trying to work the problem backwards from the GetDeviceGammaRamp function call to whatever input values would be required to create the current gamma ramp array: What will be the Brightness setting, what will be the Contrast setting, what will be the Level setting, and what will be the Gamma setting "going in".
The way that the input algorithm works is made ever more complex because "value" undergoes four or five operations before arriving at a final input value for each of the 256 members of the array. How to reverse this series of operations has me stumped.
Given any two of the three parts for any of these operations; it is possible to come up with the third part:
For example: any unknown part of 6=2*3 can be determine so long as any two parts are known ie: 3=6/2.
x=pow(y,z): y can be determined using y=pow(x,(1.0/z)); and z can be determined using log(x)/log(y).
The initial "value" is determined by it's place in the array, so this is known to us. Also know to us is the final value of "value" because we can extract it from the current gamma ramp array. So how would you work the problem backwards through each operation from the value of the gamma array [element] to determine each of the values for Brightness, Contrast, Level, and Gamma?
My graph visually demonstrates what is going on with the gamma ramp array. When Gamma is set to input value of 10, the curve is neutralized, and the graph presents a strait line.
When Brightness is lower than 50 the line moves in parallel from the 45 degree angle towards the lower right, and greater that 50 moves the line towards the upper left in parallel.
When Contrast is lower than 50, the graph line pivots clockwise about it's midpoint, and an input greater than 50 will pivot the line counterclockwise about its midpoint.
When Level is adjusted below 50 then the end of the graph line swings downwards while the starting point (0,0) remains stationary; and when Level is adjusted upwards the end of the graph line swings upwards while the starting point remains stationary.
When Gamma is adjusted to either side of 10; the graph line becomes a positive or negative curve.
All very interesting, but it doesn't provide me with any solutions to my problem.
At any rate, thanks for your interest and your input!
Best regards,
In Corona simul veritas
|
|
|
|
|
I started working a much more detailed description of how to play with the curve but realized that isn't what you were confused about.
Gamma-correcting an image is essentially raising its color intensities to 1/gamma, so that when the monitor in turn raises the value to gamma, these cancel out.
You said ... I'm trying to work the problem backwards from the GetDeviceGammaRamp function call to whatever input values would be required to create the current gamma ramp array. You need to explain why you want to reverse it .. you aren't a hardware device. Your code is designed for something like a game where it simply loads a slight adjustment to the colors at start up where it will set the gamma ramp table on the DC. You sound more like you are trying to do something like an ICC profile.
Your code is a basic exponential function it wouldn't really match a real monitor gamma output distortion which would need something like a spline. That would all be done in a processing phase not down on the output out to a device context. So I think you need to explain more what you are trying to do.
Perhaps read the Microsoft overview of gamma control on windows and expand it from there.
Using gamma correction (Windows)[^]
The current gamma correction occurs on 1 line of code in your example above
value = (Math.Pow(value / 65535, 1 / gamma) * 65535) + 0.5;
The initial gamma is divided by 10 so if you enter 10 you get Math.Pow(value / 65535, 1) that is it's linear
and the value is basically value/65535*65535 .. AKA the same value.
Value is defined as
double value = i * 256;
So all that whole function does is return a value in 256 step increments.
With gamma set to 10 you are going to get 0,255,511, ... 65535
The reverse table can be built using the line
value = (Math.Pow(value / 65535, gamma) * 65535) + 0.5;
Straight mathematics anything raised to a power is inverted by raising to 1/power so replace 1/gamma with gamma, I made bold and underlined so the substitution is more obvious.
Still confused what you are trying to do, but hopefully something there helps.
In vino veritas
modified 5-Sep-16 6:26am.
|
|
|
|
|
Hi Leon,
I took a good look at the code and the web site that you suggested, and I find it interesting. That said, I don't think it applies to my application. If I'm not mistaken, your suggested code would be something that you might use for adjusting the gamma of a photo.
The algorithm that I have put forward is actually easy to control with either four slider controls, or four updown/edit controls that will affect the graphics card for your display monitor. One control for each of the following Brightness, Contrast, Level, and Brightness.
Allow me to explain the goals that I need to achieve here in my application:
I am working on a Navigation Display where there are strict specifications for color and brightness calibration in three viewing modes: Daytime, Twilight, and Night. In this application I also make calls to GetSysColors and SetSysColors to change the over all appearance of the Windows display for Day, Twilight, and Night. The specifications also call for three specific cursors that each have to meet strict size and color requirements for each display mode. There are numerous color checks involved, as well as a grey scale display check that must appear ever time the user switches to the night time display settings (and on demand).
These specifications are laid out in the the International Hydrographic Organizations (IHO) Presentation Library for ECDIS which uses the S-57 Electronic Navigation Chart (ENC) display.
For the twilight and night time display modes it is critical that mariner's night vision be preserved, and that optimum view-ability be achieved under bright sunlight conditions.
The grey scale check that is required consist of a black box with a slightly lighter shaded box inside for which the user must be able to calibrate his display so that the lighter shaded box can be easily differentiated from the black box background. The algorithm above serves these calibration purposes.
I have used this algorithm for a number of years to adjust my own display for less eye strain when I'm spending hours at a time writing code - sometimes in a night time environment (on the ship's bridge). Because of the my inability to derive the Brightness Contrast, Level, and Gamma settings directly from the Gamma Ramp array, I have not employed this method in any of my software releases.
Thus far the best I have been able to do is iterate through all possible settings until the output matches the Graphics Card's Gamma Ramp array received through the GetDeviceGammaRamp call. This works but it takes about 49,000,000 iterations and runs for 15-20 minutes. I have applied some variations to this which has shortened the run time; but it still takes about 5 minutes to run it. I need to be able to derive these settings in about a one second. I haven't given up yet though
I hope this helps to better explain my goals.
Again, thank you for your interest and your suggestions; it is much appreciated!
Best regards.
|
|
|
|
|
But what you are doing seems to be re-inventing the wheel at least on Windows 7, 8 and 10 or I am completely missing something.
If you go to color management in control panel on Windows and tick the box on the display that says use color management (it defaults off) it will use the ICC profile for the monitor. That profile will exist so long as it has detected the monitor type and isn't using the generic. You will see the ICC profile in the box labelled Profiles associated to this device.
For most Joe Average they would only go looking for this setting if they are running dual monitors and want the two displays to have the exact some color output to the eye. It's really annoying when you have two monitors side by side on a dual monitor system with different shades. The whole point of the ICC is so that the computer color space looks exactly the same when displayed on different monitors.
So can I first ask is the color management turned on in your situation? If it is on then why don't you directly read the ICC profile which seems to be the exact thing you are trying to map from the the deviceramptable?
At least then you are down to each user will see every monitor the same, and now you need to adjust simply for each users eye which would carry from monitor to monitor if they are all running ICC or is there something I am missing?
In vino veritas
modified 5-Sep-16 12:31pm.
|
|
|
|
|
Hi Leon,
I actually haven't examined the Windows Color Management; and perhaps I should look into this.
However, I would still have to meet the specifications laid down by the IHO.
These specifications are fairly strict. When the ECDIS is set up it has to be inspected and tested with an instrument that reads the color values directly from the display screen; and they must meet specifications or else adjustments must be made to the [X,Y,L] color tables (and/or the hardware). I have had to build these testing scenarios and conversion functions into the software. Additional routines for the mariner to do self testing at sea are also a requirement (color comparison charts and the grey scale test that I mentioned previously).
To say the least, meeting these specifications has been fairly demanding. There are several thousand pages in total; and the display requirements come up again and again through out.
Getting these Brightness, Contrast, Level, and Gamma settings from the gamma ramp array has just been a minor setback in the grand scheme of things, but sooner or later I'll figure it out. I may be close to being able to extract the current gamma setting - working on it...
Cheers
|
|
|
|
|
You went and made me look it up just out of curiosity
The definitive details is given in the specification
https://www.iho.int/iho_pubs/standard/S-52/S-52_e6.0_EN.pdf[^]
-Software to generate the required colours for use during the calibration. This will
be a program that allows the user to adjust the colour DAC values from 0 to 255
in each of Red, Green and Blue.
- Software to calculate the transformation between RGB and CIE x, y, L values.
(This software is part of the Presentation Library.)
Your physical testing is for compliance to the standard CIE absolute color space.
Any windows OS from 7 up with color management turned on, with a compliant monitor should meet that specification and you just need to do the user controls they ask for in the specification. If it doesn't either the monitor manufacturer or Microsoft has some answering to do.
In vino veritas
|
|
|
|
|
Thanks for that insight. I sort of suspected that most modern monitors and operating systems would be compliant. It is going to be the end user's responsibility to have their system certified, and then do the regular checks that are required.
There is the software for conversion of the xyl values, and there is also software for the performing the color test on a CRT monitor. At the time I purchased my current version of the Presentation Library (2008) they had not yet developed tests for a LCD display. The latest version of the Presentation Library is in transit to me now, and I'm curious to see what changes have been made to the specifications since my 2008 version; and whether they will now have some sort of testing procedure for the LCD monitor. In 2008 it was still under consideration.
The way I see it, I just have to meet the specs; but even that going to be daunting. I don't expect to have this ECDIS system ready for another two years. I have had a navigation program out since 2003 - but it is not ECDIS. There are no electronic navigation charts in my existing system; but it does have background maps (world wide coverage). My latest (as yet unreleased) version is also NMEA 2000 compatible and features extensive networking capabilities. The system also has it's own "line tracking" autopilot built into it; which is great for oceanographic survey work - I hate driving lines day in and day out - it's mind numbing.
I have only recently decided that it was time to take my nav program to the next level; and make it ECDIS compliant.
Again, thanks for checking that out
Cheers!
|
|
|
|
|
Hi Leon,
I have finally found a solution for my problem; and have edited my original post to reflect this. It's not a mathematical solution, but it works well enough.
I just thought I'd give you a heads up since you took an interest
Thanks again for your input!
Keith
|
|
|
|
|
 Quote: After unsuccessfully trying to solve for a mathematical solution for a week I had to try some other way to derive the Gamma Ramp Settings directly from the GetDeviceGammaRamp call.
One early attempt involved a simple iteration of all possible settings. This gave correct results, but it took more than 20 minutes to complete the operation. My application needs to be able to do this in under a second.
I finally found a better, more efficient way to perform the iterations, and it meets my requirements. It may be an imperfect solution; but a win is a win.
I shaved a little more time off of this operation by testing for a positive or a negative curve in the Gamma setting (or no curve at all = neutral setting 10). This saves a few iterations going in. To do this I created two additional functions: PtToPtRngBrg and GetPtFromPt.
If you like, you can skip these; and simply iterate through all possible Gamma settings (2 to 50). This would greatly simplify the code.
Here is my C++ solution...
#define DEG_RAD 0.017453292519943295769236907684886
struct RngBrg{
double rng;
double brg;
};
void __fastcall TForm1::GetGammaRampSettings(void){
double i,j,k,m,m4;
double s1,s2,s3,s4;
double gamma,bright,cntrst,level;
double value;
int d;
int x1,x2,x3,x4;
bool isFound=false;
RngBrg rb;
WORD GammaArray[3][256];
WORD CompArray[256];
double DArray[256];
HDC GammaDC = GetDC( NULL );
GetDeviceGammaRamp( GammaDC, GammaArray );
ReleaseDC( NULL, GammaDC );
for( x1 = 0; x1 < 256; x1++ ){
if( GammaArray[0][x1] > 0){break;}
}
for( x2 = 0; x2 < 256; x2++ ){
if( GammaArray[0][x2] == 65535){isFound=true; break;}
}
if( !isFound ){ x2--; }
s1 = ( (double) GammaArray[0][x1] + 1 ) / 256.0;
s2 = ( (double) GammaArray[0][x2] + 1 ) / 256.0;
x3 = x1 + ( ( x2 - x1 ) / 2 );
s3 = ( (double) GammaArray[0][x3] + 1 ) / 256.0;
Memo1->Lines->Add( "x1 = " + IntToStr(x1) + " s1 = " + AnsiString(s1));
Memo1->Lines->Add( "x2 = " + IntToStr(x2) + " s2 = " + AnsiString(s2));
Memo1->Lines->Add( "x3 = " + IntToStr(x3) + " s3 = " + AnsiString(s3));
PtToPtRngBrg( &rb, x1, s1, x2, s2 );
Memo1->Lines->Add( "rng = " + AnsiString( rb.rng ) +
" brg = " + AnsiString( rb.brg ));
GetPtFromPt(x1, s1, rb.rng / 2.0, rb.brg, &m4, &s4);
Memo1->Lines->Add("m4 = " + IntToStr( Round(m4) ) + " s4=" + AnsiString(s4));
Memo1->Lines->Add("s3 - s4 = " + AnsiString( s3-s4 ));
x4 = Round(m4);
if(( s4 - s3 ) > 1 ){
Memo1->Lines->Add("Negative Gamma Curve");
for( i = 9; i > 1; i-- ){
gamma=i/10;
for( d = 0; d < 256; d++ ){
DArray[d] = ( pow( (double)(d * 256) / 65535, 1 / gamma) * 65535) + 0.5;
}
for( j = 2; j < 101 ; j++ ){
level = 1 + ((j - 50) / 100);
for( k = 0; k < 101; k++ ){
bright = 1 + (((k - 50) / 100) * 65535);
for( m = 0; m < 101; m++ ){
cntrst = 1 + ((m - 50) / 100);
value = (((( DArray[x4] / 65535 ) - 0.5) * cntrst) + 0.5) * 65535;
value = value += bright;
value *= level;
if( value > 65535){ value = 65535; }
if( value < 0 ){ value = 0; }
if( (WORD) value == GammaArray[0][x4] ){
for( d = 0; d < 256; d++ ){
value = ((( (DArray[d] / 65535) - 0.5) * cntrst) + 0.5) * 65535;
value = value += bright;
value *= level;
if( value > 65535 ){ value = 65535;}
if( value < 0 ){ value = 0;}
CompArray[d] = (WORD) value;
}
if(memcmp( &CompArray[0], &GammaArray[0][0], 2*256) == 0){
goto ENDIT;
}
}
}
}
}
}
}else if((s3-s4)>1){
Memo1->Lines->Add("Positive Gamma Curve");
for( i = 11; i < 51; i++ ){
gamma=i/10;
for( d = 0; d < 256; d++ ){
DArray[d] = ( pow( (double)(d * 256) / 65535, 1 / gamma) * 65535) + 0.5;
}
for( j = 2; j < 101 ; j++ ){
level = 1 + ((j - 50) / 100);
for( k = 0; k < 101; k++ ){
bright = 1 + (((k - 50) / 100) * 65535);
for( m = 0; m < 101; m++ ){
cntrst = 1 + ((m - 50) / 100);
value = (((( DArray[x4] / 65535 ) - 0.5) * cntrst) + 0.5) * 65535;
value = value += bright;
value *= level;
if( value > 65535){ value = 65535; }
if( value < 0 ){ value = 0; }
if( (WORD) value == GammaArray[0][x4] ){
for( d = 0; d < 256; d++ ){
value = ((( (DArray[d] / 65535) - 0.5) * cntrst) + 0.5) * 65535;
value = value += bright;
value *= level;
if( value > 65535 ){ value = 65535;}
if( value < 0 ){ value = 0;}
CompArray[d] = (WORD) value;
}
if(memcmp( &CompArray[0], &GammaArray[0][0], 2*256) == 0){
goto ENDIT;
}
}
}
}
}
}
}else{
Memo1->Lines->Add("No Gamma Curve");
i=10;
gamma=1;
for( d = 0; d < 256; d++ ){
DArray[d] = ( pow( (double)(d * 256) / 65535, 1 / gamma) * 65535) + 0.5;
}
for( j = 2; j < 101 ; j++ ){
level = 1 + ((j - 50) / 100);
for( k = 0; k < 101; k++ ){
bright = 1 + (((k - 50) / 100) * 65535);
for( m = 0; m < 101; m++ ){
cntrst = 1 + ((m - 50) / 100);
value = (((( DArray[x4] / 65535 ) - 0.5) * cntrst) + 0.5) * 65535;
value = value += bright;
value *= level;
if( value > 65535){ value = 65535; }
if( value < 0 ){ value = 0; }
if( (WORD) value == GammaArray[0][x4] ){
for( d = 0; d < 256; d++ ){
value = ((( (DArray[d] / 65535) - 0.5) * cntrst) + 0.5) * 65535;
value = value += bright;
value *= level;
if( value > 65535 ){ value = 65535;}
if( value < 0 ){ value = 0;}
CompArray[d] = (WORD)value;
}
if(memcmp( &CompArray[0], &GammaArray[0][0], 2*256) == 0){
goto ENDIT;
}
}
}
}
}
}
Memo1->Lines->Add("Values NOT Discovered - Checking All Values...");
for(i=2;i<51;i++){
gamma=i/10;
for( d = 0; d < 256; d++ ){
DArray[d] = ( pow( (double)(d * 256) / 65535, 1 / gamma) * 65535) + 0.5;
}
for( j = 2; j < 101 ; j++ ){
level = 1 + ((j - 50) / 100);
for( k = 0; k < 101; k++ ){
bright = 1 + (((k - 50) / 100) * 65535);
for( m = 0; m < 101; m++ ){
cntrst = 1 + ((m - 50) / 100);
value = (((( DArray[x4] / 65535 ) - 0.5) * cntrst) + 0.5) * 65535;
value = value += bright;
value *= level;
if( value > 65535){ value = 65535; }
if( value < 0 ){ value = 0; }
if( (WORD) value == GammaArray[0][x4] ){
for( d = 0; d < 256; d++ ){
value = ((( (DArray[d] / 65535) - 0.5) * cntrst) + 0.5) * 65535;
value = value += bright;
value *= level;
if( value > 65535 ){ value = 65535;}
if( value < 0 ){ value = 0;}
CompArray[d] = (WORD) value;
}
if(memcmp( &CompArray[0], &GammaArray[0][0], 2*256) == 0){
goto ENDIT;
}
}
}
}
}
}
Memo1->Lines->Add("Values Still NOT Discovered!!!");
Memo1->Lines->Add("Discovery Operation Failed.");
return;
ENDIT:
Memo1->Lines->Add("Bright = " + IntToStr((int)k));
Memo1->Lines->Add("Cntrst = " + IntToStr((int)m));
Memo1->Lines->Add("Level = " + IntToStr((int)j));
Memo1->Lines->Add("Gamma = " + IntToStr((int)i));
}
short __fastcall TForm1::Round(double flt){
short num=(short)flt;
if(flt>=0){
if(flt-num>=.5){num++;}
}else{
if(flt-num<=-.5){num--;}
}
return(num);
}
bool __fastcall TForm1::PtToPtRngBrg(RngBrg *rb,double x1,double y1,double x2,double y2){
rb->rng=0;rb->brg=0;
double diffx,diffy,dangle;
if(x1>=x2){
if(x1>=0&&x2<0){diffx=x1+fabs(x2);}else{diffx=x1-x2;}
}else{
if(x2>=0&&x1<0){diffx=x2+fabs(x1);}else{diffx=x2-x1;}
}
if(y1>=y2){
if(y1>=0&&y2<0){diffy=y1+fabs(y2);}else{diffy=y1-y2;}
}else{
if(y2>=0&&y1<0){diffy=y2+fabs(y1);}else{diffy=y2-y1;}
}
if(diffx==0){
rb->brg=0;rb->rng=y2-y1;
return true;
}
if(diffy==0){
rb->brg=90;rb->rng=x2-x1;
return true;
}
dangle=atan(diffy/diffx);
rb->rng=diffx/cos(dangle);
dangle=dangle/DEG_RAD;
rb->brg=90-dangle;
return true;
}
void __fastcall TForm1::GetPtFromPt(double x, double y,double rng,double brg,double *x2,double *y2){
if(brg>=360){brg-=360;}
if(brg<0){brg+=360;}
if(brg==360||brg==0){*x2=x;*y2=y+rng;return;}
if(brg==270){*y2=y;*x2=x-rng;return;}
if(brg==90){*y2=y;*x2=x+rng;return;}
if(brg==180){*x2=x;*y2=y-rng;return;}
if(brg<90){
*x2=x+(rng*cos((90-brg)*DEG_RAD));
*y2=y+(rng*sin((90-brg)*DEG_RAD));
return;
}
}
|
|
|
|
|
Hi,
I am getting around to using a printer direct. It is a Steep Learning Curve! Prior to this, I produced Text Files, which could be Printed via Notepad.
Grabbed the Bull by the Horns, Want to print Straight from the Program.
I am using MFC42. The Target Machines are Win XP-SP1. (None are Internet Enabled, The System is Outside the Internet)
The Second Hand Win 8 computer I use to write on, has a Device Driver for an HP Printer. All goes well, until I hit the Print button in the Print Dlg. Then everything crashes.
End up After the Crash with a Dlg to tell me in very many words that the printer device could not be found!
Now, I know that there is no physical printer attached to my machine, but, there should be a more graceful idea of notifying me about that fact, other than crashing.
For Instance, Can I query the CDC about a Printer being Plugged In, etc.
Kind Regards,
Bram van Kampen
|
|
|
|
|
Are you using CPrintDialog Class[^] to get the details of the printer? If you do not have a physical printer attached you can use the MS XPS writer, or if you have a PDF print application installed you can use that.
|
|
|
|
|
Well, Thanks Richard.
I worked the sample given by Chris Mauder on the MFC Forum about Printing without the Document-View Architecture. I use the CPrintDialog to obtain a pointer to a device Context, presumably in my case pointing to a HP Printer,(Apparently Installed by the Previous Owner of the Laptop) and all appears to work well. I retrieve a (pointer to) a CDC from the CPrintDialog, and the Pointer is Not NULL.
The Only thing is that there is no HP, (or, any) Printer Plugged In. (It is my Coding Laptop) My experience with say 'MS Office' is, that when the printer is not actually plugged in at the time, that the job gets spun off to the print spooler where it remains until that printer becomes available.
Is this a Feature of the Windows Print Spooler, or, a Feature of 'MS Office'?
The result in my case is a very major Foul Up, and, Minutes Later, a Message from the HP Driver that the Device cannot be found, complete with Major Advice to check Cable Connections, and a Range of Other Things.
Now, on Further Reflection, (time for quiet reflection is something that we are unlikely (and Unwisely) allow to afford ourselves when hunting for Bugs.)
It may well be that the HP Printer Driver is corrupted. My Coding Laptop is not on the Internet for obvious reasons.(Installation of the "Ms Dev Studio97" on a Win7 Computer gives an Immediate alarm under 'IsGenuine' for the OS)
I'll try to install another printer driver, (from a CD), and see how it goes.
I am ashamed to say that I have avoided Printing for the last 25 years, actually, since my Dos Days.
I have decided to bite the bullet on this Application.
I Dealt with printing in the past by sending things to a Text File, and to use NotePad, when a Printout was needed.
Also, seeing that I only need to print only a few pages, mostly One A4, sometimes 2 or 3, I did not go to the complication of doing this in a Worker Thread. I want to learn how to Crawl, before trying to learn how to Run.
Would this have an Impact. Chris Mauder's example did not mention threads.
The thing is, when things go wrong, and, especially in a for me a New and crucial Field, is: Am 'I' doing something Wrong, or Misunderstanding Something.
Once Again, thanks for your response, Richard.
I'll keep you posted on how I get on.
Bram van Kampen
|
|
|
|
|