C Source Code

"Life would be so much easier if we only had the source code."
On this page:

Introduction

Here are some snippets of C code that I hacked for specific purposes. I believe them to be useful and since it was developed while I was paid by the (Italian/French/US) government, you might consider it like your tax money at work. All this code is ANSI C and should work on any 32 bit compiler. I have tested them on LabWindows/CVI on Windows and IRIX on an SGI.

Note: the zip files contain the source code, a lib file for Windows and an FP (function panel) for LabWindows/CVI version 5.5 (the .fp are not backward compatible with previous versions of CVI. Sorry. You can still try to use them by liking directly to the .lib).

First things first, 2 headers that everybody should have, the iso646.h for meaningful connectors (and is better than & or was it && ? No ?) and some version of my def.h useful definitions file.

You can right click on a frame and select [Open frame in new window] to get a full size listing; or SelectAll/Copy/Paste the frame into your favorite editor...



Statistics

LabWindows/CVI has some great libraries for math/signal stuff. The problem is that most of it works on arrays. What if you have on the fly data and want temporary results ? Here's a standard statistics module I wrote that enables you to keep feeding data to it while getting results. Note that you can compile it for FLOAT or DOUBLE precision. Two structures and two sets of functions: for single and double variables.

2 source files: Statistics.h, statistics.c and a function panel in Statistics.zip. Example of use:

	CStat S;
	StatReset(&S);
	StatAdd(&S, 10);
	StatAdd(&S, 0);
	StatAdd(&S, 50);
	A=StatAvr(&S);	// will return 20
	// S.N  =3
	// S.Min=0
	// S.Max=50
Category:
ANSI C (Windows, Unix...), LabWindows/CVI Function Panel
1994
First C++ version
1995
Lowered to C version

Color scaling

When you have a graph with a series of plots, it makes sense to display the plots in a range of colors, like a rainbow. Problem is, the rainbow is not very visible (all the colors have the same luminance), and how do you scale between two colors anyway ? Use my ColorScaleHSL function. This module also gives you conversion functions between RGB colors and HSL color definitions and macros to get darker colors.

See the examples below for different scales of RGB and HSL between 2 colors, or here for examples with 3 colors. If you don't want to bother with the source but want to do some color stuff, check out my color palette generator freeware.

Two source files: ColorScale.h, ColorScale.c and a function panel in ColorScale.zip. Example of use:

	COLORREF Color;
	for (RG=0; RG<NbRG; RG++) {
		if (Int[RG]<Min) Min=Int[RG];
		if (Int[RG]>Max) Max=Int[RG];
	}
	if (Max==Min) MaxInt++;		// Avoid divide by 0
	for (RG=0; RG<NbRG; RG++) {
		Color=ColorScaleHSL(VAL_WHITE, VAL_BLACK, (Int[RG]-Min)/(Max-Min));
		...
		SetCtrlAttribute (PnlFax, Cnvs , ATTR_PEN_COLOR, Color);
		CanvasDrawLine (PnlFax, Cnvs, P1, P2);
	}
Category:
ANSI C (Windows, Unix...), LabWindows/CVI Function Panel
1998
First version
2001
Added ability to scale between 3 colors
2001/09/10
Added inverted steps for more readable maps

[ScaleRGB.png]
Examples of scaling using RGB or HSL, Linear or with 8 steps

The images on the left show examples of scalings between various colors (black, white, primaries [RGB] and secondaries [CMY]) using linear RGB and linear HSL. Pass the mouse over the following lines (requires JavaScript):

RGB HSL
Linear 1 2
8 steps 3 4
Examples of linear scaling using HSL Examples of scaling using RGB with 8 inverted steps Examples of scaling using HSL with 8 inverted steps

Extended time formatting

The strftime function from the ANSI C library is nice, but it lacks a lot of things before being really useful in a scientific environment. My StrfTime() function adds many formatting codes, like the number of minutes since the start of the year and things like that. And it stays compatible with the standard C strftime() function.

Two source files for the library (StrfTime.h, StrfTime.c), a documentation file and a function panel in StrfTime.zip. Also 5 utility programs and scripts to compile independently:

TimeFormat.exe
uses StrfTime.exe to format a time string from the command line)
TimeDiffFormat.exe
similar but formats the difference between two times
TimeJump.exe
returns the previous or next time/date given a date in [YY]YY[MM[DD[HH[MM[SS]]]]] format
JulianDate.exe
Julian date to YYMMDD conversions
LengthOfYearMonth.exe
return the number of days in a given month or year
TimeLoop.sh
Shell script that loops between two dates, giving you plenty of local time variables to customize your own scripts
Make_Time
Makefile to compile all the programs. Just type make -f Make_Time

Note 1: this code uses both two and four digits years, and is Y2K compliant within 1970 ~ 2026.

Note 2: 'Julian day' refers here to a day of the year expressed as a number from 1 to 366, not to the true Julian calendar established by Julius Cesar and now superseded by the Gregorian calendar (our calendar). Julian days DDD are equivalent to Month/Days MMDD, but you need to know if the year is a leap year to provide a conversion. Source code included for all programs.

Category:
ANSI C (Windows, Unix...), LabWindows/CVI Function Panel
1997
First version
2001
PreviousTime.exe and TimeFormat.exe for automated shell scripts
2001/8/3
StrfTimeDiff function for formatting a time difference
2001/11/8
Julian day conversions.
2001/11/14
Added TimeDiffFormat and LengthOfYearMonth programs.
2002/01/15
Renamed FormatTime to TimeFormat and FormatDiffTime to TimeDiffFormat.
TimeJump.exe now supersedes PreviousTime.exe
2002/06/13
Added a YYYY or YY option for years
2005/06/02
Corrected bug when using seconds.
2005/11/14
Corrected bugs when converting Julian dates from YYYYMMDD format and length of year.

Example of Use in Unix: running through a sequence of dates (I also provide a script that does exactly that, with plenty of extras):

#! /bin/ksh
Start=950101	# Start date YYMMDD - included
Stop=$(FormatTime.exe NOW "%y%m%d")		# End date YYMMDD - excluded
YYMMDD=$Start
while [ $YYMMDD != $Stop ]
do
	FormatTime.exe $YYMMDD "%d %B %Y"
	# Skip to next day
	YYMMDD=$(TimeJump.exe $YYMMDD +1)
done

Parameter Parsing

When writing scientific programs, one of the first problem you run into is: how do you want to control the program parameters (input values, default directories...). Asking the user each time is not a good idea because you cannot run the program in a batch and most of the options are probably always the same; hard coding the values inside the program is fine until you need to change them (get the same compiler, same compiling options...); saving in the registry is non portable, complex and allows for only one set of data.

No the usual solution is to put the values inside a file. But then you need a parser to read it properly. Here's one. Note that this is for reading only, you cannot modify the parameter values inside the file. Also this code works but is not optimized for speed.

Two source files: ParseParam.h, ParseParam.c. I did not bother to create a function panel for LabWindows/CVI. Example of use:

	char DirSfcBin[MAX_PATHNAME_LEN];
	int MaxLat, DoLegend, ColorZero, ColorNan, ColorCurve;
	float MaxScale;
	ParseParamString("Param.txt", DirSfcBin);
	ParseParamInt("Param.txt", MaxLat);
	ParseParamFloat("Param.txt", MaxScale);
	ParseParamBool("Param.txt", DoLegend);
	ParseParamHex("Param.txt", ColorZero);
	ParseParamHex("Param.txt", ColorNan);
 	ParseParamHex("Param.txt", ColorCurve);
Will parse the following Param.txt file:
; This is the parameter file
; Comments are preceded by ; # or !
; You can use blank lines too
; Parameters can be in any order in the file, in case of duplicates, only the first one is read.

DirSfcBin="/raid/data/SfcRain/"		; Use double quotes around strings
NAN=-9999.			; float, ignored value
MaxLat = 40			; integer
ColorZero=	0xC0C0C0	; hex value
ColorNan =	FFFFFF		; optional 0x
ColorCuve=	0x101040		; Syntax error
MaxScale=10.		; leading/trailing spaces are ignored
DoLegend=Y		; Bool can be T, F, Y, N, True, False, Yes, No, 0, 1...
Category:
ANSI C (Windows, Unix...), parser.
2001
First version


Swap Endian byte order

Computers think using blocks of 8 bits (one byte). When using more, they order the elementary bytes either Least Significant First (LSF, Little Endian) or Most Significant First (MSF, big endian). This causes big trouble when trading binary files between machines.

To determine what your machine is, you can do (in the C programming language):
long L=1; void *Ptr=&L; char B=*(char*)Ptr;
If you get 1 as a result in B, your machine is little endian, if you get 0 it's big endian. The PC is little endian, the SGI machines and Macs are big endian.

Here's a routine and a couple macros to do the byte swapping. Note that normally values more than one byte should be aligned on a byte boundary. It means that a long (4 bytes) can be at address 0x1230, 0x1234, 0x1238... but usually should not be at 0x1231. It depends a lot on compiler options, optimization...

Two source file: SwapEndian.h and SwapEndian.c. Example of use:

	#include "SwapEndian.h"
	...
	double D;
	FILE *file=fopen("File.bin", "rb");
	fread(&D, sizeof(D), 1, file);
	SWAP_DOUBLE(D);
	printf("Value: %d", D);
Category:
ANSI C (Windows, Unix...), machine compatibility.
2001
First version

Graphic Filter

?php IR("Pics/Filters.png", "User interface of the FilterPopup module") ?>

You want to lighten up a bitmap or turn it to a negative image ? That's a simple graphic filter (here the function Filter1x1()).
You want to sharpen up a bitmap or enhance the edges or emboss it ? That can be done with a 3x3 graphic filter (here the function Filter3x3()).
You want to change a color bitmap to greyscale or switch the colors ? That can be done with an interchannel graphic filter (here the function Filter1C()).
This sample source code does all of that (plus 5x5 filters) and works in the same way than the user defined filters of applications like Buy at Amazon.comPhotoShop or Buy at Amazon.comPaint Shop Pro.

Some sample filters are included, but if you want to define your own, here's how for a 3x3 filter: define a 3x3 matrix with the coefficients of the surrounding pixels, a divider and a bias. For instance {{1,0,0},{0,5,0},{0,0,1}} will apply to a pixel the sum of the upper left pixel, the lower right pixel and 5 times the central pixel. Then it is divided by div and we add a bias. The result is truncated to fit between 0 (black) and 255 (white). This applies separately to the different channels Red, Green and Blue. There is no way to combine the channels with a normal 1x1, 3x3 or 5x5 filter, but you can do it with an interchannel filter. It works on greyscale images, 24 bits RGB or 32 bits images with alpha channel (the filter is applied to the alpha channel, which may not be a desired result).

Two source files: GraphicFilter.h and GraphicFilter.c with 4 functions in them. Also some specific LabWindows/CVI code to do a custom filter popup (one UIR file CustomFilter.uir, and one C file FilterPopup.c with their respective headers). I did not bother creating a function panel for LabWindows/CVI. Download them all (18Kb). Example of use:

	Png_ReadBitmapFromFile(NULL, &Bits, &RowBytes, &PixDepth, &Width, &Height, SourcePathName); // Reads a PNG file
	Filter3x3(Bits, RowBytes, PixDepth, Width, Height, FilterSharpen); // Apply sharpen filter
	Jpg_SaveBitmapToFile(Bits, RowBytes, PixDepth, Width, Height, DestPathName, Compression));	// Saves to a JPEG file
Category:
ANSI C (Windows, Unix...) for the filters only, graphics.
2001/08/15
First version
2002/03/15
Added simple pixel filters, 5x5 filters and interchannel color filters.
Added popups for custom filters (LabWindows/CVI only).

Simple logging facility

There are many ways to log error messages out of a program, but I couldn't find one that matched my requirements, so I wrote a simple logging facility. The requirements:

2 source files: SimpleLog.h, SimpleLog.c. Example of use:

// print all messages to stderr, no time stamp
SimpleLog_Setup(NULL, NULL, 0, 1, 0, " ");
// Avoid repeating the last message
SimpleLog_Setup("Msg.log", "%H:%M ", 1, 0, 0, ", ");
// Among the last 10 different messages, avoid repeating them at most 20 times
SimpleLog_Setup("Msg.log", "%Y%m%d-%H%M%S ", 10, 20, 0, "\t");
// Among the last 100 different messages, avoid repeating them but print them at least once per minute
SimpleLog_Setup(NULL, "%Y%m%d-%H%M%S ", 100, 0, 60, " ");

// Display everything except debug messages
SimpleLog_FilterLevel(SL_NOTICE);

SimpleLog_Write(SL_WARNING, __func__, "fubar has a value of %d", fubar);
// This won't be printed with the above filter level
SimpleLog_Write(SL_DEBUG, __func__, "expected value was %d", tarfu);

// Optional before quitting the program
SimpleLog_Flush();
Category:
ANSI C (Windows, Unix...)
2009/02/23
First version

Numerical and boolean evaluation

There's sometimes a need to give a user the possibility to input formulas inside a program without recompiling the whole thing, but it's not possible to do this simply in C (there's no magical 'eval' function). So this is a simple postfix evaluator that can use double and booleans present in the program with various formulas. The requirements:

2 source files: PostfixEval.h, PostfixEval.c. Example of use (also see the testcases at the end of the c file):

double A=2, B=3, C=4;
tPE_Variable VarList[10];
tPE_Val Val;
char *Formula="AA BB / sin CC + sqrt";
int NV=0;
VarList[NV].Name="AA";	VarList[NV].pVal=&A;	VarList[NV++].Type=VAL_DOUBLE;
VarList[NV].Name="BB";	VarList[NV].pVal=&B;	VarList[NV++].Type=VAL_DOUBLE;
VarList[NV].Name="CC";	VarList[NV].pVal=&C;	VarList[NV++].Type=VAL_DOUBLE;
Val=PostfixEval_Compute(Formula, VarList, NV, NULL, NULL)
switch (Val.Type) {
	case VAL_ERROR: printf("\n%s gave error %s", Formula, PostfixEval_ErrMsg(Val.Err, NULL)); break;	\
	case VAL_BOOL:  printf("\n%s is %s", Formula, Val.B?"TRUE":"FALSE");  break;	\
	case VAL_DOUBLE:printf("\n%s = %f",  Formula, Val.D); break;	\
	default:		printf("\nError, invalid result type %d", Val.Type); break;	\
}
Category:
ANSI C (Windows, Unix...)
2009/02/23
First version

Support my site: make a donation, buy images, use associate services
Download: Here's a summary of the available downloads: