18#include <tqdatetime.h>
23#include "kis_paint_device.h"
24#include "kis_scale_visitor.h"
25#include "kis_filter_strategy.h"
28void KisScaleWorker::run()
30 double fwidth = m_filterStrategy->support();
32 TQRect rect = m_dev -> exactBounds();
33 TQ_INT32 width = rect.width();
34 TQ_INT32 height = rect.height();
35 m_pixelSize=m_dev -> pixelSize();
38 if ( m_sx == 1.0F && m_sy == 1.0F ) {
41 TQ_INT32 targetW = TQABS( tqRound( m_sx * width ) );
42 TQ_INT32 targetH = TQABS( tqRound( m_sy * height ) );
44 TQ_UINT8* newData =
new TQ_UINT8[targetW * targetH * m_pixelSize ];
45 TQ_CHECK_PTR(newData);
47 double* weight =
new double[ m_pixelSize ];
49 TQ_UINT8* pel =
new TQ_UINT8[ m_pixelSize ];
52 TQ_UINT8 *pel2 =
new TQ_UINT8[ m_pixelSize ];
55 bool* bPelDelta =
new bool[ m_pixelSize ];
56 ContribList *contribX;
58 const TQ_INT32 BLACK_PIXEL=0;
59 const TQ_INT32 WHITE_PIXEL=255;
63 TQ_UINT8 * tmp =
new TQ_UINT8[ width * m_pixelSize ];
67 TQ_UINT8 **tmpRows =
new TQ_UINT8*[ height ];
70 TQ_UINT8 **tmpRowsMem;
73 tmpRowsMem =
new TQ_UINT8*[ (int)(fwidth / m_sy * 2 + 1) ];
74 for(
int i = 0; i < (int)(fwidth / m_sy * 2 + 1); i++)
76 tmpRowsMem[i] =
new TQ_UINT8[ width * m_pixelSize ];
77 TQ_CHECK_PTR(tmpRowsMem[i]);
82 tmpRowsMem =
new TQ_UINT8*[ (int)(fwidth * 2 + 1) ];
83 for(
int i = 0; i < (int)(fwidth * 2 + 1); i++)
85 tmpRowsMem[i] =
new TQ_UINT8[ width * m_pixelSize ];
86 TQ_CHECK_PTR(tmpRowsMem[i]);
91 contribX =
new ContribList[ targetW ];
92 for(
int x = 0; x < targetW; x++)
94 calcContrib(&contribX[x], m_sx, fwidth, width, m_filterStrategy, x);
97 TQTime starttime = TQTime::currentTime ();
99 for(
int y = 0; y < targetH; y++)
102 calcContrib(&contribY, m_sy, fwidth, height, m_filterStrategy, y);
105 for(
int srcpos = 0; srcpos < contribY.n; srcpos++)
107 if (!(contribY.p[srcpos].m_pixel < 0 || contribY.p[srcpos].m_pixel >= height))
109 tmpRows[contribY.p[srcpos].m_pixel] =
new TQ_UINT8[ width * m_pixelSize ];
111 m_dev ->readBytes(tmpRows[contribY.p[srcpos].m_pixel], 0, contribY.p[srcpos].m_pixel, width, 1);
116 for(
int x = 0; x < width; x++)
118 for(
int channel = 0; channel < m_pixelSize; channel++){
119 weight[channel] = 0.0;
120 bPelDelta[channel] =
false;
121 pel[channel]=tmpRows[contribY.p[0].m_pixel][ x * m_pixelSize + channel ];
123 for(
int srcpos = 0; srcpos < contribY.n; srcpos++)
125 if (!(contribY.p[srcpos].m_pixel < 0 || contribY.p[srcpos].m_pixel >= height)){
126 for(
int channel = 0; channel < m_pixelSize; channel++)
128 pel2[channel]=tmpRows[contribY.p[srcpos].m_pixel][ x * m_pixelSize + channel ];
129 if(pel2[channel] != pel[channel]) bPelDelta[channel] =
true;
130 weight[channel] += pel2[channel] * contribY.p[srcpos].m_weight;
135 for(
int channel = 0; channel < m_pixelSize; channel++){
136 weight[channel] = bPelDelta[channel] ?
static_cast<int>(tqRound(weight[channel])) : pel[channel];
137 tmp[ x * m_pixelSize + channel ] =
static_cast<TQ_UINT8
>(CLAMP(weight[channel], BLACK_PIXEL, WHITE_PIXEL));
142 for(
int x = 0; x < targetW; x++)
144 for(
int channel = 0; channel < m_pixelSize; channel++){
145 weight[channel] = 0.0;
146 bPelDelta[channel] =
false;
147 pel[channel] = tmp[ contribX[x].p[0].m_pixel * m_pixelSize + channel ];
149 for(
int srcpos = 0; srcpos < contribX[x].n; srcpos++)
151 for(
int channel = 0; channel < m_pixelSize; channel++){
152 pel2[channel] = tmp[ contribX[x].p[srcpos].m_pixel * m_pixelSize + channel ];
153 if(pel2[channel] != pel[channel])
154 bPelDelta[channel] =
true;
155 weight[channel] += pel2[channel] * contribX[x].p[srcpos].m_weight;
158 for(
int channel = 0; channel < m_pixelSize; channel++){
159 weight[channel] = bPelDelta[channel] ?
static_cast<int>(tqRound(weight[channel])) : pel[channel];
160 int currentPos = (y*targetW+x) * m_pixelSize;
161 if (weight[channel]<0)
162 newData[currentPos + channel] = 0;
163 else if (weight[channel]>255)
164 newData[currentPos + channel] = 255;
166 newData[currentPos + channel] = (uchar)weight[channel];
173 m_dev -> writeBytes( newData, 0, 0, targetW, targetH);
174 m_dev -> crop(0, 0, targetW, targetH);
178 for(
int x = 0; x < targetW; x++)
179 delete[] contribX[x].p;
191 for(
int i = 0; i < (int)(fwidth / m_sy * 2 + 1); i++)
193 delete[] tmpRowsMem[i];
198 for(
int i = 0; i < (int)(fwidth * 2 + 1); i++)
200 delete[] tmpRowsMem[i];
204 TQTime stoptime = TQTime::currentTime ();
208int KisScaleWorker::calcContrib(ContribList *contrib,
double scale,
double fwidth,
int srcwidth, KisFilterStrategy* filterStrategy, TQ_INT32 i)
220 double center, begin, end;
227 width = fwidth / scale;
228 fscale = 1.0 / scale;
231 contrib->p =
new Contrib[ (int)(width * 2 + 1) ];
233 center = (double) i / scale;
234 begin = ceil(center - width);
235 end = floor(center + width);
236 for(
int srcpos = (
int)begin; srcpos <= end; ++srcpos)
238 weight = center - (double) srcpos;
239 weight = filterStrategy->valueAt(weight / fscale) / fscale;
242 else if(srcpos >= srcwidth)
243 n = (srcwidth - srcpos) + srcwidth - 1;
248 contrib->p[k].m_pixel = n;
249 contrib->p[k].m_weight = weight;
256 contrib->p =
new Contrib[ (int)(fwidth * 2 + 1) ];
258 center = (double) i / scale;
259 begin = ceil(center - fwidth);
260 end = floor(center + fwidth);
262 for(
int srcpos = (
int)begin; srcpos <= end; ++srcpos)
264 weight = center - (double) srcpos;
265 weight = filterStrategy->valueAt(weight);
268 }
else if(srcpos >= srcwidth) {
269 n = (srcwidth - srcpos) + srcwidth - 1;
274 contrib->p[k].m_pixel = n;
275 contrib->p[k].m_weight = weight;