21 #include "../lout/msg.h" 22 #include "../lout/misc.hh" 24 #include <FL/fl_draw.H> 27 #define IMAGE_MAX_AREA (6000 * 6000) 29 #define MAX_WIDTH 0x8000 30 #define MAX_HEIGHT 0x8000 48 for (
int i = 0; i < gammaCorrectionTables->size(); i++) {
50 if (gct->
gamma == gamma)
54 _MSG(
"Creating new table for gamma = %g\n", gamma);
59 for (
int i = 0; i < 256; i++)
60 gct->
map[i] = 255 * pow((
double)i / 255, gamma);
62 gammaCorrectionTables->put (gct);
68 return width <= 0 || height <= 0 ||
74 _MSG(
"Deleting gammaCorrectionTables\n");
75 delete gammaCorrectionTables;
76 gammaCorrectionTables = NULL;
83 _MSG (
"FltkImgbuf::FltkImgbuf: new root %p\n",
this);
84 init (type, width, height, gamma, NULL);
92 _MSG (
"FltkImgbuf::FltkImgbuf: new scaled %p, root is %p\n",
this, root);
93 init (type, width, height, gamma, root);
99 if (excessiveImageDimensions (width, height)) {
104 MSG(
"FltkImgbuf::init: suspicious image size request %d x %d\n",
106 init (type, 1, 1, gamma, root);
114 MSG(
"FltkImgbuf::init: cannot handle large width %d\n", width);
117 MSG(
"FltkImgbuf::init: cannot handle large height %d\n", height);
119 }
else if (gamma <= 0) {
120 MSG(
"FltkImgbuf::init: non-positive gamma %g\n", gamma);
121 init (type, width, height, 1, root);
126 this->height = height;
134 case RGBA: bpp = 4;
break;
135 case RGB: bpp = 3;
break;
136 default: bpp = 1;
break;
138 _MSG(
"FltkImgbuf::init this=%p width=%d height=%d bpp=%d gamma=%g\n",
139 this, width, height, bpp, gamma);
140 rawdata =
new uchar[bpp * width * height];
142 memset(rawdata, 222, width*height*bpp);
145 deleteOnUnref =
true;
152 scaledBuffers = NULL;
156 for (
int row = 0; row < root->
height; row++) {
166 _MSG (
"FltkImgbuf::~FltkImgbuf\n");
169 root->detachScaledBuf (
this);
175 delete scaledBuffers;
186 scaledBuffers->detachRef (scaledBuf);
188 _MSG(
"FltkImgbuf[root %p]: scaled buffer %p is detached, %d left\n",
189 this, scaledBuf, scaledBuffers->size ());
191 if (refCount == 0 && scaledBuffers->isEmpty () && deleteOnUnref)
204 if (row < root->height) {
206 scaleRowSimple (row, data);
208 scaleRowBeautiful (row, data);
214 int sr1 = scaledY (row);
215 int sr2 = scaledY (row + 1);
217 for (
int sr = sr1; sr < sr2; sr++) {
219 if (copiedRows->get(sr))
continue;
221 copiedRows->set (sr,
true);
223 for (
int px = 0; px < root->width; px++) {
224 int px1 = px * width / root->width;
225 int px2 = (px+1) * width / root->width;
226 for (
int sp = px1; sp < px2; sp++) {
227 memcpy(rawdata + (sr*width + sp)*bpp, data + px*bpp, bpp);
231 memcpy(rawdata + sr*width*bpp, rawdata + sr1*width*bpp, width*bpp);
238 int sr1 = scaledY (row);
239 int sr2 = scaledY (row + 1);
240 bool allRootRows =
false;
243 if (copiedRows->get(sr1))
return;
245 if (height > root->height) {
246 scaleBuffer (data, root->width, 1,
247 rawdata + sr1 * width * bpp, width, sr2 - sr1,
250 for (
int sr = sr1; sr < sr2 || sr == sr1; sr++)
251 copiedRows->set (sr,
true);
253 assert (sr1 == sr2 || sr1 + 1 == sr2);
254 int row1 = backscaledY(sr1), row2 = backscaledY(sr1 + 1);
258 for (
int r=row1; (allRootRows=root->copiedRows->get(r)) && ++r < row2; );
260 scaleBuffer (root->rawdata + row1 * root->width * bpp,
261 root->width, row2 - row1,
262 rawdata + sr1 * width * bpp, width, 1,
265 copiedRows->set (sr1,
true);
292 int destWidth,
int destHeight,
int bpp,
295 uchar *gammaMap1, *gammaMap2;
298 gammaMap1 = findGammaCorrectionTable (gamma);
299 gammaMap2 = findGammaCorrectionTable (1 / gamma);
302 for(
int x = 0; x < destWidth; x++)
303 for(
int y = 0; y < destHeight; y++) {
304 int xo1 = x * srcWidth / destWidth;
306 int yo1 = y * srcHeight / destHeight;
308 int n = (xo2 - xo1) * (yo2 - yo1);
311 for(
int i = 0; i < bpp; i++)
314 for(
int xo = xo1; xo < xo2; xo++)
315 for(
int yo = yo1; yo < yo2; yo++) {
316 const core::byte *ps = src + bpp * (yo * srcWidth + xo);
317 for(
int i = 0; i < bpp; i++)
322 core::byte *pd = dest + bpp * (y * destWidth + x);
323 for(
int i = 0; i < bpp; i++)
335 copiedRows->set (row,
true);
336 memcpy(rawdata + row * width * bpp, data, width * bpp);
364 MSG(
"FltkImgbuf::getScaledBuf: cannot handle large width %d\n", width);
368 MSG(
"FltkImgbuf::getScaledBuf: cannot handle large height %d\n", height);
372 if (width == this->width && height == this->height) {
388 if (excessiveImageDimensions (width, height)) {
389 MSG(
"FltkImgbuf::getScaledBuf: suspicious image size request %d x %d\n",
397 scaledBuffers->append (sb);
413 _MSG(
"::getRowArea: area x=%d y=%d width=%d height=%d\n",
416 if (row > root->height)
420 int sr1 = scaledY (row);
421 int sr2 = scaledY (row + 1);
427 _MSG(
"::getRowArea: area x=%d y=%d width=%d height=%d\n",
435 return root ? root->width : width;
440 return root ? root->height : height;
445 return new FltkImgbuf (type, width, height, gamma);
449 int xSrc,
int ySrc,
int widthSrc,
int heightSrc)
452 assert (bpp == fDest->
bpp);
462 for (
int x = xSrc; x < xSrc2; x++)
463 for (
int y = ySrc; y < ySrc2; y++) {
464 int iSrc = x + width * y;
465 int iDest = xDestRoot + x + fDest->
width * (yDestRoot + y);
469 for (
int b = 0; b < bpp; b++)
470 fDest->
rawdata[bpp * iDest + b] = rawdata[bpp * iSrc + b];
493 if (--refCount == 0) {
497 if (scaledBuffers->isEmpty () && deleteOnUnref) {
500 _MSG(
"FltkImgbuf[root %p]: not deleted. numScaled=%d\n",
501 this, scaledBuffers->size ());
511 return refCount == 1 &&
512 (scaledBuffers == NULL || scaledBuffers->isEmpty ());
518 this->deleteOnUnref = deleteOnUnref;
523 return refCount != 0 ||
524 (scaledBuffers != NULL && !scaledBuffers->isEmpty ());
531 assert (root != NULL);
532 return ySrc * height / root->height;
537 assert (root != NULL);
543 return yScaled * root->height / height;
547 int x,
int y,
int width,
int height)
552 _MSG(
"::draw: xRoot=%d x=%d yRoot=%d y=%d width=%d height=%d\n" 553 " this->width=%d this->height=%d\n",
554 xRoot, x, yRoot, y, width, height, this->width, this->height);
556 if (x > this->width || y > this->height) {
560 if (x + width > this->width) {
561 width = this->width - x;
564 if (y + height > this->height) {
565 height = this->height - y;
568 fl_draw_image(rawdata+bpp*(y*this->width + x), xRoot + x, yRoot + y, width,
569 height, bpp, this->width * bpp);