```// Copyright (C) 2009  Davis E. King (davis@dlib.net)
#ifndef DLIB_INTEGRAL_IMAGE
#define DLIB_INTEGRAL_IMAGE

#include "integral_image_abstract.h"

#include "../algs.h"
#include "../assert.h"
#include "../geometry.h"
#include "../array2d.h"
#include "../matrix.h"
#include "../pixel.h"
#include "../noncopyable.h"

namespace dlib
{

// ----------------------------------------------------------------------------------------

template <
typename T
>
class integral_image_generic : noncopyable
{
public:
typedef T value_type;

long nr() const { return int_img.nr(); }
long nc() const { return int_img.nc(); }

template <typename image_type>
const image_type& img_
)
{
const_image_view<image_type> img(img_);
T pixel;
int_img.set_size(img.nr(), img.nc());

// compute the first row of the integral image
T temp = 0;
for (long c = 0; c < img.nc(); ++c)
{
assign_pixel(pixel, img[0][c]);
temp += pixel;
int_img[0][c] = temp;
}

// now compute the rest of the integral image
for (long r = 1; r < img.nr(); ++r)
{
temp = 0;
for (long c = 0; c < img.nc(); ++c)
{
assign_pixel(pixel, img[r][c]);
temp += pixel;
int_img[r][c] = temp + int_img[r-1][c];
}
}

}

value_type get_sum_of_area (
const rectangle& rect
) const
{
DLIB_ASSERT(get_rect(*this).contains(rect) == true && rect.is_empty() == false,
"\tvalue_type get_sum_of_area(rect)"
<< "\n\tYou have given a rectangle that goes outside the image"
<< "\n\tthis:            " << this
<< "\n\trect.is_empty(): " << rect.is_empty()
<< "\n\trect:            " << rect
<< "\n\tget_rect(*this): " << get_rect(*this)
);

T top_left = 0, top_right = 0, bottom_left = 0, bottom_right = 0;

bottom_right = int_img[rect.bottom()][rect.right()];
if (rect.left()-1 >= 0 && rect.top()-1 >= 0)
{
top_left = int_img[rect.top()-1][rect.left()-1];
bottom_left = int_img[rect.bottom()][rect.left()-1];
top_right = int_img[rect.top()-1][rect.right()];
}
else if (rect.left()-1 >= 0)
{
bottom_left = int_img[rect.bottom()][rect.left()-1];
}
else if (rect.top()-1 >= 0)
{
top_right = int_img[rect.top()-1][rect.right()];
}

return bottom_right - bottom_left - top_right + top_left;
}

void swap(integral_image_generic& item)
{
int_img.swap(item.int_img);
}

private:

array2d<T> int_img;
};

template <
typename T
>
void swap (
integral_image_generic<T>& a,
integral_image_generic<T>& b
) { a.swap(b); }

// ----------------------------------------------------------------------------------------

typedef integral_image_generic<long> integral_image;

// ----------------------------------------------------------------------------------------

template <typename integral_image_type>
typename integral_image_type::value_type haar_x (
const integral_image_type& img,
const point& p,
long width
)
{
DLIB_ASSERT(get_rect(img).contains(centered_rect(p,width,width)) == true,
"\tlong haar_x(img,p,width)"
<< "\n\tYou have given a point and with that goes outside the image"
<< "\n\tget_rect(img):  " << get_rect(img)
<< "\n\tp:              " << p
<< "\n\twidth:          " << width
);

rectangle left_rect;
left_rect.set_left ( p.x() - width / 2 );
left_rect.set_top ( p.y() - width / 2 );
left_rect.set_right ( p.x()-1 );
left_rect.set_bottom ( left_rect.top() + width - 1 );

rectangle right_rect;
right_rect.set_left ( p.x() );
right_rect.set_top ( left_rect.top() );
right_rect.set_right ( left_rect.left() + width -1 );
right_rect.set_bottom ( left_rect.bottom() );

return img.get_sum_of_area(right_rect) - img.get_sum_of_area(left_rect);
}

//  ----------------------------------------------------------------------------

template <typename integral_image_type>
typename integral_image_type::value_type haar_y (
const integral_image_type& img,
const point& p,
long width
)
{
DLIB_ASSERT(get_rect(img).contains(centered_rect(p,width,width)) == true,
"\tlong haar_y(img,p,width)"
<< "\n\tYou have given a point and with that goes outside the image"
<< "\n\tget_rect(img):  " << get_rect(img)
<< "\n\tp:              " << p
<< "\n\twidth:          " << width
);

rectangle top_rect;
top_rect.set_left ( p.x() - width / 2 );
top_rect.set_top ( p.y() - width / 2 );
top_rect.set_right ( top_rect.left() + width - 1 );
top_rect.set_bottom ( p.y()-1 );

rectangle bottom_rect;
bottom_rect.set_left ( top_rect.left() );
bottom_rect.set_top ( p.y() );
bottom_rect.set_right ( top_rect.right() );
bottom_rect.set_bottom ( top_rect.top() + width - 1 );

return img.get_sum_of_area(bottom_rect) - img.get_sum_of_area(top_rect);
}

// ----------------------------------------------------------------------------------------

}

#endif // DLIB_INTEGRAL_IMAGE

```