Files
secondo/Algebras/Picture/PictureAlgebra_histops.cpp
2026-01-23 17:03:45 +08:00

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;
}