merge pixmap handling from sampler, material.h and ccdemos's image module to new Pixmap class
add check for PNG library, allow writing PNG file from a Pixmap
simplify demos using new methods from Sampler and Pixmap
--- a/SConstruct	Sun Apr 27 22:55:17 2008 +0200
+++ b/SConstruct	Mon Apr 28 11:44:11 2008 +0200
@@ -48,6 +48,9 @@
 opt.Save('.optioncache', env)
 Help(opt.GenerateHelpText(env))
 
+
+### configure
+
 platform = 'unknown'
 def CheckPlatform(context):
 	global platform
@@ -104,11 +107,9 @@
 conf.CheckGCC()
 conf.CheckIntelC()
 conf.CheckCPUFlags()
-env = conf.Finish()
 
-
-if intelc and env['intelc']:
-	Tool("intelc").generate(env)
+if intelc and conf.env['intelc']:
+	Tool("intelc").generate(conf.env)
 	cc = 'intelc'
 elif gcc:
 	cc = 'gcc'
@@ -119,17 +120,17 @@
 if cc == 'intelc':
 	add_flags += cpuflags_intelc + ' '
 
-if env['precision'] == 'double':
+if conf.env['precision'] == 'double':
 	add_flags += '-DPYRIT_DOUBLE '
 elif cc == 'gcc':
 	add_flags += '-fsingle-precision-constant '
 
-add_flags += env['flags']
+add_flags += conf.env['flags']
 
 if cc == 'intelc':
-	env.Append(CCFLAGS="-O3 -w1 " + add_flags)
+	conf.env.Append(CCFLAGS="-O3 -w1 " + add_flags)
 elif cc == 'gcc':
-	env.Append(CCFLAGS="-O3 -Wall -pipe " + add_flags)
+	conf.env.Append(CCFLAGS="-O3 -Wall -pipe " + add_flags)
 	# CCFLAGS= -fno-strict-aliasing
 else:
 	print "No supported compiler found."
@@ -138,11 +139,19 @@
 print "Using compiler: " + cc
 print "Additional flags: " + add_flags
 
-# pthread
-if env['PLATFORM'] == 'win32':
-	env.Append(LIBS=["pthreadGC2"])
+if conf.CheckLibWithHeader('png', 'png.h', 'C'):
+	conf.env.Append(CCFLAGS='-DHAVE_PNG')
+	conf.env.Append(LIBS=['png'])
+
+if conf.env['PLATFORM'] == 'win32':
+	conf.env.Append(LIBS=["pthreadGC2"])
 else:
-	env.Append(CCFLAGS="-pthread ")
+	conf.env.Append(CCFLAGS="-pthread ")
+
+env = conf.Finish()
+
+
+### build targets
 
 (lib, pymodule) = SConscript('src/SConscript', build_dir='build/lib', duplicate=0, exports='env')
 
--- a/ccdemos/SConscript	Sun Apr 27 22:55:17 2008 +0200
+++ b/ccdemos/SConscript	Mon Apr 28 11:44:11 2008 +0200
@@ -1,18 +1,16 @@
 Import('env lib')
 myenv = env.Clone()
 myenv.Append(CPPPATH = ['.','#include'], LIBPATH='#build/lib')
-myenv.Prepend(LIBS=['pyrit','png'])
+myenv.Prepend(LIBS=['pyrit'])
 
 sdlenv = myenv.Clone()
 sdlenv.ParseConfig('sh sdl-config --cflags --libs')
 
 l = []
-image_obj = myenv.Object('image.c', CC="$CXX")
-l.append( image_obj )
 l.append( sdlenv.Program(['realtime.cc']) )
 l.append( sdlenv.Program(['realtime_bunny.cc']) )
 l.append( sdlenv.Program(['realtime_dragon.cc']) )
-l.append( sdlenv.Program(['spheres_shadow.cc']+image_obj) )
-l.append( sdlenv.Program(['textures.cc']+image_obj) )
+l.append( sdlenv.Program(['spheres_shadow.cc']) )
+l.append( sdlenv.Program(['textures.cc']) )
 
 myenv.Alias('cc-demos', l)
--- a/ccdemos/image.c	Sun Apr 27 22:55:17 2008 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-/* This code is part of RGB Image Library
-   see URL: xxx */
-
-/**************************************************************************
-
-RGB Image Library (rgbimagelib)
-File: image.c
-
-Copyright (c) 2006 Radek Brich
-
-Permission is hereby granted, free of charge, to any person
-obtaining a copy of this software and associated documentation
-files (the "Software"), to deal in the Software without
-restriction, including without limitation the rights to use,
-copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following
-conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
-**************************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <png.h>
-
-#include "image.h"
-
-int new_image(struct image **img, int width, int height, int pixelsize)
-{
-	*img = (struct image *) malloc(sizeof(struct image));
-	(*img)->pixel_size = pixelsize;
-	(*img)->width = width;
-	(*img)->height = height;
-	(*img)->data = (unsigned char *) malloc(width * height * pixelsize);
-	return(0);
-}
-
-void destroy_image(struct image **img)
-{
-	free((*img)->data);
-	free(*img);
-	*img = NULL;
-}
-
-/* funkce pro ulozeni obrazku do PNG souboru (vyuziva knihovnu libpng) */
-int save_png(const char *fname, struct image *img)
-{
-	int y; /* pomocna promenna pro pruchod radku obrazu */
-	FILE *f;
-	png_structp png;   /* PNG data */
-	png_infop pnginfo; /* PNG info */
-	unsigned char *data;
-
-	if ((f = fopen(fname, "wb")) == NULL)
-		return (0);
-
-	png = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
-	if (!png) {
-		fclose(f);
-		return (0);
-	}
-
-	pnginfo = png_create_info_struct(png);
-	if (!pnginfo) {
-		fclose(f);
-		png_destroy_write_struct(&png, 0);
-		return (0);
-	}
-
-	if (setjmp(png_jmpbuf(png))) {
-		fclose(f);
-		png_destroy_info_struct(png, &pnginfo);
-		png_destroy_write_struct(&png, &pnginfo);
-		return (0);
-	}
-
-	/* predat knihovne PNG ukazatel na soubor */
-	png_init_io(png, f);
-
-	/* parametry PNG */
-	png_set_compression_level(png, Z_BEST_COMPRESSION);
-	png_set_IHDR(png, pnginfo, img->width, img->height, 8, PNG_COLOR_TYPE_RGB,
-		PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
-		PNG_FILTER_TYPE_DEFAULT);
-	png_set_sRGB(png, pnginfo, PNG_sRGB_INTENT_PERCEPTUAL);
-	png_set_sRGB_gAMA_and_cHRM(png, pnginfo, PNG_INFO_sRGB);
-
-	/* zapsat hlavicku */
-	png_write_info(png, pnginfo);
-
-	/* zapsat data */
-	data = img->data;
-	for (y = 0; y < img->height; y++, data += img->width * img->pixel_size)
-		png_write_row(png, (png_byte *) data);
-
-	/* ukoncit soubor a uvolnit pomocne struktury */
-	png_write_end(png, pnginfo);
-	png_destroy_info_struct(png, &pnginfo);
-	png_destroy_write_struct(&png, 0);
-
-	fclose(f);
-
-	return (1);
-}
--- a/ccdemos/image.h	Sun Apr 27 22:55:17 2008 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,20 +0,0 @@
-#ifndef IMAGE_H
-#define IMAGE_H
-
-#define IMG_GRAYSCALE	1
-#define IMG_RGB		3
-
-/* raw image */
-struct image {
-	int pixel_size;  /* should be 1 for grayscale and 3 for RGB*/
-	int width;
-	int height;
-	unsigned char *data;
-};
-
-int new_image(struct image **img, int width, int height, int pixelsize);
-void destroy_image(struct image **img);
-
-int save_png(const char *fname, struct image *img);
-
-#endif
--- a/ccdemos/spheres_shadow.cc	Sun Apr 27 22:55:17 2008 +0200
+++ b/ccdemos/spheres_shadow.cc	Mon Apr 28 11:44:11 2008 +0200
@@ -1,7 +1,6 @@
 #include "raytracer.h"
 #include "octree.h"
 
-#include "image.h"
 #include "common_sdl.h"
 
 Camera cam;
@@ -108,24 +107,10 @@
 	if (argc == 2 && !strcmp(argv[1], "-r"))
 	{
 		pyrit_verbosity = 2;
-		Float *fdata = (Float *) malloc(w*h*3*sizeof(Float));
-		DefaultSampler sampler(fdata, w, h);
+		DefaultSampler sampler(w, h);
 		sampler.setOversample(2);
 		rt.setSampler(&sampler);
 		rt.render();
-
-		struct image *img;
-		new_image(&img, w, h, 3);
-
-		Float *fd = fdata;
-		for (unsigned char *cd = img->data; cd != img->data + w*h*3; cd++, fd++) {
-			if (*fd > 1.0)
-				*cd = 255;
-			else
-				*cd = (unsigned char)(*fd * 255.0);
-		}
-		free(fdata);
-		save_png("spheres_shadow.png", img);
-		destroy_image(&img);
+		sampler.getPixmap().writePNG("spheres_shadow.png");
 	}
 }
--- a/ccdemos/textures.cc	Sun Apr 27 22:55:17 2008 +0200
+++ b/ccdemos/textures.cc	Mon Apr 28 11:44:11 2008 +0200
@@ -1,7 +1,6 @@
 #include "raytracer.h"
 #include "octree.h"
 
-#include "image.h"
 #include "common_sdl.h"
 
 Camera cam(Vector3(0.,6.,6.), Vector3(0.,2.,-7.), Vector3(0.,0.,-1.));
@@ -141,26 +140,12 @@
 	if (argc == 2 && !strcmp(argv[1], "-r"))
 	{
 		pyrit_verbosity = 2;
-		Float *fdata = (Float *) malloc(w*h*3*sizeof(Float));
 		rt.ambientOcclusion(300, 5.0, 0.5);
-		DefaultSampler sampler(fdata, w, h);
+		DefaultSampler sampler(w, h);
 		sampler.setOversample(2);
 		sampler.setSubsample(1);
 		rt.setSampler(&sampler);
 		rt.render();
-
-		struct image *img;
-		new_image(&img, w, h, 3);
-
-		Float *fd = fdata;
-		for (unsigned char *cd = img->data; cd != img->data + w*h*3; cd++, fd++) {
-			if (*fd > 1.0)
-				*cd = 255;
-			else
-				*cd = (unsigned char)(*fd * 255.0);
-		}
-		free(fdata);
-		save_png("textures.png", img);
-		destroy_image(&img);
+		sampler.getPixmap().writePNG("textures.png");
 	}
 }
--- a/include/material.h	Sun Apr 27 22:55:17 2008 +0200
+++ b/include/material.h	Mon Apr 28 11:44:11 2008 +0200
@@ -29,6 +29,7 @@
 
 #include "common.h"
 #include "vector.h"
+#include "pixmap.h"
 
 /**
  * perlin noise
@@ -225,24 +226,6 @@
 };
 
 /**
- * pixmap for image texture
- */
-class Pixmap
-{
-	Colour *data;
-	int w,h;
-public:
-	Pixmap(): data(NULL), w(0), h(0) {};
-	Pixmap(Float *adata, int aw, int ah):
-		data((Colour*)(adata)), w(aw), h(ah) {};
-	void setData(Float *adata, int aw, int ah)
-		{ data = (Colour*)adata; w = aw; h = ah; };
-	Colour get(int x, int y) { return data[y*w + x]; };
-	int getWidth() { return w; };
-	int getHeight() { return h; };
-};
-
-/**
  * 2D image texture
  */
 class ImageTexture: public Texture2D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/pixmap.h	Mon Apr 28 11:44:11 2008 +0200
@@ -0,0 +1,63 @@
+/*
+ * pixmap.h: 2D image class
+ *
+ * This file is part of Pyrit Ray Tracer.
+ *
+ * Copyright 2008  Radek Brich
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef PIXMAP_H
+#define PIXMAP_H
+
+#include "common.h"
+#include "vector.h"
+
+/**
+ * 2D pixmap
+ */
+class Pixmap
+{
+	union
+	{
+		Colour *data;
+		Float *fdata;
+	};
+	int w,h;
+	bool refdata;
+public:
+	Pixmap(): data(NULL), w(0), h(0), refdata(true) {};
+	Pixmap(Float *afdata, int aw, int ah):
+		fdata(afdata), w(aw), h(ah), refdata(true) {};
+	Pixmap(int aw, int ah):
+		data(new Colour[aw*ah]), w(aw), h(ah), refdata(false) {};
+	virtual ~Pixmap() { if (!refdata) delete[] data; };
+
+	void setData(Float *afdata, int aw, int ah)
+		{ fdata = afdata; w = aw; h = ah; };
+	Colour get(int x, int y) { return data[y*w + x]; };
+	const int &getWidth() { return w; };
+	const int &getHeight() { return h; };
+	Float*& getFloatData() { return fdata; };
+	unsigned char *getCharData() const;
+	int writePNG(const char *fname) const;
+};
+
+#endif
--- a/include/sampler.h	Sun Apr 27 22:55:17 2008 +0200
+++ b/include/sampler.h	Mon Apr 28 11:44:11 2008 +0200
@@ -29,6 +29,7 @@
 
 #include "common.h"
 #include "vector.h"
+#include "pixmap.h"
 
 using namespace std;
 
@@ -56,19 +57,23 @@
 class Sampler
 {
 protected:
-	Float *buffer;
-	int w,h;
+
+	Pixmap pixmap;
 	bool packetable;
 public:
-	Sampler(Float *abuffer, int &aw, int &ah):
-		buffer(abuffer), w(aw), h(ah), packetable(false) {};
+	Sampler(Float *buffer, const int &w, const int &h):
+		pixmap(buffer, w, h), packetable(false) {};
+	Sampler(const int &w, const int &h):
+		pixmap(w, h), packetable(false) {};
 	virtual ~Sampler() {};
-	void resetBuffer(Float *abuffer, int &aw, int &ah) { buffer = abuffer; w = aw; h = ah; };
+	void resetBuffer(Float *buffer, int &w, int &h)
+		{ pixmap.setData(buffer, w, h); };
 	virtual void init() = 0;
 	virtual int initSampleSet() = 0;
 	virtual bool nextSample(Sample *s) = 0;
 	virtual void saveSample(Sample &samp, Colour &col) = 0;
 	bool packetableSamples() { return packetable; };
+	const Pixmap &getPixmap() { return pixmap; };
 };
 
 /**
@@ -82,8 +87,10 @@
 	int oversample; // 0 = no, 1 = 4x, 2 = 9x, 3 = 16x
 	int sx,sy,osa_samp; // current sample properties
 public:
-	DefaultSampler(Float *abuffer, int &aw, int &ah):
-		Sampler(abuffer, aw, ah), phase(-1), subsample(0), oversample(0) {};
+	DefaultSampler(Float *buffer, const int &w, const int &h):
+		Sampler(buffer, w, h), phase(-1), subsample(0), oversample(0) {};
+	DefaultSampler(const int &w, const int &h):
+		Sampler(w, h), phase(-1), subsample(0), oversample(0) {};
 	void init();
 	int initSampleSet();
 	bool nextSample(Sample *s);
--- a/src/SConscript	Sun Apr 27 22:55:17 2008 +0200
+++ b/src/SConscript	Mon Apr 28 11:44:11 2008 +0200
@@ -18,7 +18,7 @@
 sources = [
 	'raytracer.cc', 'scene.cc', 'shapes.cc', 'sampler.cc',
 	'container.cc', 'kdtree.cc', 'octree.cc', 'material.cc',
-	'serialize.cc']
+	'serialize.cc', 'pixmap.cc']
 
 objs = []
 shared_objs = []
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pixmap.cc	Mon Apr 28 11:44:11 2008 +0200
@@ -0,0 +1,113 @@
+/*
+ * pixmap.cc: 2D image class
+ *
+ * This file is part of Pyrit Ray Tracer.
+ *
+ * Copyright 2008  Radek Brich
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdio.h>
+
+#ifdef HAVE_PNG
+#	include <png.h>
+#endif
+
+#include "pixmap.h"
+
+unsigned char *Pixmap::getCharData() const
+{
+	unsigned char *cdata = new unsigned char[w*h*3];
+	Float *fd = fdata;
+	for (unsigned char *cd = cdata; cd != cdata + w*h*3; cd++, fd++)
+	{
+		if (*fd > 1.0)
+			*cd = 255;
+		else
+			*cd = (unsigned char)(*fd * 255.0);
+	}
+	return cdata;
+}
+
+int Pixmap::writePNG(const char *fname) const
+{
+#ifndef HAVE_PNG
+	return -3;
+#else
+	int y;
+	FILE *f;
+	png_structp png;   /* PNG data */
+	png_infop pnginfo; /* PNG info */
+	unsigned char *cdata, *d;
+
+	if ((f = fopen(fname, "wb")) == NULL)
+		return -1;
+
+	png = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
+	if (!png) {
+		fclose(f);
+		return -2;
+	}
+
+	pnginfo = png_create_info_struct(png);
+	if (!pnginfo) {
+		fclose(f);
+		png_destroy_write_struct(&png, 0);
+		return -2;
+	}
+
+	if (setjmp(png_jmpbuf(png))) {
+		fclose(f);
+		png_destroy_info_struct(png, &pnginfo);
+		png_destroy_write_struct(&png, &pnginfo);
+		return -2;
+	}
+
+	/* predat knihovne PNG ukazatel na soubor */
+	png_init_io(png, f);
+
+	/* parametry PNG */
+	png_set_compression_level(png, Z_BEST_COMPRESSION);
+	png_set_IHDR(png, pnginfo, w, h, 8, PNG_COLOR_TYPE_RGB,
+		PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
+		PNG_FILTER_TYPE_DEFAULT);
+	png_set_sRGB(png, pnginfo, PNG_sRGB_INTENT_PERCEPTUAL);
+	png_set_sRGB_gAMA_and_cHRM(png, pnginfo, PNG_INFO_sRGB);
+
+	/* zapsat hlavicku */
+	png_write_info(png, pnginfo);
+
+	/* zapsat data */
+	d = cdata = getCharData();
+	for (y = 0; y < h; y++, d += w * 3)
+		png_write_row(png, (png_byte *) d);
+
+	/* ukoncit soubor a uvolnit pomocne struktury */
+	png_write_end(png, pnginfo);
+	png_destroy_info_struct(png, &pnginfo);
+	png_destroy_write_struct(&png, 0);
+
+	fclose(f);
+
+	delete[] cdata;
+
+	return 0;
+#endif
+}
--- a/src/sampler.cc	Sun Apr 27 22:55:17 2008 +0200
+++ b/src/sampler.cc	Mon Apr 28 11:44:11 2008 +0200
@@ -39,6 +39,9 @@
 {
 	static const int gridsamples[] = {1,5,9,16};
 	const int samples = gridsamples[oversample];
+	const int &w = pixmap.getWidth(), &h = pixmap.getHeight();
+	Float *&buffer = pixmap.getFloatData();
+
 	if ( phase == 0 )
 	{
 		if (subsample > 1)
@@ -141,6 +144,9 @@
 
 bool DefaultSampler::nextSample(Sample* s)
 {
+	const int &w = pixmap.getWidth(), &h = pixmap.getHeight();
+	Float *&buffer = pixmap.getFloatData();
+
 	if (phase == 1)
 	{
 		// subsampling
@@ -268,7 +274,8 @@
 
 void DefaultSampler::saveSample(Sample &samp, Colour &col)
 {
-	Float *buf = buffer + 3*(samp.sy * w + samp.sx);
+	Float *buf = pixmap.getFloatData()
+		+ 3*(samp.sy * pixmap.getWidth() + samp.sx);
 	if (phase == 2 && oversample)
 	{
 		*(buf+0) += col.r;