--- a/src/sampler.cc Mon Apr 21 19:35:27 2008 +0200
+++ b/src/sampler.cc Tue Apr 22 13:33:12 2008 +0200
@@ -40,91 +40,222 @@
const int samples = gridsamples[oversample];
if ( phase == 0 )
{
- phase++;
- sx = -1;
- return w*h*samples;
+ if (subsample > 1)
+ {
+ phase = 1;
+ sx = -1;
+ return (w/subsample+1)*(h/subsample+1);
+ }
+ else
+ {
+ phase = 2;
+ sx = -1;
+ return w*h*samples;
+ }
}
- else if ( phase == 1 && oversample )
+ if ( phase == 1 )
{
- phase = -1;
+ // finalize subsampling
+ const Float subsample2 = 1.0/(subsample*subsample);
+ int num_samples = 0;
+ Colour ic;
+ phase = 2;
+ sx = -1;
+ for (int y = 0; y < h/subsample; y++)
+ for (int x = 0; x < w/subsample; x++)
+ {
+ int x1 = x*subsample;
+ int y1 = y*subsample;
+ int x2 = (x+1)*subsample;
+ int y2 = (y+1)*subsample;
+ if (x2 > w-1) x2 = w-1;
+ if (y2 > h-1) y2 = h-1;
+ if (x1 == x2 || y1 == y2)
+ continue;
+ Float *p;
+ p = buffer + 3*(y1*w + x1);
+ Colour c1(*p, *(p+1), *(p+2));
+ p = buffer + 3*(y1*w + x2);
+ Colour c2(*p, *(p+1), *(p+2));
+ p = buffer + 3*(y2*w + x1);
+ Colour c3(*p, *(p+1), *(p+2));
+ p = buffer + 3*(y2*w + x2);
+ Colour c4(*p, *(p+1), *(p+2));
+ Float m = (c1-c2).mag2();
+ m = max(m, (c2-c3).mag2());
+ m = max(m, (c3-c4).mag2());
+ m = max(m, (c4-c1).mag2());
+ if (m < 0.002)
+ {
+ // interpolate
+ for (int i = 0; i < subsample; i++)
+ for (int j = 0; j < subsample; j++)
+ {
+ ic = c1*(subsample-i)*(subsample-j)*subsample2
+ + c2*(i)*(subsample-j)*subsample2
+ + c3*(subsample-i)*(j)*subsample2
+ + c4*(i)*(j)*subsample2;
+ p = buffer + 3*((y1+j)*w + x1+i);
+ *(p + 0) = ic.r;
+ *(p + 1) = oversample ? -ic.g : ic.g;
+ *(p + 2) = ic.b;
+ }
+ }
+ else
+ {
+ // mark as to be computed
+ num_samples += subsample * subsample;
+ for (int i = 0; i < subsample; i++)
+ for (int j = 0; j < subsample; j++)
+ if (oversample || i != 0 || j != 0)
+ *(buffer + 3*((y1+j)*w + x1+i)) = -1.;
+ }
+ }
+ return num_samples;
+ }
+ if ( phase == 2 && oversample )
+ {
+ // finalize oversampling
Float *buf;
- for (buf = buffer; buf != buffer + w*h*3; buf++)
- *buf = *buf * (1.0/samples);
- return 0;
+ if (subsample > 1)
+ for (buf = buffer; buf != buffer + w*h*3; buf += 3)
+ if (*(buf+1) < 0)
+ {
+ // interpolated
+ *(buf+1) = -*(buf+1);
+ }
+ else
+ {
+ *buf = *buf * (1.0/samples);
+ *(buf+1) = *(buf+1) * (1.0/samples);
+ *(buf+2) = *(buf+2) * (1.0/samples);
+ }
+ else
+ for (buf = buffer; buf != buffer + w*h*3; buf++)
+ *buf = *buf * (1.0/samples);
}
- else
- {
- phase = -1;
- return 0;
- }
+ phase = -1;
+ return 0;
}
bool DefaultSampler::nextSample(Sample* s)
{
- /* grid oversampling */
- static const int gridsamples[] = {1,5,9,16};
- static const Float osa5x[] = {0.0, -0.4, +0.4, +0.4, -0.4};
- static const Float osa5y[] = {0.0, -0.4, -0.4, +0.4, +0.4};
- static const Float osa9x[] = {-0.34, 0.00, +0.34,
- -0.34, 0.00, +0.34, -0.34, 0.00, +0.34};
- static const Float osa9y[] = {-0.34, -0.34, -0.34,
- 0.00, 0.00, 0.00, +0.34, +0.34, +0.34};
- static const Float osa16x[] = {-0.375, -0.125, +0.125, +0.375,
- -0.375, -0.125, +0.125, +0.375, -0.375, -0.125, +0.125, +0.375,
- -0.375, -0.125, +0.125, +0.375};
- static const Float osa16y[] = {-0.375, -0.375, -0.375, -0.375,
- -0.125, -0.125, -0.125, -0.125, +0.125, +0.125, +0.125, +0.125,
- +0.375, +0.375, +0.375, +0.375};
- static const Float *osaSx[] = {NULL, osa5x, osa9x, osa16x};
- static const Float *osaSy[] = {NULL, osa5y, osa9y, osa16y};
- const int samples = gridsamples[oversample];
- const Float *osax = osaSx[oversample];
- const Float *osay = osaSy[oversample];
-
- if (sx < 0)
+ if (phase == 1)
{
- // first sample
- s->x = -(Float)w/h/2.0;
- s->y = -0.5;
- sx = 0;
- sy = 0;
- osa_samp = 0;
- }
- else
- {
- osa_samp++;
-
- if (oversample && oversample <= 3 && osa_samp < samples)
+ // subsampling
+ if (sx < 0)
{
- s->x = osax[osa_samp]/h + (Float)sx/h - (Float)w/h/2.0;
- s->y = osay[osa_samp]/h + (Float)sy/h - 0.5;
+ // first sample
+ s->x = -(Float)w/h/2.0;
+ s->y = -0.5;
+ sx = 0;
+ sy = 0;
+ osa_samp = 0;
}
else
{
- sx++;
- if (sx >= w)
+ if (sx == w-1)
{
+ if (sy == h-1)
+ return false;
+ sy += subsample;
+ if (sy > h-1)
+ sy = h-1;
sx = 0;
- sy++;
}
-
- if (sy >= h)
- return false;
+ else
+ {
+ sx += subsample;
+ if (sx > w-1)
+ sx = w-1;
+ }
s->x = (Float)sx/h - (Float)w/h/2.0;
s->y = (Float)sy/h - 0.5;
- osa_samp = 0;
}
}
-
- if (osa_samp == 0 && oversample && oversample <= 3)
+ else if (phase == 2)
{
- s->x += osax[0]/h;
- s->y += osay[0]/h;
- Float *buf = buffer + 3*(sy*w + sx);
- *(buf++) = 0;
- *(buf++) = 0;
- *(buf++) = 0;
+ /* grid oversampling */
+ static const int gridsamples[] = {1,5,9,16};
+ static const Float osa5x[] = {0.0, -0.4, +0.4, +0.4, -0.4};
+ static const Float osa5y[] = {0.0, -0.4, -0.4, +0.4, +0.4};
+ static const Float osa9x[] = {-0.34, 0.00, +0.34,
+ -0.34, 0.00, +0.34, -0.34, 0.00, +0.34};
+ static const Float osa9y[] = {-0.34, -0.34, -0.34,
+ 0.00, 0.00, 0.00, +0.34, +0.34, +0.34};
+ static const Float osa16x[] = {-0.375, -0.125, +0.125, +0.375,
+ -0.375, -0.125, +0.125, +0.375, -0.375, -0.125, +0.125, +0.375,
+ -0.375, -0.125, +0.125, +0.375};
+ static const Float osa16y[] = {-0.375, -0.375, -0.375, -0.375,
+ -0.125, -0.125, -0.125, -0.125, +0.125, +0.125, +0.125, +0.125,
+ +0.375, +0.375, +0.375, +0.375};
+ static const Float *osaSx[] = {NULL, osa5x, osa9x, osa16x};
+ static const Float *osaSy[] = {NULL, osa5y, osa9y, osa16y};
+ const int samples = gridsamples[oversample];
+ const Float *osax = osaSx[oversample];
+ const Float *osay = osaSy[oversample];
+
+ if (sx < 0)
+ {
+ // first sample
+ s->x = -(Float)w/h/2.0;
+ s->y = -0.5;
+ sx = 0;
+ sy = 0;
+ osa_samp = 0;
+ }
+ else
+ {
+ osa_samp++;
+
+ if (oversample && oversample <= 3 && osa_samp < samples)
+ {
+ s->x = osax[osa_samp]/h + (Float)sx/h - (Float)w/h/2.0;
+ s->y = osay[osa_samp]/h + (Float)sy/h - 0.5;
+ }
+ else
+ {
+ sx++;
+ if (sx >= w)
+ {
+ sx = 0;
+ sy++;
+ }
+ if (sy >= h)
+ return false;
+
+ if (subsample > 1)
+ {
+ // find next not interpolated pixel
+ while ( *(buffer + 3*(sy*w + sx)) >= 0. )
+ {
+ sx++;
+ if (sx >= w)
+ {
+ sx = 0;
+ sy++;
+ }
+ if (sy >= h)
+ return false;
+ }
+ }
+
+ s->x = (Float)sx/h - (Float)w/h/2.0;
+ s->y = (Float)sy/h - 0.5;
+ osa_samp = 0;
+ }
+ }
+
+ if (osa_samp == 0 && oversample && oversample <= 3)
+ {
+ s->x += osax[0]/h;
+ s->y += osay[0]/h;
+ Float *buf = buffer + 3*(sy*w + sx);
+ *(buf++) = 0;
+ *(buf++) = 0;
+ *(buf++) = 0;
+ }
}
s->sx = sx;
@@ -137,7 +268,7 @@
void DefaultSampler::saveSample(Sample &samp, Colour &col)
{
Float *buf = buffer + 3*(samp.sy * w + samp.sx);
- if (oversample)
+ if (phase == 2 && oversample)
{
*(buf+0) += col.r;
*(buf+1) += col.g;