2014-06-10 13:13:16 +00:00
|
|
|
#include "CanvasPreview.h"
|
|
|
|
|
2014-06-12 15:45:59 +00:00
|
|
|
#include "Color.h"
|
|
|
|
#include "CanvasLiveClient.h"
|
|
|
|
#include "Mutex.h"
|
2014-08-18 14:33:09 +00:00
|
|
|
#include "ColorProfile.h"
|
2014-06-12 15:45:59 +00:00
|
|
|
|
|
|
|
#include <cassert>
|
|
|
|
|
2014-08-19 09:25:27 +00:00
|
|
|
#define CHECK_COORDINATES(_x_, _y_) \
|
|
|
|
assert(_x_ >= 0); \
|
|
|
|
assert(_y_ >= 0); \
|
|
|
|
assert(_x_ < this->width); \
|
|
|
|
assert(_y_ < this->height) \
|
|
|
|
|
2014-06-10 13:13:16 +00:00
|
|
|
CanvasPreview::CanvasPreview()
|
|
|
|
{
|
|
|
|
width = 1;
|
|
|
|
height = 1;
|
2014-06-12 15:45:59 +00:00
|
|
|
pixels = new Color[1];
|
|
|
|
|
|
|
|
dirty_left = 1;
|
|
|
|
dirty_right = -1;
|
|
|
|
dirty_down = 1;
|
|
|
|
dirty_up = -1;
|
|
|
|
|
2014-08-18 15:16:17 +00:00
|
|
|
scaled = false;
|
|
|
|
factor = 1.0;
|
|
|
|
factor_x = 1.0;
|
|
|
|
factor_y = 1.0;
|
|
|
|
|
2014-06-12 15:45:59 +00:00
|
|
|
lock = new Mutex();
|
2014-08-18 14:33:09 +00:00
|
|
|
profile = new ColorProfile();
|
2014-06-10 13:13:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CanvasPreview::~CanvasPreview()
|
|
|
|
{
|
|
|
|
delete [] pixels;
|
2014-06-12 15:45:59 +00:00
|
|
|
delete lock;
|
2014-08-18 14:33:09 +00:00
|
|
|
delete profile;
|
2014-06-10 13:13:16 +00:00
|
|
|
}
|
|
|
|
|
2014-08-19 09:25:27 +00:00
|
|
|
const Color &CanvasPreview::getFinalPixel(int x, int y) const
|
|
|
|
{
|
|
|
|
CHECK_COORDINATES(x, y);
|
|
|
|
|
|
|
|
return pixels[y * width + x];
|
|
|
|
}
|
|
|
|
|
2014-06-10 13:13:16 +00:00
|
|
|
void CanvasPreview::setSize(int real_width, int real_height, int preview_width, int preview_height)
|
|
|
|
{
|
2014-06-12 15:45:59 +00:00
|
|
|
lock->acquire();
|
|
|
|
|
2014-06-10 13:13:16 +00:00
|
|
|
delete [] pixels;
|
2014-06-12 15:45:59 +00:00
|
|
|
pixels = new Color[preview_width * preview_height];
|
2014-06-10 13:13:16 +00:00
|
|
|
|
|
|
|
width = preview_width;
|
|
|
|
height = preview_height;
|
2014-06-12 15:45:59 +00:00
|
|
|
|
|
|
|
dirty_left = width;
|
|
|
|
dirty_right = -1;
|
|
|
|
dirty_down = height;
|
|
|
|
dirty_up = -1;
|
|
|
|
|
2014-08-18 15:16:17 +00:00
|
|
|
scaled = (real_width != preview_height or real_height != preview_height);
|
2014-08-20 14:45:45 +00:00
|
|
|
factor_x = (double)preview_width / (double)real_width;
|
|
|
|
factor_y = (double)preview_height / (double)real_height;
|
2014-08-18 15:16:17 +00:00
|
|
|
factor = factor_x * factor_y;
|
|
|
|
|
2014-06-12 15:45:59 +00:00
|
|
|
lock->release();
|
|
|
|
|
|
|
|
reset();
|
|
|
|
}
|
|
|
|
|
2014-08-20 12:31:28 +00:00
|
|
|
void CanvasPreview::setToneMapping(const ColorProfile &profile)
|
|
|
|
{
|
|
|
|
profile.copy(this->profile);
|
|
|
|
setAllDirty();
|
|
|
|
}
|
|
|
|
|
2014-06-12 15:45:59 +00:00
|
|
|
void CanvasPreview::reset()
|
|
|
|
{
|
|
|
|
lock->acquire();
|
|
|
|
|
|
|
|
int n = width * height;
|
|
|
|
for (int i = 0; i < n; i++)
|
|
|
|
{
|
|
|
|
pixels[i] = COLOR_BLACK;
|
|
|
|
}
|
|
|
|
|
|
|
|
lock->release();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CanvasPreview::initLive(CanvasLiveClient *client)
|
|
|
|
{
|
|
|
|
client->canvasResized(width, height);
|
|
|
|
client->canvasCleared(COLOR_BLACK);
|
|
|
|
|
|
|
|
setAllDirty();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CanvasPreview::updateLive(CanvasLiveClient *client)
|
|
|
|
{
|
|
|
|
int x, y;
|
|
|
|
|
|
|
|
lock->acquire();
|
|
|
|
|
|
|
|
for (y = dirty_down; y <= dirty_up; y++)
|
|
|
|
{
|
|
|
|
for (x = dirty_left; x <= dirty_right; x++)
|
|
|
|
{
|
2014-08-18 14:33:09 +00:00
|
|
|
client->canvasPainted(x, y, profile->apply(pixels[y * width + x]));
|
2014-06-12 15:45:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
dirty_left = width;
|
|
|
|
dirty_right = -1;
|
|
|
|
dirty_down = height;
|
|
|
|
dirty_up = -1;
|
|
|
|
|
|
|
|
lock->release();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CanvasPreview::pushPixel(int real_x, int real_y, const Color &old_color, const Color &new_color)
|
|
|
|
{
|
2014-08-18 15:16:17 +00:00
|
|
|
int x, y;
|
|
|
|
|
|
|
|
if (scaled)
|
|
|
|
{
|
2014-08-20 14:45:45 +00:00
|
|
|
x = int(real_x * factor_x);
|
|
|
|
y = int(real_y * factor_y);
|
2014-08-19 09:25:27 +00:00
|
|
|
|
|
|
|
x = (x >= width) ? width - 1 : x;
|
|
|
|
y = (y >= height) ? height - 1 : y;
|
2014-08-18 15:16:17 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
x = real_x;
|
|
|
|
y = real_y;
|
|
|
|
}
|
2014-06-12 15:45:59 +00:00
|
|
|
|
2014-08-19 09:25:27 +00:00
|
|
|
CHECK_COORDINATES(x, y);
|
2014-08-18 15:33:15 +00:00
|
|
|
|
2014-08-20 14:45:45 +00:00
|
|
|
lock->acquire();
|
|
|
|
|
2014-08-18 15:16:17 +00:00
|
|
|
Color* pixel = pixels + (y * width + x);
|
2014-08-20 14:45:45 +00:00
|
|
|
pixel->r = pixel->r - old_color.r * factor + new_color.r * factor;
|
|
|
|
pixel->g = pixel->g - old_color.g * factor + new_color.g * factor;
|
|
|
|
pixel->b = pixel->b - old_color.b * factor + new_color.b * factor;
|
2014-06-12 15:45:59 +00:00
|
|
|
|
|
|
|
// Set pixel dirty
|
|
|
|
if (x < dirty_left)
|
|
|
|
{
|
|
|
|
dirty_left = x;
|
|
|
|
}
|
|
|
|
if (x > dirty_right)
|
|
|
|
{
|
|
|
|
dirty_right = x;
|
|
|
|
}
|
|
|
|
if (y < dirty_down)
|
|
|
|
{
|
|
|
|
dirty_down = y;
|
|
|
|
}
|
|
|
|
if (y > dirty_up)
|
|
|
|
{
|
|
|
|
dirty_up = y;
|
|
|
|
}
|
|
|
|
|
|
|
|
lock->release();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CanvasPreview::setAllDirty()
|
|
|
|
{
|
|
|
|
lock->acquire();
|
|
|
|
|
|
|
|
dirty_left = 0;
|
|
|
|
dirty_right = width - 1;
|
|
|
|
dirty_down = 0;
|
|
|
|
dirty_up = height - 1;
|
|
|
|
|
|
|
|
lock->release();
|
2014-06-10 13:13:16 +00:00
|
|
|
}
|