/*
* surf - visualizing algebraic curves and algebraic surfaces
* Copyright (C) 1996-1997 Friedrich-Alexander-Universitaet
* Erlangen-Nuernberg
* 1997-2000 Johannes Gutenberg-Universitaet Mainz
* Authors: Stephan Endrass, Hans Huelf, Ruediger Oertel,
* Kai Schneider, Ralf Schmitt, Johannes Beigel
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <math.h>
#include <stdio.h>
#include "def.h"
#include "float_buffer.h"
#include "Thread.h"
#include "stop.h"
// ----------------------------------------------------------------------------
// --------- constructors for old float_buffer --------------------------------
// ----------------------------------------------------------------------------
float_buffer::float_buffer()
: b( 0 ),
n(0),
width(0),
height(0)
{
}
float_buffer::float_buffer( int w, int h )
: b(new float [w*h] ),
n(w*h),
width(w),
height(h)
{
}
// ----------------------------------------------------------------------------
// ----------- release memory -------------------------------------------------
// ----------------------------------------------------------------------------
float_buffer::~float_buffer()
{
delete [] b;
}
// ----------------------------------------------------------------------------
// ------------ change size of buffer -----------------------------------------
// ----------------------------------------------------------------------------
void float_buffer::Realloc( int w, int h )
{
if (width==w && height == h)
return;
delete [] b;
b = new float [ w * h ];
n = w * h;
width = w;
height = h;
*this=-10.0; //FIXME
}
// ----------------------------------------------------------------------------
// ------------ set the whole buffer equal f ----------------------------------
// ----------------------------------------------------------------------------
float_buffer& float_buffer::operator=( float f )
{
for( int i = 0; i < n; i++ )
b[i] = f;
return *this;
}
// ----------------------------------------------------------------------------
// ------------ set the whole buffer equal zero -------------------------------
// ----------------------------------------------------------------------------
void float_buffer::NullInit()
{
for( int i = 0; i < n; i++ )
b[i] = 0.0;
}
// ----------------------------------------------------------------------------
// ------------ copy from a float buffer with maybe different size ------------
// ----------------------------------------------------------------------------
void float_buffer::Copy( const float_buffer& alt )
{
int xm = min( width, alt.width );
int ym = min( height, alt.height );
for( int y = 0; y < ym; y++ )
for( int x = 0; x < xm; x++ )
b[y*width+x] = alt.Get( x, y );
}
// ----------------------------------------------------------------------------
// ------------ copy one line of a float buffer with maybe different size -----
// ----------------------------------------------------------------------------
void float_buffer::CopyLine( const float_buffer& alt, int src, int dest )
{
if( dest >= 0 && dest < height ) {
int xm = min( width, alt.width );
for( int x = 0; x < xm; x++ )
b[dest*width+x]=alt.Get(x,src);
}
}
// ----------------------------------------------------------------------------
// -------- get 3 by 3 field in a small buffer --------------------------------
// -------- used in enhance edges ---------------------------------------------
// ----------------------------------------------------------------------------
float float_buffer::GetAbsFieldModuloHeight( int x, int y )
{
if( x < 0 || x >= width - 2 || y < 0 )
return 0.0;
int l1 = (y%height) * width + x;
int l2 = ((y+1)%height) * width + x;
int l3 = ((y+2)%height) * width + x;
return ( fabs(b[l1]) + fabs(b[l1+1]) + fabs(b[l1+2]) +
fabs(b[l2]) + fabs(b[l2+1]) + fabs(b[l2+2]) +
fabs(b[l3]) + fabs(b[l3+1]) + fabs(b[l3+2]) );
}
// ----------------------------------------------------------------------------
// ------- perform gamma correction on buffer ---------------------------------
// ----------------------------------------------------------------------------
void float_buffer::CorrectGamma (double gamma)
{
for( int pos = 0; pos < n; pos++ )
b[pos] = pow((double)b[pos], gamma);
}
// ----------------------------------------------------------------------------
// ------- perform edge enhancement on buffer ---------------------------------
// ------- routine fixed ----- uses only a width by 3 temp buffer -------------
// ----------------------------------------------------------------------------
void float_buffer::EnhanceEdges (double alpha)
{
float_buffer buffer( width, 3 );
buffer.Copy( *this );
for( int y = 0; y < height - 2 && !stop; y++ ) {
int pos = y*width;
for( int x = 0; x < width - 2; x++, pos++ ) {
// calculate new value from data in temp buffer
float err = buffer.GetAbsFieldModuloHeight( x, y ) / 9.0;
float result = ( buffer.Get( x+1, (y+1)%3 ) - alpha * err )
/ ( 1.0 - alpha );
// do min and max range clipping
if( result < 0.0 )
b[pos] = 0.0;
else if ( result < 1.0 )
b[pos] = result;
else
b[pos] = 1.0;
}
// insert next line at obsolete line in temp buffer
if( y < height - 3 )
buffer.CopyLine( *this, y+3, y%3 );
}
}
// ----------------------------------------------------------------------------
// ------ do tone scale adjustment --------------------------------------------
// ----------------------------------------------------------------------------
void float_buffer::AdjustToneScale( )
{
float value;
for( int pos = 0; pos < n; pos++ ) {
value = b[pos];
if( value < 0.1 ) {
b[pos] = 0.0;
} else if( value < 0.85 ) {
b[pos] = ( value - 0.1 )/0.8;
} else {
b[pos] = 1.0;
}
}
}
syntax highlighted by Code2HTML, v. 0.9.1