merge pixmap handling from sampler, material.h and ccdemos's image module to new Pixmap class pyrit
authorRadek Brich <radek.brich@devl.cz>
Mon, 28 Apr 2008 11:44:11 +0200
branchpyrit
changeset 88 f7edb3b90816
parent 87 1081e3dd3f3e
child 89 fcf1487b398b
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
SConstruct
ccdemos/SConscript
ccdemos/image.c
ccdemos/image.h
ccdemos/spheres_shadow.cc
ccdemos/textures.cc
include/material.h
include/pixmap.h
include/sampler.h
src/SConscript
src/pixmap.cc
src/sampler.cc
--- 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;