--Boundary-00=_3gTUBfyLblI6mZa Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline Hello, I moved the scaling code to a visitor. Please copy the attached files to krita/core/ (or maybe better to krita/core/visitors, but I don't know how to set up the automake stuff...) and apply the attached patch. I will work on progress info for the scaling code next. Then I try to implement simple image rotation. There is an advanced algorith which works really good, which is explained in Graphics Gems I, but unfortunately someone borrowed the book from our library and I will have to wait until mid of october to get the book. Michael --Boundary-00=_3gTUBfyLblI6mZa Content-Type: text/x-chdr; charset="us-ascii"; name="kis_scale_visitor.h" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="kis_scale_visitor.h" /* * copyright (c) 2004 Michael Thaler * * this program is free software; you can redistribute it and/or modify * it under the terms of the gnu general public license as published by * the free software foundation; either version 2 of the license, or * (at your option) any later version. * * this program is distributed in the hope that it will be useful, * but without any warranty; without even the implied warranty of * merchantability or fitness for a particular purpose. see the * gnu general public license for more details. * * you should have received a copy of the gnu general public license * along with this program; if not, write to the free software * foundation, inc., 675 mass ave, cambridge, ma 02139, usa. */ #ifndef KIS_SCALE_VISITOR_H_ #define KIS_SCALE_VISITOR_H_ #include "kis_types.h" #include "kis_paint_device.h" class KisScaleVisitor { /* Structs for the image rescaling routine */ struct CONTRIB { Q_INT32 m_pixel; double m_weight; }; struct CLIST { Q_INT32 n; //number of contributors CONTRIB *p; //pointer to list of contributions }; public: KisScaleVisitor(); ~KisScaleVisitor(); void visitKisPaintDevice(KisPaintDevice* dev); void scale(double sx, double sy); private: KisPaintDevice* m_dev; /** * calc_x_contrib() * * Calculates the filter weights for a single target column. * contribX->p must be freed afterwards. * * Returns -1 if error, 0 otherwise. */ int calc_x_contrib(CLIST *contribX, double xcale, double fwidth, int dstwidth, int srcwidth, double (KisScaleVisitor::*filterf)(double), Q_INT32 i); /* scaling filter function definitions */ double filter(double t); double box_filter(double t); double triangle_filter(double t); double bell_filter(double t); double B_spline_filter(double t); double sinc(double x); double Lanczos3_filter(double t); double Mitchell_filter(double t); CLIST * contrib; //array of contribution lists }; inline KisScaleVisitor::KisScaleVisitor() { } inline KisScaleVisitor::~KisScaleVisitor() { } inline void KisScaleVisitor::visitKisPaintDevice(KisPaintDevice* dev) { m_dev=dev; } #endif // KIS_SCALE_VISITOR_H_ --Boundary-00=_3gTUBfyLblI6mZa Content-Type: text/x-c++src; charset="us-ascii"; name="kis_scale_visitor.cc" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="kis_scale_visitor.cc" /* * Copyright (c) 2004 Michael Thaler * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include "kis_scale_visitor.h" void KisScaleVisitor::scale(double xscale, double yscale) { //define filter supports const double filter_support=1.0; const double box_support=0.5; const double triangle_support=1.0; const double bell_support=1.5; const double B_spline_support=2.0; const double Lanczos3_support=3.0; const double Mitchell_support=2.0; double (KisScaleVisitor::*filterf)(double) = &KisScaleVisitor::Mitchell_filter; //pointer to filter function double fwidth; // target image data Q_INT32 targetW; Q_INT32 targetH; // compute size of target image // (this bit seems to be mostly from QImage.xForm) QWMatrix scale_matrix; scale_matrix.scale(xscale, yscale); scale_matrix = QPixmap::trueMatrix( scale_matrix, m_dev->width(), m_dev->height() ); if ( scale_matrix.m11() == 1.0F && scale_matrix.m22() == 1.0F ) { kdDebug() << "Identity matrix, do nothing.\n"; return; } targetW = qRound( scale_matrix.m11() * m_dev->width() ); targetH = qRound( scale_matrix.m22() * m_dev->height() ); targetW = QABS( targetW ); targetH = QABS( targetH ); //set filter type enum filterType { BOX_FILTER, TRIANGLE_FILTER, BELL_FILTER, B_SPLINE_FILTER, FILTER, LANCZOS3_FILTER, MITCHELL_FILTER }; filterType filter=MITCHELL_FILTER; switch(filter){ case BOX_FILTER: filterf=&KisScaleVisitor::box_filter; fwidth=box_support; break; case TRIANGLE_FILTER: filterf=&KisScaleVisitor::triangle_filter; fwidth=triangle_support; break; case BELL_FILTER: filterf=&KisScaleVisitor::bell_filter; fwidth=bell_support; break; case B_SPLINE_FILTER: filterf=&KisScaleVisitor::B_spline_filter; fwidth=B_spline_support; break; case FILTER: filterf=&KisScaleVisitor::filter; fwidth=filter_support; break; case LANCZOS3_FILTER: filterf=&KisScaleVisitor::Lanczos3_filter; fwidth=Lanczos3_support; break; case MITCHELL_FILTER: filterf=&KisScaleVisitor::Mitchell_filter; fwidth=Mitchell_support; break; } KisTileMgrSP tm = new KisTileMgr(m_dev -> colorStrategy() -> depth(), targetW, targetH); QUANTUM * newData = new QUANTUM[targetW * targetH * m_dev -> depth() * sizeof(QUANTUM)]; int n; /* pixel number */ double center, left, right; /* filter calculation variables */ double m_width, fscale, weight[m_dev -> depth()]; /* filter calculation variables */ QUANTUM *pel = new QUANTUM[m_dev -> depth() * sizeof(QUANTUM)]; QUANTUM *pel2 = new QUANTUM[m_dev -> depth() * sizeof(QUANTUM)]; bool bPelDelta[m_dev -> depth()]; CLIST *contribY; /* array of contribution lists */ CLIST contribX; int nRet = -1; const Q_INT32 BLACK_PIXEL=0; const Q_INT32 WHITE_PIXEL=255; // create intermediate column to hold horizontal dst column zoom QUANTUM * tmp = new QUANTUM[m_dev -> height() * m_dev -> depth() * sizeof(QUANTUM)]; /* Build y weights */ /* pre-calculate filter contributions for a column */ contribY = (CLIST *)calloc(targetH, sizeof(CLIST)); int k; if(yscale < 1.0) { m_width = fwidth / yscale; fscale = 1.0 / yscale; for(int y = 0; y < targetH; y++) { contribY[y].n = 0; contribY[y].p = (CONTRIB *)calloc((int) (m_width * 2 + 1), sizeof(CONTRIB)); center = (double) y / yscale; left = ceil(center - m_width); right = floor(center + m_width); for(int xx = (int)left; xx <= right; xx++) { weight[0] = center - (double) xx; weight[0] = (this->*filterf)(weight[0] / fscale) / fscale; if(xx < 0) { n = -xx; } else if(xx >= m_dev -> height()) { n = (m_dev -> height() - xx) + m_dev -> height() - 1; } else { n = xx; } k = contribY[y].n++; contribY[y].p[k].m_pixel = n; contribY[y].p[k].m_weight = weight[0]; } } } else { for(int y = 0; y < targetH; y++) { contribY[y].n = 0; contribY[y].p = (CONTRIB *)calloc((int) (fwidth * 2 + 1), sizeof(CONTRIB)); center = (double) y / yscale; left = ceil(center - fwidth); right = floor(center + fwidth); for(int xx = (int)left; xx <= right; xx++) { weight[0] = center - (double) xx; weight[0] = (this->*filterf)(weight[0]); if(xx < 0) { n = -xx; } else if(xx >= m_dev -> height()) { n = (m_dev -> height() - xx) + m_dev -> height() - 1; } else { n = xx; } k = contribY[y].n++; contribY[y].p[k].m_pixel = n; contribY[y].p[k].m_weight = weight[0]; } } } for(int x = 0; x < targetW; x++) { calc_x_contrib(&contribX, xscale, fwidth, targetW, m_dev -> width(), filterf, x); /* Apply horz filter to make dst column in tmp. */ for(int y = 0; y < m_dev -> height(); y++) { for(int channel = 0; channel < m_dev -> depth(); channel++){ weight[channel] = 0.0; bPelDelta[channel] = FALSE; } m_dev -> tiles() -> readPixelData(contribX.p[0].m_pixel, y, contribX.p[0].m_pixel, y, pel, m_dev -> depth()); for(int xx = 0; xx < contribX.n; xx++) { if (!(contribX.p[xx].m_pixel < 0 || contribX.p[xx].m_pixel >= m_dev -> width())){ m_dev -> tiles()->readPixelData(contribX.p[xx].m_pixel, y, contribX.p[xx].m_pixel, y, pel2, m_dev -> depth()); for(int channel = 0; channel < m_dev -> depth(); channel++) { if(pel2[channel] != pel[channel]) bPelDelta[channel] = TRUE; weight[channel] += pel2[channel] * contribX.p[xx].m_weight; } } } for(int channel = 0; channel < m_dev -> depth(); channel++){ weight[channel] = bPelDelta[channel] ? static_cast(qRound(weight[channel])) : pel[channel]; tmp[y*m_dev -> depth()+channel] = static_cast(CLAMP(weight[channel], BLACK_PIXEL, WHITE_PIXEL)); } } /* next row in temp column */ free(contribX.p); /* The temp column has been built. Now stretch it vertically into dst column. */ for(int y = 0; y < targetH; y++) { for(int channel = 0; channel < m_dev -> depth(); channel++){ weight[channel] = 0.0; bPelDelta[channel] = FALSE; pel[channel] = tmp[contribY[y].p[0].m_pixel*m_dev -> depth()+channel]; } for(int xx = 0; xx < contribY[y].n; xx++) { for(int channel = 0; channel < m_dev -> depth(); channel++){ pel2[channel] = tmp[contribY[y].p[xx].m_pixel*m_dev -> depth()+channel]; if(pel2[channel] != pel[channel]) bPelDelta[channel] = TRUE; weight[channel] += pel2[channel] * contribY[y].p[xx].m_weight; } } for(int channel = 0; channel < m_dev -> depth(); channel++){ weight[channel] = bPelDelta[channel] ? static_cast(qRound(weight[channel])) : pel[channel]; int currentPos = (y*targetW+x) * m_dev -> depth(); // try to be at least a little efficient if (weight[channel]<0) newData[currentPos + channel] = 0; else if (weight[channel]>255) newData[currentPos + channel] = 255; else newData[currentPos + channel] = (uchar)weight[channel]; } } /* next dst row */ } /* next dst column */ tm -> writePixelData(0, 0, targetW - 1, targetH - 1, newData, targetW * m_dev -> depth()); m_dev -> setTiles(tm); // Also sets width and height correctly nRet = 0; /* success */ free(tmp); /* free the memory allocated for vertical filter weights */ for(int y = 0; y < targetH; y++) free(contribY[y].p); free(contribY); //return nRet; return; } int KisScaleVisitor::calc_x_contrib(CLIST *contribX, double xscale, double fwidth, int /*dstwidth*/, int srcwidth, double (KisScaleVisitor::*filterf)(double), Q_INT32 x) { //CLIST* contribX: receiver of contrib info //double xscale: horizontal zooming scale //double fwidth: Filter sampling width //int dstwidth: Target bitmap width //int srcwidth: Source bitmap width //double (*filterf)(double): Filter proc //int i: Pixel column in source bitmap being processed double width; double fscale; double center, left, right; double weight; Q_INT32 k, n; if(xscale < 1.0) { /* Shrinking image */ width = fwidth / xscale; fscale = 1.0 / xscale; contribX->n = 0; contribX->p = (CONTRIB *)calloc((int) (width * 2 + 1), sizeof(CONTRIB)); center = (double) x / xscale; left = ceil(center - width); right = floor(center + width); for(int xx = (int)left; xx <= right; ++xx) { weight = center - (double) xx; weight = (this->*filterf)(weight / fscale) / fscale; if(xx < 0) n = -xx; else if(xx >= srcwidth) n = (srcwidth - xx) + srcwidth - 1; else n = xx; k = contribX->n++; contribX->p[k].m_pixel = n; contribX->p[k].m_weight = weight; } } else { /* Expanding image */ contribX->n = 0; contribX->p = (CONTRIB *)calloc((int) (fwidth * 2 + 1), sizeof(CONTRIB)); center = (double) x / xscale; left = ceil(center - fwidth); right = floor(center + fwidth); for(int xx = (int)left; xx <= right; ++xx) { weight = center - (double) xx; weight = (this->*filterf)(weight); if(xx < 0) { n = -xx; } else if(xx >= srcwidth) { n = (srcwidth - xx) + srcwidth - 1; } else { n = xx; } k = contribX->n++; contribX->p[k].m_pixel = n; contribX->p[k].m_weight = weight; } } return 0; } /* calc_x_contrib */ /* Filter function definitions */ double KisScaleVisitor::filter(double t) { /* f(t) = 2|t|^3 - 3|t|^2 + 1, -1 <= t <= 1 */ if(t < 0.0) t = -t; if(t < 1.0) return((2.0 * t - 3.0) * t * t + 1.0); return(0.0); } double KisScaleVisitor::box_filter(double t) { if((t > -0.5) && (t <= 0.5)) return(1.0); return(0.0); } double KisScaleVisitor::triangle_filter(double t) { if(t < 0.0) t = -t; if(t < 1.0) return(1.0 - t); return(0.0); } double KisScaleVisitor::bell_filter(double t) { if(t < 0) t = -t; if(t < .5) return(.75 - (t * t)); if(t < 1.5) { t = (t - 1.5); return(.5 * (t * t)); } return(0.0); } double KisScaleVisitor::B_spline_filter(double t) { double tt; if(t < 0) t = -t; if(t < 1) { tt = t * t; return((.5 * tt * t) - tt + (2.0 / 3.0)); } else if(t < 2) { t = 2 - t; return((1.0 / 6.0) * (t * t * t)); } return(0.0); } double KisScaleVisitor::sinc(double x) { const double pi=3.1415926535897932385; x *= pi; if(x != 0) return(sin(x) / x); return(1.0); } double KisScaleVisitor::Lanczos3_filter(double t) { if(t < 0) t = -t; if(t < 3.0) return(sinc(t) * sinc(t/3.0)); return(0.0); } double KisScaleVisitor::Mitchell_filter(double t) { const double B=1.0/3.0; const double C=1.0/3.0; double tt; tt = t * t; if(t < 0) t = -t; if(t < 1.0) { t = (((12.0 - 9.0 * B - 6.0 * C) * (t * tt)) + ((-18.0 + 12.0 * B + 6.0 * C) * tt) + (6.0 - 2 * B)); return(t / 6.0); } else if(t < 2.0) { t = (((-1.0 * B - 6.0 * C) * (t * tt)) + ((6.0 * B + 30.0 * C) * tt) + ((-12.0 * B - 48.0 * C) * t) + (8.0 * B + 24 * C)); return(t / 6.0); } return(0.0); } --Boundary-00=_3gTUBfyLblI6mZa Content-Type: text/x-diff; charset="us-ascii"; name="mydiff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="mydiff" ? mydiff ? core/kis_scale_visitor.cc ? core/kis_scale_visitor.h Index: core/Makefile.am =================================================================== RCS file: /home/kde/koffice/krita/core/Makefile.am,v retrieving revision 1.111 diff -u -3 -u -p -r1.111 Makefile.am --- core/Makefile.am 21 Sep 2004 09:41:44 -0000 1.111 +++ core/Makefile.am 22 Sep 2004 08:22:37 -0000 @@ -72,8 +72,8 @@ libkritacore_la_SOURCES = kis_paint_devi kis_filter.cc \ kis_plugin_registry.cc \ kis_filter_registry.cc \ - kis_selection_manager.cc - + kis_selection_manager.cc \ + kis_scale_visitor.cc noinst_HEADERS = kis_paint_device.h \ kis_layer.h \ @@ -111,8 +111,9 @@ noinst_HEADERS = kis_paint_device.h \ kis_matrix.h \ kis_filter.h \ kis_filter_registry.h \ - kis_selection_manager.h - + kis_selection_manager.h \ + kis_scale_visitor.h + libkritacore_la_METASOURCES = AUTO libkritacore_la_LDFLAGS = $(all_libraries) SUBDIRS = tiles builder strategy color_strategy paintop resources tool Index: core/kis_paint_device.cc =================================================================== RCS file: /home/kde/koffice/krita/core/kis_paint_device.cc,v retrieving revision 1.98 diff -u -3 -u -p -r1.98 kis_paint_device.cc --- core/kis_paint_device.cc 20 Sep 2004 18:21:52 -0000 1.98 +++ core/kis_paint_device.cc 22 Sep 2004 08:22:38 -0000 @@ -307,355 +307,16 @@ void KisPaintDevice::resize(Q_INT32 w, Q painter.end(); } -void KisPaintDevice::scale(double xscale, double yscale) +void KisPaintDevice::accept(KisScaleVisitor& visitor) { - - //define filter supports - const double filter_support=1.0; - const double box_support=0.5; - const double triangle_support=1.0; - const double bell_support=1.5; - const double B_spline_support=2.0; - const double Lanczos3_support=3.0; - const double Mitchell_support=2.0; - - double (KisPaintDevice::*filterf)(double) = &KisPaintDevice::Mitchell_filter; //pointer to filter function - double fwidth; - - // target image data - Q_INT32 targetW; - Q_INT32 targetH; - - // compute size of target image - // (this bit seems to be mostly from QImage.xForm) - QWMatrix scale_matrix; - scale_matrix.scale(xscale, yscale); - scale_matrix = QPixmap::trueMatrix( scale_matrix, width(), height() ); - if ( scale_matrix.m11() == 1.0F && scale_matrix.m22() == 1.0F ) { - kdDebug() << "Identity matrix, do nothing.\n"; - return; - } - targetW = qRound( scale_matrix.m11() * width() ); - targetH = qRound( scale_matrix.m22() * height() ); - targetW = QABS( targetW ); - targetH = QABS( targetH ); - - //set filter type - enum filterType { - BOX_FILTER, - TRIANGLE_FILTER, - BELL_FILTER, - B_SPLINE_FILTER, - FILTER, - LANCZOS3_FILTER, - MITCHELL_FILTER - }; - filterType filter=MITCHELL_FILTER; - switch(filter){ - case BOX_FILTER: filterf=&KisPaintDevice::box_filter; fwidth=box_support; break; - case TRIANGLE_FILTER: filterf=&KisPaintDevice::triangle_filter; fwidth=triangle_support; break; - case BELL_FILTER: filterf=&KisPaintDevice::bell_filter; fwidth=bell_support; break; - case B_SPLINE_FILTER: filterf=&KisPaintDevice::B_spline_filter; fwidth=B_spline_support; break; - case FILTER: filterf=&KisPaintDevice::filter; fwidth=filter_support; break; - case LANCZOS3_FILTER: filterf=&KisPaintDevice::Lanczos3_filter; fwidth=Lanczos3_support; break; - case MITCHELL_FILTER: filterf=&KisPaintDevice::Mitchell_filter; fwidth=Mitchell_support; break; - } - - KisTileMgrSP tm = new KisTileMgr(colorStrategy() -> depth(), targetW, targetH); - QUANTUM * newData = new QUANTUM[targetW * targetH * depth() * sizeof(QUANTUM)]; - int n; /* pixel number */ - double center, left, right; /* filter calculation variables */ - double m_width, fscale, weight[depth()]; /* filter calculation variables */ - QUANTUM *pel = new QUANTUM[depth() * sizeof(QUANTUM)]; - QUANTUM *pel2 = new QUANTUM[depth() * sizeof(QUANTUM)]; - bool bPelDelta[depth()]; - CLIST *contribY; /* array of contribution lists */ - CLIST contribX; - int nRet = -1; - const Q_INT32 BLACK_PIXEL=0; - const Q_INT32 WHITE_PIXEL=255; - - - // create intermediate column to hold horizontal dst column zoom - QUANTUM * tmp = new QUANTUM[height() * depth() * sizeof(QUANTUM)]; - - /* Build y weights */ - /* pre-calculate filter contributions for a column */ - contribY = (CLIST *)calloc(targetH, sizeof(CLIST)); - int k; - if(yscale < 1.0) - { - m_width = fwidth / yscale; - fscale = 1.0 / yscale; - for(int y = 0; y < targetH; y++) - { - contribY[y].n = 0; - contribY[y].p = (CONTRIB *)calloc((int) (m_width * 2 + 1), sizeof(CONTRIB)); - center = (double) y / yscale; - left = ceil(center - m_width); - right = floor(center + m_width); - for(int xx = (int)left; xx <= right; xx++) { - weight[0] = center - (double) xx; - weight[0] = (this->*filterf)(weight[0] / fscale) / fscale; - if(xx < 0) { - n = -xx; - } else if(xx >= height()) { - n = (height() - xx) + height() - 1; - } else { - n = xx; - } - k = contribY[y].n++; - contribY[y].p[k].m_pixel = n; - contribY[y].p[k].m_weight = weight[0]; - } - } - } else { - for(int y = 0; y < targetH; y++) { - contribY[y].n = 0; - contribY[y].p = (CONTRIB *)calloc((int) (fwidth * 2 + 1), sizeof(CONTRIB)); - center = (double) y / yscale; - left = ceil(center - fwidth); - right = floor(center + fwidth); - for(int xx = (int)left; xx <= right; xx++) { - weight[0] = center - (double) xx; - weight[0] = (this->*filterf)(weight[0]); - if(xx < 0) { - n = -xx; - } else if(xx >= height()) { - n = (height() - xx) + height() - 1; - } else { - n = xx; - } - k = contribY[y].n++; - contribY[y].p[k].m_pixel = n; - contribY[y].p[k].m_weight = weight[0]; - } - } - } - - - for(int x = 0; x < targetW; x++) - { - calc_x_contrib(&contribX, xscale, fwidth, targetW, width(), filterf, x); - /* Apply horz filter to make dst column in tmp. */ - for(int y = 0; y < height(); y++) - { - for(int channel = 0; channel < depth(); channel++){ - weight[channel] = 0.0; - bPelDelta[channel] = FALSE; - } - tiles()->readPixelData(contribX.p[0].m_pixel, y, contribX.p[0].m_pixel, y, pel, depth()); - for(int xx = 0; xx < contribX.n; xx++) - { - if (!(contribX.p[xx].m_pixel < 0 || contribX.p[xx].m_pixel >= width())){ - tiles()->readPixelData(contribX.p[xx].m_pixel, y, contribX.p[xx].m_pixel, y, pel2, depth()); - for(int channel = 0; channel < depth(); channel++) - { - if(pel2[channel] != pel[channel]) bPelDelta[channel] = TRUE; - weight[channel] += pel2[channel] * contribX.p[xx].m_weight; - } - } - } - - for(int channel = 0; channel < depth(); channel++){ - weight[channel] = bPelDelta[channel] ? static_cast(qRound(weight[channel])) : pel[channel]; - tmp[y*depth()+channel] = static_cast(CLAMP(weight[channel], BLACK_PIXEL, WHITE_PIXEL)); - } - } /* next row in temp column */ - free(contribX.p); - - /* The temp column has been built. Now stretch it - vertically into dst column. */ - for(int y = 0; y < targetH; y++) - { - for(int channel = 0; channel < depth(); channel++){ - weight[channel] = 0.0; - bPelDelta[channel] = FALSE; - pel[channel] = tmp[contribY[y].p[0].m_pixel*depth()+channel]; - } - for(int xx = 0; xx < contribY[y].n; xx++) - { - for(int channel = 0; channel < depth(); channel++){ - pel2[channel] = tmp[contribY[y].p[xx].m_pixel*depth()+channel]; - if(pel2[channel] != pel[channel]) bPelDelta[channel] = TRUE; - weight[channel] += pel2[channel] * contribY[y].p[xx].m_weight; - } - } - for(int channel = 0; channel < depth(); channel++){ - weight[channel] = bPelDelta[channel] ? static_cast(qRound(weight[channel])) : pel[channel]; - int currentPos = (y*targetW+x) * depth(); // try to be at least a little efficient - if (weight[channel]<0) newData[currentPos + channel] = 0; - else if (weight[channel]>255) newData[currentPos + channel] = 255; - else newData[currentPos + channel] = (uchar)weight[channel]; - } - } /* next dst row */ - } /* next dst column */ - tm -> writePixelData(0, 0, targetW - 1, targetH - 1, newData, targetW * depth()); - setTiles(tm); // Also sets width and height correctly - nRet = 0; /* success */ - - free(tmp); - - /* free the memory allocated for vertical filter weights */ - for(int y = 0; y < targetH; y++) - free(contribY[y].p); - free(contribY); - - //return nRet; - return; -} - -int KisPaintDevice::calc_x_contrib(CLIST *contribX, double xscale, double fwidth, int /*dstwidth*/, int srcwidth, double (KisPaintDevice::*filterf)(double), Q_INT32 x) -{ - //CLIST* contribX: receiver of contrib info - //double xscale: horizontal zooming scale - //double fwidth: Filter sampling width - //int dstwidth: Target bitmap width - //int srcwidth: Source bitmap width - //double (*filterf)(double): Filter proc - //int i: Pixel column in source bitmap being processed - - double width; - double fscale; - double center, left, right; - double weight; - Q_INT32 k, n; - - if(xscale < 1.0) - { - /* Shrinking image */ - width = fwidth / xscale; - fscale = 1.0 / xscale; - - contribX->n = 0; - contribX->p = (CONTRIB *)calloc((int) (width * 2 + 1), sizeof(CONTRIB)); - center = (double) x / xscale; - left = ceil(center - width); - right = floor(center + width); - for(int xx = (int)left; xx <= right; ++xx) - { - weight = center - (double) xx; - weight = (this->*filterf)(weight / fscale) / fscale; - if(xx < 0) - n = -xx; - else if(xx >= srcwidth) - n = (srcwidth - xx) + srcwidth - 1; - else - n = xx; - - k = contribX->n++; - contribX->p[k].m_pixel = n; - contribX->p[k].m_weight = weight; - } - } - else - { - /* Expanding image */ - contribX->n = 0; - contribX->p = (CONTRIB *)calloc((int) (fwidth * 2 + 1), sizeof(CONTRIB)); - center = (double) x / xscale; - left = ceil(center - fwidth); - right = floor(center + fwidth); - - for(int xx = (int)left; xx <= right; ++xx) - { - weight = center - (double) xx; - weight = (this->*filterf)(weight); - if(xx < 0) { - n = -xx; - } else if(xx >= srcwidth) { - n = (srcwidth - xx) + srcwidth - 1; - } else { - n = xx; - } - k = contribX->n++; - contribX->p[k].m_pixel = n; - contribX->p[k].m_weight = weight; - } - } - return 0; -} /* calc_x_contrib */ - -/* Filter function definitions */ - -double KisPaintDevice::filter(double t) -{ - /* f(t) = 2|t|^3 - 3|t|^2 + 1, -1 <= t <= 1 */ - if(t < 0.0) t = -t; - if(t < 1.0) return((2.0 * t - 3.0) * t * t + 1.0); - return(0.0); + visitor.visitKisPaintDevice(this); } -double KisPaintDevice::box_filter(double t) +void KisPaintDevice::scale(double xscale, double yscale) { - if((t > -0.5) && (t <= 0.5)) return(1.0); - return(0.0); -} - -double KisPaintDevice::triangle_filter(double t) -{ - if(t < 0.0) t = -t; - if(t < 1.0) return(1.0 - t); - return(0.0); -} - -double KisPaintDevice::bell_filter(double t) -{ - if(t < 0) t = -t; - if(t < .5) return(.75 - (t * t)); - if(t < 1.5) { - t = (t - 1.5); - return(.5 * (t * t)); - } - return(0.0); -} - -double KisPaintDevice::B_spline_filter(double t) -{ - double tt; - - if(t < 0) t = -t; - if(t < 1) { - tt = t * t; - return((.5 * tt * t) - tt + (2.0 / 3.0)); - } else if(t < 2) { - t = 2 - t; - return((1.0 / 6.0) * (t * t * t)); - } - return(0.0); -} - -double KisPaintDevice::sinc(double x) -{ - const double pi=3.1415926535897932385; - x *= pi; - if(x != 0) return(sin(x) / x); - return(1.0); -} - -double KisPaintDevice::Lanczos3_filter(double t) -{ - if(t < 0) t = -t; - if(t < 3.0) return(sinc(t) * sinc(t/3.0)); - return(0.0); -} - -double KisPaintDevice::Mitchell_filter(double t) -{ - const double B=1.0/3.0; - const double C=1.0/3.0; - double tt; - - tt = t * t; - if(t < 0) t = -t; - if(t < 1.0) { - t = (((12.0 - 9.0 * B - 6.0 * C) * (t * tt)) + ((-18.0 + 12.0 * B + 6.0 * C) * tt) + (6.0 - 2 * B)); - return(t / 6.0); - } else if(t < 2.0) { - t = (((-1.0 * B - 6.0 * C) * (t * tt)) + ((6.0 * B + 30.0 * C) * tt) + ((-12.0 * B - 48.0 * C) * t) + (8.0 * B + 24 * C)); - return(t / 6.0); - } - return(0.0); + KisScaleVisitor visitor; + accept(visitor); + visitor.scale(xscale,yscale); } void KisPaintDevice::rotate(double angle) Index: core/kis_paint_device.h =================================================================== RCS file: /home/kde/koffice/krita/core/kis_paint_device.h,v retrieving revision 1.77 diff -u -3 -u -p -r1.77 kis_paint_device.h --- core/kis_paint_device.h 20 Sep 2004 18:21:52 -0000 1.77 +++ core/kis_paint_device.h 22 Sep 2004 08:22:38 -0000 @@ -34,6 +34,7 @@ #include "kistilemgr.h" #include "kis_strategy_colorspace.h" #include "kispixeldata.h" +#include "kis_scale_visitor.h" class QImage; class QSize; @@ -44,6 +45,7 @@ class QWMatrix; class KisTileCommand; class KisIteratorLineQuantum; class KisIteratorLinePixel; +class KisScaleVisitor; /** * Class modelled on QPaintDevice. @@ -52,19 +54,6 @@ class KisPaintDevice : public QObject, p Q_OBJECT typedef KisRenderInterface super; - /* Structs for the image rescaling routine */ - struct CONTRIB { - Q_INT32 m_pixel; - double m_weight; - }; - - struct CLIST { - Q_INT32 n; //number of contributors - CONTRIB *p; //pointer to list of contributions - }; - - - public: KisPaintDevice(Q_INT32 width, Q_INT32 height, KisStrategyColorSpaceSP colorStrategy, @@ -290,26 +279,6 @@ private: KisPaintDevice& operator=(const KisPaintDevice&); void init(); - /** - * calc_x_contrib() - * - * Calculates the filter weights for a single target column. - * contribX->p must be freed afterwards. - * - * Returns -1 if error, 0 otherwise. - */ - int calc_x_contrib(CLIST *contribX, double xcale, double fwidth, int dstwidth, int srcwidth, double (KisPaintDevice::*filterf)(double), Q_INT32 i); - - /* scaling filter function definitions */ - double filter(double t); - double box_filter(double t); - double triangle_filter(double t); - double bell_filter(double t); - double B_spline_filter(double t); - double sinc(double x); - double Lanczos3_filter(double t); - double Mitchell_filter(double t); - private: KisImage *m_owner; KisTileMgrSP m_tiles; @@ -327,10 +296,7 @@ private: CompositeOp m_compositeOp; KisStrategyColorSpaceSP m_colorStrategy; - - CLIST * contrib; //array of contribution lists - - + void accept(KisScaleVisitor &); }; --Boundary-00=_3gTUBfyLblI6mZa Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ kimageshop mailing list kimageshop@kde.org https://mail.kde.org/mailman/listinfo/kimageshop --Boundary-00=_3gTUBfyLblI6mZa--