2014-08-21 10:36:28 +00:00
|
|
|
#include "CanvasPictureWriter.h"
|
|
|
|
|
|
|
|
#include <cassert>
|
|
|
|
|
|
|
|
#include "Canvas.h"
|
|
|
|
#include "CanvasPortion.h"
|
|
|
|
#include "ColorProfile.h"
|
|
|
|
#include "PackStream.h"
|
|
|
|
|
2015-11-09 21:30:46 +00:00
|
|
|
CanvasPictureWriter::CanvasPictureWriter(const Canvas *canvas) : canvas(canvas) {
|
2014-08-21 10:36:28 +00:00
|
|
|
profile = new ColorProfile();
|
|
|
|
antialias = 1;
|
|
|
|
width = canvas->getWidth();
|
|
|
|
height = canvas->getHeight();
|
2014-08-21 13:30:09 +00:00
|
|
|
|
2014-08-21 20:23:04 +00:00
|
|
|
cache = new Color[1];
|
|
|
|
cache_y = -antialias;
|
|
|
|
cache_width = 0;
|
2014-08-21 10:36:28 +00:00
|
|
|
}
|
|
|
|
|
2015-11-09 21:30:46 +00:00
|
|
|
CanvasPictureWriter::~CanvasPictureWriter() {
|
2014-08-21 10:36:28 +00:00
|
|
|
delete profile;
|
2015-08-23 20:44:45 +00:00
|
|
|
delete[] cache;
|
2014-08-21 10:36:28 +00:00
|
|
|
}
|
|
|
|
|
2015-11-09 21:30:46 +00:00
|
|
|
void CanvasPictureWriter::setAntialias(int antialias) {
|
2014-08-21 10:36:28 +00:00
|
|
|
assert(antialias >= 1);
|
|
|
|
assert(canvas->getWidth() % antialias == 0);
|
|
|
|
assert(canvas->getHeight() % antialias == 0);
|
|
|
|
|
|
|
|
this->antialias = antialias;
|
|
|
|
this->width = canvas->getWidth() / antialias;
|
|
|
|
this->height = canvas->getHeight() / antialias;
|
|
|
|
}
|
|
|
|
|
2015-11-09 21:30:46 +00:00
|
|
|
void CanvasPictureWriter::setColorProfile(const ColorProfile &profile) {
|
2014-08-21 10:36:28 +00:00
|
|
|
profile.copy(this->profile);
|
|
|
|
}
|
|
|
|
|
2015-12-10 23:36:50 +00:00
|
|
|
bool CanvasPictureWriter::saveCanvas(const string &filepath) {
|
2014-08-21 10:36:28 +00:00
|
|
|
return save(filepath, width, height);
|
|
|
|
}
|
|
|
|
|
2015-11-09 21:30:46 +00:00
|
|
|
unsigned int CanvasPictureWriter::getPixel(int x, int y) {
|
2014-08-21 12:53:49 +00:00
|
|
|
Color comp;
|
|
|
|
|
2015-11-09 21:30:46 +00:00
|
|
|
if (antialias > 1) {
|
2014-08-21 10:36:28 +00:00
|
|
|
int basex = x * antialias;
|
|
|
|
int basey = y * antialias;
|
|
|
|
double factor = 1.0 / (antialias * antialias);
|
|
|
|
|
2014-08-21 12:53:49 +00:00
|
|
|
comp = COLOR_BLACK;
|
|
|
|
|
2015-11-09 21:30:46 +00:00
|
|
|
for (int iy = 0; iy < antialias; iy++) {
|
|
|
|
for (int ix = 0; ix < antialias; ix++) {
|
2014-08-21 10:36:28 +00:00
|
|
|
Color col = getRawPixel(basex + ix, basey + iy);
|
|
|
|
comp.r += col.r * factor;
|
|
|
|
comp.g += col.g * factor;
|
|
|
|
comp.b += col.b * factor;
|
|
|
|
}
|
|
|
|
}
|
2015-11-09 21:30:46 +00:00
|
|
|
} else {
|
2014-08-21 12:53:49 +00:00
|
|
|
comp = getRawPixel(x, y);
|
2014-08-21 10:36:28 +00:00
|
|
|
}
|
2014-08-21 12:53:49 +00:00
|
|
|
|
|
|
|
comp = profile->apply(comp);
|
|
|
|
comp.normalize();
|
|
|
|
return comp.to32BitBGRA();
|
2014-08-21 10:36:28 +00:00
|
|
|
}
|
|
|
|
|
2015-11-09 21:30:46 +00:00
|
|
|
Color CanvasPictureWriter::getRawPixel(int x, int y) {
|
|
|
|
if (not(y >= cache_y && y < cache_y + antialias)) {
|
2014-08-21 20:23:04 +00:00
|
|
|
// Load rows into cache
|
2015-08-23 20:44:45 +00:00
|
|
|
delete[] cache;
|
2014-08-21 20:23:04 +00:00
|
|
|
cache_y = y;
|
|
|
|
cache_width = canvas->getWidth();
|
|
|
|
cache = new Color[cache_width * antialias];
|
|
|
|
|
|
|
|
CanvasPortion *portion = NULL;
|
|
|
|
PackStream *stream = new PackStream;
|
|
|
|
|
2015-11-09 21:30:46 +00:00
|
|
|
Color *itcolor = cache;
|
2014-08-21 20:23:04 +00:00
|
|
|
bool has_pixels = false;
|
2015-11-09 21:30:46 +00:00
|
|
|
for (int cy = cache_y; cy < cache_y + antialias; cy++) {
|
|
|
|
for (int cx = 0; cx < cache_width; cx++) {
|
2014-08-21 20:23:04 +00:00
|
|
|
CanvasPortion *nportion = canvas->atPixel(cx, cy);
|
2015-11-09 21:30:46 +00:00
|
|
|
if (nportion != portion) {
|
2014-08-21 20:23:04 +00:00
|
|
|
portion = nportion;
|
|
|
|
delete stream;
|
|
|
|
stream = new PackStream;
|
2015-11-09 21:30:46 +00:00
|
|
|
has_pixels =
|
|
|
|
portion->getReadStream(*stream, cx - portion->getXOffset(), cy - portion->getYOffset());
|
2014-08-21 20:23:04 +00:00
|
|
|
}
|
2015-11-09 21:30:46 +00:00
|
|
|
if (has_pixels) {
|
2014-08-21 20:23:04 +00:00
|
|
|
itcolor->load(stream);
|
2015-11-09 21:30:46 +00:00
|
|
|
} else {
|
2014-08-21 20:23:04 +00:00
|
|
|
*itcolor = COLOR_BLACK;
|
|
|
|
}
|
|
|
|
itcolor++;
|
|
|
|
}
|
2014-08-21 13:30:09 +00:00
|
|
|
}
|
2015-08-23 20:44:45 +00:00
|
|
|
|
|
|
|
delete stream;
|
2014-08-21 10:36:28 +00:00
|
|
|
}
|
|
|
|
|
2014-08-21 20:23:04 +00:00
|
|
|
// Hit the cache
|
|
|
|
return cache[(y - cache_y) * cache_width + x];
|
2014-08-21 10:36:28 +00:00
|
|
|
}
|