25#include "tqfontinfo.h"
26#include "tqfontmetrics.h"
34#include <tqpointarray.h>
44#include "kis_global.h"
46#include "kis_iterators_pixel.h"
48#include "kis_paint_device.h"
49#include "kis_painter.h"
50#include "kis_pattern.h"
52#include "kis_colorspace.h"
55#include "kis_selection.h"
56#include "kis_convolution_painter.h"
59KisKernelSP KisKernel::fromTQImage(
const TQImage& img)
61 KisKernelSP k =
new KisKernel;
62 k->width = img.width();
63 k->height = img.height();
65 uint count = k->width * k->height;
66 k->data =
new TQ_INT32[count];
67 TQ_INT32* itData = k->data;
68 TQ_UINT8* itImg = (TQ_UINT8*)img.bits();
70 for(uint i = 0; i < count; ++i , ++itData, itImg+=4)
72 *itData = 255 - ( *itImg + *(itImg+1) + *(itImg+2) ) / 3;
79KisConvolutionPainter::KisConvolutionPainter()
84KisConvolutionPainter::KisConvolutionPainter(KisPaintDeviceSP device) : super(device)
88void KisConvolutionPainter::applyMatrix(KisKernelSP kernel, TQ_INT32 x, TQ_INT32 y, TQ_INT32 w, TQ_INT32 h,
89 KisConvolutionBorderOp borderOp,
90 KisChannelInfo::enumChannelFlags channelFlags )
93 if (m_device->hasSelection()) {
95 TQRect r = m_device->selection()->selectedRect().intersect(TQRect(x, y, w, h));
103 if ( w == 0 && h == 0 )
return;
106 TQ_INT32 kw, kh, khalfWidth, khalfHeight, xLastMinuskhw, yLastMinuskhh;
109 khalfWidth = (kw - 1) / 2;
110 khalfHeight = (kh - 1) / 2;
112 xLastMinuskhw = x + (w - khalfWidth);
113 yLastMinuskhh = y + (h - khalfHeight);
116 if (w < kw || h < kh || (kw&1) == 0 || (kh&1) == 0 || kernel->factor == 0 )
return;
118 m_cancelRequested =
false;
119 int lastProgressPercent = 0;
120 emit notifyProgress(0);
122 KisColorSpace * cs = m_device->colorSpace();
126 case BORDER_DEFAULT_FILL :
129 applyMatrixRepeat(kernel, x, y, w, h, channelFlags);
142 int cacheSize = kw * kh;
143 int cdepth = cs -> pixelSize();
144 TQ_UINT8** pixelPtrCache =
new TQ_UINT8*[cacheSize];
145 for (
int i = 0; i < cacheSize; i++)
146 pixelPtrCache[i] =
new TQ_UINT8[cdepth];
152 for (; row < y + h; ++row) {
157 KisHLineIteratorPixel hit = m_device->createHLineIterator(x, row, w,
true);
158 bool needFull =
true;
159 while (!hit.isDone()) {
166 for (TQ_INT32 krow = 0; krow < kh; ++krow) {
173 KisHLineIteratorPixel kit = m_device->createHLineIterator(col - khalfWidth, (row - khalfHeight) + krow, kw,
false);
174 while (!kit.isDone()) {
175 memcpy(pixelPtrCache[i], kit.oldRawData(), cdepth);
183 for (TQ_INT32 krow = 0; krow < kh; ++krow) {
184 TQ_UINT8** d = pixelPtrCache + krow * kw;
186 for (
int i = 0; i < (kw-1); i++) {
187 memcpy(d[i], d[i+1], cdepth);
191 KisVLineIteratorPixel kit = m_device->createVLineIterator(col + khalfWidth, row - khalfHeight, kh,
false);
192 while (!kit.isDone()) {
193 memcpy(pixelPtrCache[i], kit.oldRawData(), cdepth);
198 if (hit.isSelected()) {
199 cs->
convolveColors(pixelPtrCache, kernel->data, channelFlags, hit.rawData(), kernel->factor, kernel->offset, kw * kh);
206 int progressPercent = 100 - ((((y + h) - row) * 100) / h);
208 if (progressPercent > lastProgressPercent) {
209 emit notifyProgress(progressPercent);
210 lastProgressPercent = progressPercent;
212 if (m_cancelRequested) {
213 for (
int i = 0; i < cacheSize; i++)
214 delete[] pixelPtrCache[i];
215 delete[] pixelPtrCache;
225 emit notifyProgressDone();
227 for (
int i = 0; i < cacheSize; i++)
228 delete[] pixelPtrCache[i];
229 delete[] pixelPtrCache;
232void KisConvolutionPainter::applyMatrixRepeat(KisKernelSP kernel, TQ_INT32 x, TQ_INT32 y, TQ_INT32 w, TQ_INT32 h,
233 KisChannelInfo::enumChannelFlags channelFlags)
235 int lastProgressPercent = 0;
237 TQ_INT32 kw, kh, khalfWidth, khalfHeight, xLastMinuskhw, yLastMinuskhh;
240 khalfWidth = (kw - 1) / 2;
241 khalfHeight = (kh - 1) / 2;
243 xLastMinuskhw = x + (w - khalfWidth);
244 yLastMinuskhh = y + (h - khalfHeight);
246 KisColorSpace * cs = m_device->colorSpace();
250 int cacheSize = kw * kh;
251 int cdepth = cs -> pixelSize();
252 TQ_UINT8** pixelPtrCache =
new TQ_UINT8*[cacheSize];
253 for (
int i = 0; i < cacheSize; i++)
254 pixelPtrCache[i] =
new TQ_UINT8[cdepth];
259 for (; row < y + h; ++row) {
264 KisHLineIteratorPixel hit = m_device->createHLineIterator(x, row, w,
true);
265 bool needFull =
true;
267 TQ_INT32 itStart = row - khalfHeight;
273 }
else if(itStart + kh > yLastMinuskhh)
275 itH -= itStart + kh - yLastMinuskhh;
277 KisVLineIteratorPixel kit = m_device->createVLineIterator(col + khalfWidth, itStart, itH,
false);
278 while (!hit.isDone()) {
286 if( row < khalfHeight )
293 KisHLineIteratorPixel kit = m_device->createHLineIterator(0, 0, kw,
false);
294 for(; kcol < (khalfWidth - x) + 1; ++kcol)
296 memcpy(pixelPtrCache[kcol], kit.oldRawData(), cdepth);
298 for(; kcol < kw; ++kcol)
301 memcpy(pixelPtrCache[kcol], kit.oldRawData(), cdepth);
305 KisHLineIteratorPixel kit = m_device->createHLineIterator(col - khalfWidth, 0, kw,
false);
306 while (!kit.isDone()) {
307 memcpy(pixelPtrCache[kcol], kit.oldRawData(), cdepth);
313 for(;krow < (khalfHeight - row); ++krow)
316 for (
int i = 0; i < kw; i++)
317 memcpy(pixelPtrCache[krow * kw + i], pixelPtrCache[i], cdepth);
322 if(row + khalfHeight > yLastMinuskhh)
324 itH += yLastMinuskhh - row - khalfHeight;
326 for (; krow < itH; ++krow) {
333 TQ_INT32 itHStart = col - khalfWidth;
340 KisHLineIteratorPixel kit = m_device->createHLineIterator(itHStart, (row - khalfHeight) + krow, itW,
false);
341 if( col < khalfWidth )
343 for(; i < krow * kw + ( kw - itW ); i+= 1)
345 memcpy(pixelPtrCache[i], kit.oldRawData(), cdepth);
348 while (!kit.isDone()) {
349 memcpy(pixelPtrCache[i], kit.oldRawData(), cdepth);
354 TQ_INT32 lastvalid = i - kw;
355 for(; krow < kh; ++krow) {
357 for (
int i = 0; i < kw; i++)
358 memcpy(pixelPtrCache[krow * kw + i], pixelPtrCache[lastvalid + i],
370 TQ_UINT8* firstincache = pixelPtrCache[0];
371 memmove(pixelPtrCache, pixelPtrCache + 1, (cacheSize - 1) *
sizeof(TQ_UINT8*) );
372 pixelPtrCache[cacheSize - 1] = firstincache;
373 if(col < xLastMinuskhw)
378 if( row < khalfHeight )
380 for(; i < (khalfHeight- row ) * kw; i+=kw)
382 memcpy(pixelPtrCache[i], kit.oldRawData(), cdepth);
385 while (!kit.isDone()) {
386 memcpy(pixelPtrCache[i], kit.oldRawData(), cdepth);
390 TQ_INT32 lastvalid = i - kw;
391 for(;i < kw*kh; i+=kw)
393 memcpy(pixelPtrCache[i], pixelPtrCache[lastvalid], cdepth);
397 if (hit.isSelected()) {
398 cs->convolveColors(pixelPtrCache, kernel->data, channelFlags, hit.rawData(), kernel->factor, kernel->offset, kw * kh);
404 int progressPercent = 100 - ((((y + h) - row) * 100) / h);
406 if (progressPercent > lastProgressPercent) {
407 emit notifyProgress(progressPercent);
408 lastProgressPercent = progressPercent;
410 if (m_cancelRequested) {
411 for (
int i = 0; i < cacheSize; i++)
412 delete[] pixelPtrCache[i];
413 delete[] pixelPtrCache;
422 emit notifyProgressDone();
423 for (
int i = 0; i < cacheSize; i++)
424 delete[] pixelPtrCache[i];
425 delete[] pixelPtrCache;
virtual void convolveColors(TQ_UINT8 **colors, TQ_INT32 *kernelValues, KisChannelInfo::enumChannelFlags channelFlags, TQ_UINT8 *dst, TQ_INT32 factor, TQ_INT32 offset, TQ_INT32 nPixels) const =0
Convolve the given array of pointers to pixels and return the result in dst.
TQRect addDirtyRect(TQRect r)
Add the r to the current dirty rect, and return the dirtyRect after adding r to it.