653 lines
17 KiB
C++
653 lines
17 KiB
C++
/*
|
|
//paragraph [1] Title: [{\Large \bf \begin{center}] [\end{center}}]
|
|
//paragraph [10] Footnote: [{\footnote{] [}}]
|
|
//[ue] [\"{u}]
|
|
//[ae] [\"{a}]
|
|
//[TOC] [\tableofcontents]
|
|
|
|
[1] Picture Algebra: Class Definitions
|
|
|
|
Dezember 2004 Christian Bohnbuck, Uwe Hartmann, Marion Langen and Holger
|
|
M[ue]nx during Prof. G[ue]ting's practical course
|
|
'Extensible Database Systems' at Fernuniversit[ae]t Hagen.
|
|
|
|
December 2005, Victor Almeida deleted the deprecated algebra levels
|
|
(~executable~, ~descriptive~, and ~hibrid~). Only the executable
|
|
level remains. Models are also removed from type constructors.
|
|
|
|
[TOC]
|
|
|
|
1 Introduction
|
|
|
|
See the documentation of ~PictureAlgebra.h~ for a general introduction to
|
|
the Picture algebra.
|
|
|
|
This module contains SECONDO operators on ~picture~, which deal with
|
|
a ~histogram~ object.
|
|
|
|
2 Includes and other preparations
|
|
|
|
*/
|
|
|
|
|
|
#include "Algebra.h"
|
|
#include "QueryProcessor.h"
|
|
#include "StandardTypes.h"
|
|
#include "NestedList.h"
|
|
#include "StringUtils.h"
|
|
|
|
#include "PictureAlgebra.h"
|
|
|
|
using namespace std;
|
|
|
|
extern NestedList* nl;
|
|
extern QueryProcessor *qp;
|
|
|
|
|
|
/*
|
|
|
|
3 Operators on ~picture~
|
|
|
|
3.1 Operator ~Colordist~
|
|
|
|
The function ~Colordist~ creates a ~histogram~-object and returns
|
|
this. The calling function should not forget to delete the ~histogram~-object.
|
|
|
|
*/
|
|
|
|
Histogram* Picture::Colordist(HistogramChannel channel) {
|
|
if (PA_DEBUG) cerr << "Picture::Colordist() called" << endl;
|
|
|
|
//
|
|
// Create a histogram of this picture.
|
|
// Don't forget to delete the object !
|
|
//
|
|
|
|
Histogram* h = new Histogram();
|
|
if (( channel < 0 ) || ( channel > 3 ))
|
|
{
|
|
h->SetDefined( false );
|
|
}
|
|
else
|
|
{
|
|
h->CopyFrom( (const Attribute *) &this->histogram[ channel ] );
|
|
}
|
|
|
|
return h;
|
|
}
|
|
|
|
/*
|
|
|
|
3.2 Operator ~Equals~
|
|
|
|
The ~Equals~-function checks, whether two pictures are equal. Therefore,
|
|
it creates for each picture a histogram and compares the datas of
|
|
these objects.
|
|
|
|
*/
|
|
|
|
bool Picture::Equals(Picture* pic, int n, int p, bool &valid, double& diff) {
|
|
//if (PA_DEBUG)
|
|
cerr << "Picture::Equals() called. n=" << n << ", p=" << p << endl;
|
|
|
|
//
|
|
// Create two histograms and call the equal-function for
|
|
// histograms.
|
|
//
|
|
Histogram* h1 = &this->histogram[HC_BRIGHTNESS];
|
|
Histogram* h2 = &pic->histogram[HC_BRIGHTNESS];
|
|
|
|
//cerr << "Picture::Equals() this="
|
|
// << (int) this
|
|
// << " h1="
|
|
// << (int) h1
|
|
// << " h2="
|
|
// << (int) h2
|
|
// << endl;
|
|
|
|
bool rc = h1->Equals( h2, n, p, valid, diff);
|
|
//
|
|
// Delete everything!
|
|
//
|
|
// Nope: h1 and h2 are just pointers into the attribute histogram,
|
|
// therefore the referenced memory must not be deleted...
|
|
//delete h1;
|
|
//delete h2;
|
|
|
|
cerr << "Picture::Equals() done" << endl;
|
|
return( rc );
|
|
}
|
|
|
|
/*
|
|
|
|
3.2 Operator ~Contains~
|
|
|
|
The ~Contains~-function checks, whether a picture is contained in another one. Therefore,
|
|
it compares for each picture all the color-histogram and multiplies the relative numbers
|
|
by the number of pictures.
|
|
|
|
*/
|
|
bool Picture::Contains(Picture* pic) {
|
|
|
|
// calculate number of pixels
|
|
int pixel_this = GetWidth() * GetHeight();
|
|
int pixel_pic = pic->GetWidth() * pic->GetHeight();
|
|
|
|
// compare red histograms
|
|
Histogram* h_this = &this->histogram[HC_RED];
|
|
Histogram* h_pic = &pic->histogram[HC_RED];
|
|
if ( !h_this->Contains(pixel_this, h_pic, pixel_pic) ) {
|
|
return false;
|
|
}
|
|
|
|
// compare green histograms
|
|
h_this = &this->histogram[HC_GREEN];
|
|
h_pic = &pic->histogram[HC_GREEN];
|
|
if ( !h_this->Contains(pixel_this, h_pic, pixel_pic) ) {
|
|
return false;
|
|
}
|
|
|
|
// compare blue histograms
|
|
h_this = &this->histogram[HC_BLUE];
|
|
h_pic = &pic->histogram[HC_BLUE];
|
|
if ( !h_this->Contains(pixel_this, h_pic, pixel_pic) ) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
|
|
3.3 Operator ~Like~
|
|
|
|
The function ~Like~ checks, whether the brightness of the picture
|
|
in the interval of [l,u] differs p+-t percent.
|
|
|
|
p main percentage
|
|
t +- relative percentage
|
|
l minimal range of interval
|
|
u maximal range of interval
|
|
|
|
~Like~ returns true, if the picture fulfils the specified
|
|
parameters. Otherwise it returns false.
|
|
|
|
*/
|
|
|
|
bool Picture::Like(int p, int t, int l, int u, bool& valid) {
|
|
if (PA_DEBUG) cerr << "Picture::Like() called" << endl;
|
|
|
|
//
|
|
// Create a histogram and check the brightness in the
|
|
// interval [l, u].
|
|
//
|
|
Histogram* h = &this->histogram[ HC_BRIGHTNESS ];
|
|
|
|
bool rc = h->Like( p, t, l, u, valid );
|
|
if (PA_DEBUG)
|
|
cerr << "This picture " << ((rc)?"fulfils": "does not fulfil")
|
|
<< " the specified parameter." << endl;
|
|
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
|
|
3.4 Operator ~Like~
|
|
|
|
The function ~Like~ checks, whether the brightness of the picture
|
|
in the interval of [l,u] differs p+-t percent.
|
|
|
|
p main percentage
|
|
t +- relative percentage
|
|
l minimal range of interval
|
|
u maximal range of interval
|
|
|
|
~Like~ returns true, if the picture fulfils the specified
|
|
parameters. Otherwise it returns false.
|
|
Please notice thate the specified parameters ~p~ and ~t~ are type float.
|
|
|
|
*/
|
|
|
|
bool Picture::Like(double p, double t, int l, int u, bool& valid) {
|
|
if (PA_DEBUG) cerr << "Picture::Like() called" << endl;
|
|
|
|
//
|
|
// Create a histogram and check the brightness in the
|
|
// interval [l, u].
|
|
//
|
|
Histogram* h = &this->histogram[ HC_BRIGHTNESS ];
|
|
|
|
bool rc = h->Like( p, t, l, u, valid );
|
|
if (PA_DEBUG)
|
|
cerr << "This picture " << ((rc)?"fulfils": "does not fulfil")
|
|
<< " the specified parameter." << endl;
|
|
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
|
|
4 Type mapping fucntions
|
|
|
|
These functions check whether the specified nested list parameter structure
|
|
is in correct type of parameters for the operatoris ~Colordist~, ~Equals~
|
|
and ~Like~.
|
|
|
|
*/
|
|
|
|
ListExpr PictureColordistTypeMap(ListExpr args) {
|
|
if (PA_DEBUG) cerr << "PictureColordistTypeMap() called" << endl;
|
|
|
|
ListExpr arg1, arg2;
|
|
|
|
if ( nl->ListLength(args) != 2 )
|
|
{
|
|
ErrorReporter::ReportError(
|
|
"expected four arguments but received "
|
|
+stringutils::int2str(nl->ListLength(args)));
|
|
|
|
return( nl->SymbolAtom(Symbol::TYPEERROR()));
|
|
}
|
|
|
|
//
|
|
// Got 2 different arguments ( picture, int )
|
|
//
|
|
arg1 = nl->First(args);
|
|
arg2 = nl->Second(args);
|
|
|
|
if ( ! nl->IsEqual(arg1, Picture::BasicType()))
|
|
{
|
|
ErrorReporter::ReportError(
|
|
"expected 'picture' as first argument but received '"
|
|
+nl->ToString(arg1)
|
|
+"'");
|
|
|
|
return (nl->SymbolAtom(Symbol::TYPEERROR()));
|
|
}
|
|
if ( ! nl->IsEqual(arg2, CcInt::BasicType()))
|
|
{
|
|
ErrorReporter::ReportError(
|
|
"expected 'int' as second argument but received '"
|
|
+nl->ToString(arg2)
|
|
+"'");
|
|
|
|
return (nl->SymbolAtom(Symbol::TYPEERROR()));
|
|
}
|
|
|
|
return( nl->SymbolAtom(Histogram::BasicType()));
|
|
}
|
|
|
|
ListExpr PictureEqualsTypeMap(ListExpr args) {
|
|
if (PA_DEBUG) cerr << "PictureEqualsTypeMap() called" << endl;
|
|
|
|
ListExpr arg1, arg2, arg3, arg4;
|
|
|
|
if ( nl->ListLength(args) != 4 )
|
|
{
|
|
ErrorReporter::ReportError(
|
|
"expected four arguments but received "
|
|
+stringutils::int2str(nl->ListLength(args)));
|
|
|
|
return( nl->SymbolAtom(Symbol::TYPEERROR()));
|
|
}
|
|
|
|
//
|
|
// Got 4 different arguments ( picture, picture, int, int )
|
|
//
|
|
arg1 = nl->First(args);
|
|
arg2 = nl->Second(args);
|
|
arg3 = nl->Third(args);
|
|
arg4 = nl->Fourth(args);
|
|
|
|
if ( ! nl->IsEqual(arg1, Picture::BasicType()) )
|
|
{
|
|
ErrorReporter::ReportError(
|
|
"expected 'picture' as first argument but received '"
|
|
+nl->ToString(arg1)
|
|
+"'");
|
|
|
|
return (nl->SymbolAtom(Symbol::TYPEERROR()));
|
|
}
|
|
if ( ! nl->IsEqual(arg2, Picture::BasicType()))
|
|
{
|
|
ErrorReporter::ReportError(
|
|
"expected 'picture' as second argument but received '"
|
|
+nl->ToString(arg2)
|
|
+"'");
|
|
|
|
return (nl->SymbolAtom(Symbol::TYPEERROR()));
|
|
}
|
|
if ( ! nl->IsEqual(arg3, CcInt::BasicType()))
|
|
{
|
|
ErrorReporter::ReportError(
|
|
"expected 'int' as third argument but received '"
|
|
+nl->ToString(arg3)
|
|
+"'");
|
|
|
|
return (nl->SymbolAtom(Symbol::TYPEERROR()));
|
|
}
|
|
if ( ! nl->IsEqual(arg4, CcInt::BasicType() ))
|
|
{
|
|
ErrorReporter::ReportError(
|
|
"expected 'int' as fourth argument but received '"
|
|
+nl->ToString(arg4)
|
|
+"'");
|
|
|
|
return (nl->SymbolAtom(Symbol::TYPEERROR()));
|
|
}
|
|
|
|
return( nl->SymbolAtom(CcReal::BasicType()));
|
|
}
|
|
|
|
ListExpr PictureLikeTypeMap(ListExpr args) {
|
|
if (PA_DEBUG) cerr << "PictureLikeTypeMap() called" << endl;
|
|
|
|
ListExpr arg1, arg2, arg3, arg4, arg5;
|
|
|
|
if ( nl->ListLength(args) != 5 )
|
|
{
|
|
ErrorReporter::ReportError(
|
|
"expected five arguments but received "
|
|
+stringutils::int2str(nl->ListLength(args)));
|
|
|
|
return( nl->SymbolAtom(Symbol::TYPEERROR()));
|
|
}
|
|
|
|
//
|
|
// Got 5 different arguments ( picture, int, int, int, int )
|
|
//
|
|
arg1 = nl->First(args);
|
|
arg2 = nl->Second(args);
|
|
arg3 = nl->Third(args);
|
|
arg4 = nl->Fourth(args);
|
|
arg5 = nl->Fifth(args);
|
|
|
|
if ( ! nl->IsEqual(arg1, Picture::BasicType()))
|
|
{
|
|
ErrorReporter::ReportError(
|
|
"expected 'picture' as first argument but received '"
|
|
+nl->ToString(arg1)
|
|
+"'");
|
|
|
|
return (nl->SymbolAtom(Symbol::TYPEERROR()));
|
|
}
|
|
if ( ! nl->IsEqual(arg2, CcInt::BasicType()) &&
|
|
! nl->IsEqual(arg2, CcReal::BasicType() ))
|
|
{
|
|
ErrorReporter::ReportError(
|
|
"expected 'int' or 'real' as second argument but received '"
|
|
+nl->ToString(arg2)
|
|
+"'");
|
|
|
|
return (nl->SymbolAtom(Symbol::TYPEERROR()));
|
|
}
|
|
if ( ! nl->IsEqual(arg3, CcInt::BasicType() ) &&
|
|
! nl->IsEqual(arg3, CcReal::BasicType() ))
|
|
{
|
|
ErrorReporter::ReportError(
|
|
"expected 'int' or 'real' as third argument but received '"
|
|
+nl->ToString(arg3)
|
|
+"'");
|
|
|
|
return (nl->SymbolAtom(Symbol::TYPEERROR()));
|
|
}
|
|
if ( ! nl->IsEqual(arg4, CcInt::BasicType() ) )
|
|
{
|
|
ErrorReporter::ReportError(
|
|
"expected 'int' as fourth argument but received '"
|
|
+nl->ToString(arg4)
|
|
+"'");
|
|
|
|
return (nl->SymbolAtom(Symbol::TYPEERROR()));
|
|
}
|
|
if ( ! nl->IsEqual(arg5, CcInt::BasicType() ) )
|
|
{
|
|
ErrorReporter::ReportError(
|
|
"expected 'int' as fifth argument but received '"
|
|
+nl->ToString(arg5)
|
|
+"'");
|
|
|
|
return (nl->SymbolAtom(Symbol::TYPEERROR()));
|
|
}
|
|
if ( ! nl->Equal(arg2, arg3) )
|
|
{
|
|
ErrorReporter::ReportError(
|
|
"second and third argument must have same type but received '"
|
|
+nl->ToString(arg2)
|
|
+"' and '"
|
|
+nl->ToString(arg3)
|
|
+"'");
|
|
|
|
return (nl->SymbolAtom(Symbol::TYPEERROR()));
|
|
}
|
|
|
|
return( nl->SymbolAtom(CcBool::BasicType()));
|
|
}
|
|
|
|
/*
|
|
|
|
5 Type mapping functions
|
|
|
|
The following functions are the ~Value Mapping~ functions for the operators
|
|
~Colordist~, ~Equals~ and ~Like~.
|
|
|
|
*/
|
|
|
|
int PictureColordistValueMap(Word* args,
|
|
Word& result,
|
|
int message,
|
|
Word& local,
|
|
Supplier s) {
|
|
if (PA_DEBUG) cerr << "PictureColordistValueMap() called" << endl;
|
|
|
|
Picture* pic;
|
|
CcInt* channel;
|
|
|
|
pic = ((Picture*) args[0].addr);
|
|
channel = ((CcInt*) args[1].addr);
|
|
|
|
result = qp->ResultStorage(s);
|
|
|
|
Histogram* res = ((Histogram *)result.addr);
|
|
|
|
|
|
//
|
|
// I need at least a defined picture. Other parameters are
|
|
// checked in function ~Colordist~.
|
|
//
|
|
if ( pic->IsDefined() )
|
|
{
|
|
Histogram* hist = pic->Colordist(
|
|
HistogramChannel(channel->GetIntval()));
|
|
res->CopyFrom( (const Attribute *) hist);
|
|
delete hist;
|
|
}
|
|
else
|
|
{
|
|
cerr << endl << endl
|
|
<< "The specified picture is not defined."
|
|
<< endl << endl;
|
|
|
|
res->SetDefined( false );
|
|
}
|
|
return( 0 );
|
|
}
|
|
|
|
int PictureEqualsValueMap(Word* args,
|
|
Word& result,
|
|
int message,
|
|
Word& local,
|
|
Supplier s) {
|
|
if (PA_DEBUG) cerr << "PictureEqualsValueMap() called" << endl;
|
|
|
|
Picture* pic1;
|
|
Picture* pic2;
|
|
CcInt* numberValue;
|
|
CcInt* averageValue;
|
|
|
|
pic1 = ((Picture*) args[0].addr);
|
|
pic2 = ((Picture*) args[1].addr);
|
|
numberValue = ((CcInt *) args[2].addr);
|
|
averageValue = ((CcInt *) args[3].addr);
|
|
|
|
result = qp->ResultStorage(s);
|
|
|
|
if ( pic1->IsDefined() && pic2->IsDefined() )
|
|
{
|
|
bool valid = false;
|
|
double diff = 0;
|
|
pic1->Equals( pic2, numberValue->GetIntval(),
|
|
averageValue->GetIntval(), valid, diff );
|
|
|
|
((CcReal*)result.addr)->Set( valid, diff );
|
|
}
|
|
else
|
|
{
|
|
cerr << endl << endl
|
|
<< "At least one of the specified picture is not defined."
|
|
<< endl << endl;
|
|
|
|
((CcReal*)result.addr)->Set(false, false);
|
|
}
|
|
|
|
return( 0 );
|
|
}
|
|
|
|
int PictureContainsValueMap(Word* args,
|
|
Word& result,
|
|
int message,
|
|
Word& local,
|
|
Supplier s) {
|
|
if (PA_DEBUG) cerr << "PictureContainsValueMap() called" << endl;
|
|
|
|
Picture* pic1 = ((Picture*) args[0].addr);
|
|
Picture* pic2 = ((Picture*) args[1].addr);
|
|
|
|
result = qp->ResultStorage(s);
|
|
|
|
if ( pic1->IsDefined() && pic2->IsDefined() )
|
|
{
|
|
bool isInside = pic1->Contains( pic2 );
|
|
((CcBool*)result.addr)->Set( true, isInside );
|
|
}
|
|
else
|
|
{
|
|
cerr << endl << endl
|
|
<< "At least one of the specified picture is not defined."
|
|
<< endl << endl;
|
|
|
|
((CcBool*)result.addr)->Set(false, false);
|
|
}
|
|
|
|
return( 0 );
|
|
}
|
|
|
|
|
|
static int PictureLikeValueMap_int(Word* args,
|
|
Word& result,
|
|
int message,
|
|
Word& local,
|
|
Supplier s) {
|
|
if (PA_DEBUG) cerr << "PictureLikeValueMap_int() called" << endl;
|
|
|
|
Picture* pic;
|
|
CcInt* percentage;
|
|
CcInt* delta;
|
|
CcInt* minInterval;
|
|
CcInt* maxInterval;
|
|
|
|
pic = ((Picture*) args[0].addr);
|
|
percentage = ((CcInt *) args[1].addr);
|
|
delta = ((CcInt *) args[2].addr);
|
|
minInterval = ((CcInt *) args[3].addr);
|
|
maxInterval = ((CcInt *) args[4].addr);
|
|
|
|
result = qp->ResultStorage(s);
|
|
|
|
if ( pic->IsDefined() )
|
|
{
|
|
bool valid;
|
|
bool rc = pic->Like( percentage->GetIntval(), delta->GetIntval(),
|
|
minInterval->GetIntval(), maxInterval->GetIntval(), valid);
|
|
|
|
((CcBool*)result.addr)->Set( valid, rc );
|
|
}
|
|
else
|
|
{
|
|
cerr << endl << endl
|
|
<< "The specified picture is not defined"
|
|
<< endl << endl;
|
|
((CcBool*)result.addr)->Set(false, false);
|
|
}
|
|
|
|
return( 0 );
|
|
}
|
|
|
|
static int PictureLikeValueMap_real(Word* args,
|
|
Word& result,
|
|
int message,
|
|
Word& local,
|
|
Supplier s) {
|
|
if (PA_DEBUG) cerr << "PictureLikeValueMap_real() called" << endl;
|
|
|
|
Picture* pic;
|
|
CcReal* percentage;
|
|
CcReal* delta;
|
|
CcInt* minInterval;
|
|
CcInt* maxInterval;
|
|
|
|
pic = ((Picture*) args[0].addr);
|
|
percentage = ((CcReal *) args[1].addr);
|
|
delta = ((CcReal *) args[2].addr);
|
|
minInterval = ((CcInt *) args[3].addr);
|
|
maxInterval = ((CcInt *) args[4].addr);
|
|
|
|
result = qp->ResultStorage(s);
|
|
|
|
if ( pic->IsDefined() )
|
|
{
|
|
bool valid;
|
|
bool rc = pic->Like( percentage->GetRealval(),
|
|
delta->GetRealval(),
|
|
minInterval->GetIntval(),
|
|
maxInterval->GetIntval(), valid );
|
|
|
|
((CcBool*)result.addr)->Set( valid, rc );
|
|
}
|
|
else
|
|
{
|
|
cerr << endl << endl
|
|
<< "The specified picture is not defined"
|
|
<< endl << endl;
|
|
((CcBool*)result.addr)->Set(false, false);
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
ValueMapping pictureLikeValueMap[] = {
|
|
PictureLikeValueMap_int,
|
|
PictureLikeValueMap_real
|
|
};
|
|
|
|
/*
|
|
|
|
6 Select function
|
|
|
|
This function is necessary because the ~Like~ operator is overloaded.
|
|
|
|
*/
|
|
|
|
int PictureLikeSelect(ListExpr args) {
|
|
if (PA_DEBUG) cerr << "PictureLikeSelect() called" << endl;
|
|
|
|
// It is sufficient to check second parameter because type mapping
|
|
// function already assured that third parameter has same type as
|
|
// second parameter.
|
|
|
|
ListExpr arg2 = nl->Second(args);
|
|
|
|
return nl->IsEqual(arg2, CcInt::BasicType() ) ? 0 : 1;
|
|
}
|