Back to index

scribus-ng  1.3.4.dfsg+svn20071115
scimage.cpp
Go to the documentation of this file.
00001 /*
00002 For general Scribus (>=1.3.2) copyright and licensing information please refer
00003 to the COPYING file provided with the program. Following this notice may exist
00004 a copyright and/or license notice that predates the release of Scribus 1.3.2
00005 for which a new license (GPL+exception) is in place.
00006 */
00007 #include "scimage.h"
00008 #include "scribus.h"
00009 #include "scpaths.h"
00010 #include "scribuscore.h"
00011 #include "scimgdataloader_gimp.h"
00012 #include "scimgdataloader_jpeg.h"
00013 #include "scimgdataloader_pdf.h"
00014 #include "scimgdataloader_ps.h"
00015 #include "scimgdataloader_psd.h"
00016 #include "scimgdataloader_pdf.h"
00017 #include "scimgdataloader_qt.h"
00018 #include "scimgdataloader_tiff.h"
00019 #include <qmessagebox.h>
00020 #include <qtextstream.h>
00021 #include <memory>
00022 #include <cassert>
00023 #include CMS_INC
00024 #include "cmsutil.h"
00025 #include "gsutil.h"
00026 #include "exif.h"
00027 #include "commonstrings.h"
00028 #include "colorutil.h"
00029 #include "util.h"
00030 #include "rawimage.h"
00031 #include "sccolorengine.h"
00032 
00033 using namespace std;
00034 
00035 typedef struct my_error_mgr
00036 {
00037        struct jpeg_error_mgr pub;            /* "public" fields */
00038        jmp_buf setjmp_buffer;  /* for return to caller */
00039 }
00040 *my_error_ptr;
00041 
00042 static void my_error_exit (j_common_ptr cinfo)
00043 {
00044        my_error_ptr myerr = (my_error_ptr) cinfo->err;
00045        (*cinfo->err->output_message) (cinfo);
00046        longjmp (myerr->setjmp_buffer, 1);
00047 }
00048 
00049 ScImage::ScImage(const QImage & image) : QImage(image)
00050 {
00051        initialize();
00052 }
00053 
00054 
00055 // ScImage will use implicit sharing:
00056 ScImage::ScImage(const ScImage & image) : QImage(image.copy())
00057 {
00058        initialize();
00059 }
00060 
00061 
00062 ScImage::ScImage() : QImage()
00063 {
00064        initialize();
00065 }
00066 
00067 ScImage::ScImage( int width, int height ) : QImage( width, height, 32 )
00068 {
00069        initialize();
00070 }
00071 
00072 const QImage& ScImage::qImage()
00073 {
00074        return *this;
00075 }
00076 
00077 QImage* ScImage::qImagePtr()
00078 {
00079        return this;
00080 }
00081 
00082 QImage ScImage::smoothScale(int h, int w, QImage::ScaleMode mode) const
00083 {
00084        return QImage::smoothScale(h,w,mode);
00085 }
00086 
00087 
00088 void ScImage::initialize()
00089 {
00090        imgInfo.xres = 72;
00091        imgInfo.yres = 72;
00092        imgInfo.colorspace = 0;
00093        imgInfo.valid = false;
00094        imgInfo.isRequest = false;
00095        imgInfo.isEmbedded = false;
00096        imgInfo.progressive = false;
00097        imgInfo.exifDataValid = false;
00098        imgInfo.lowResType = 1;
00099        imgInfo.lowResScale = 1.0;
00100        imgInfo.PDSpathData.clear();
00101        imgInfo.RequestProps.clear();
00102        imgInfo.clipPath = "";
00103        imgInfo.usedPath = "";
00104        imgInfo.layerInfo.clear();
00105        imgInfo.duotoneColors.clear();
00106        imgInfo.exifInfo.cameraName = "";
00107        imgInfo.exifInfo.cameraVendor = "";
00108        imgInfo.exifInfo.thumbnail = QImage();
00109        imgInfo.BBoxX = 0;
00110        imgInfo.BBoxH = 0;
00111 }
00112 
00113 ScImage::~ScImage()
00114 {
00115        curveTable.resize(0);
00116 }
00117 
00118 void ScImage::applyEffect(QValueList<imageEffect> effectsList, ColorList& colors, bool cmyk)
00119 {
00120        ScribusDoc* doc = colors.document();
00121        if (effectsList.count() != 0)
00122        {
00123               for (uint a = 0; a < effectsList.count(); ++a)
00124               {
00125                      if ((*effectsList.at(a)).effectCode == EF_INVERT)
00126                             invert(cmyk);
00127                      if ((*effectsList.at(a)).effectCode == EF_GRAYSCALE)
00128                             toGrayscale(cmyk);
00129                      if ((*effectsList.at(a)).effectCode == EF_COLORIZE)
00130                      {
00131                             QString tmpstr = (*effectsList.at(a)).effectParameters;
00132                             QString col = CommonStrings::None;
00133                             int shading = 100;
00134                             QTextStream fp(&tmpstr, IO_ReadOnly);
00135                             fp >> col;
00136                             fp >> shading;
00137                             colorize(doc, colors[col], shading, cmyk);
00138                      }
00139                      if ((*effectsList.at(a)).effectCode == EF_BRIGHTNESS)
00140                      {
00141                             QString tmpstr = (*effectsList.at(a)).effectParameters;
00142                             int brightnessValue = 0;
00143                             QTextStream fp(&tmpstr, IO_ReadOnly);
00144                             fp >> brightnessValue;
00145                             brightness(brightnessValue, cmyk);
00146                      }
00147                      if ((*effectsList.at(a)).effectCode == EF_CONTRAST)
00148                      {
00149                             QString tmpstr = (*effectsList.at(a)).effectParameters;
00150                             int contrastValue = 0;
00151                             QTextStream fp(&tmpstr, IO_ReadOnly);
00152                             fp >> contrastValue;
00153                             contrast(contrastValue, cmyk);
00154                      }
00155                      if ((*effectsList.at(a)).effectCode == EF_SHARPEN)
00156                      {
00157                             QString tmpstr = (*effectsList.at(a)).effectParameters;
00158                             double radius, sigma;
00159                             QTextStream fp(&tmpstr, IO_ReadOnly);
00160                             fp >> radius;
00161                             fp >> sigma;
00162                             sharpen(radius, sigma);
00163                      }
00164                      if ((*effectsList.at(a)).effectCode == EF_BLUR)
00165                      {
00166                             QString tmpstr = (*effectsList.at(a)).effectParameters;
00167                             double radius, sigma;
00168                             QTextStream fp(&tmpstr, IO_ReadOnly);
00169                             fp >> radius;
00170                             fp >> sigma;
00171                             blur(static_cast<int>(radius));
00172                      }
00173                      if ((*effectsList.at(a)).effectCode == EF_SOLARIZE)
00174                      {
00175                             QString tmpstr = (*effectsList.at(a)).effectParameters;
00176                             double sigma;
00177                             QTextStream fp(&tmpstr, IO_ReadOnly);
00178                             fp >> sigma;
00179                             solarize(sigma, cmyk);
00180                      }
00181                      if ((*effectsList.at(a)).effectCode == EF_DUOTONE)
00182                      {
00183                             QString tmpstr = (*effectsList.at(a)).effectParameters;
00184                             QString col1 = CommonStrings::None;
00185                             int shading1 = 100;
00186                             QString col2 = CommonStrings::None;
00187                             int shading2 = 100;
00188                             QTextStream fp(&tmpstr, IO_ReadOnly);
00189                             col1 = fp.readLine();
00190                             col2 = fp.readLine();
00191                             fp >> shading1;
00192                             fp >> shading2;
00193                             int numVals;
00194                             double xval, yval;
00195                             FPointArray curve1;
00196                             curve1.resize(0);
00197                             fp >> numVals;
00198                             for (int nv = 0; nv < numVals; nv++)
00199                             {
00200                                    fp >> xval;
00201                                    fp >> yval;
00202                                    curve1.addPoint(xval, yval);
00203                             }
00204                             int lin1;
00205                             fp >> lin1;
00206                             FPointArray curve2;
00207                             curve2.resize(0);
00208                             fp >> numVals;
00209                             for (int nv = 0; nv < numVals; nv++)
00210                             {
00211                                    fp >> xval;
00212                                    fp >> yval;
00213                                    curve2.addPoint(xval, yval);
00214                             }
00215                             int lin2;
00216                             fp >> lin2;
00217                             duotone(doc, colors[col1], shading1, curve1, lin1, colors[col2], shading2, curve2, lin2, cmyk);
00218                      }
00219                      if ((*effectsList.at(a)).effectCode == EF_TRITONE)
00220                      {
00221                             QString tmpstr = (*effectsList.at(a)).effectParameters;
00222                             QString col1 = CommonStrings::None;
00223                             QString col2 = CommonStrings::None;
00224                             QString col3 = CommonStrings::None;
00225                             int shading1 = 100;
00226                             int shading2 = 100;
00227                             int shading3 = 100;
00228                             QTextStream fp(&tmpstr, IO_ReadOnly);
00229                             col1 = fp.readLine();
00230                             col2 = fp.readLine();
00231                             col3 = fp.readLine();
00232                             fp >> shading1;
00233                             fp >> shading2;
00234                             fp >> shading3;
00235                             int numVals;
00236                             double xval, yval;
00237                             FPointArray curve1;
00238                             curve1.resize(0);
00239                             fp >> numVals;
00240                             for (int nv = 0; nv < numVals; nv++)
00241                             {
00242                                    fp >> xval;
00243                                    fp >> yval;
00244                                    curve1.addPoint(xval, yval);
00245                             }
00246                             int lin1;
00247                             fp >> lin1;
00248                             FPointArray curve2;
00249                             curve2.resize(0);
00250                             fp >> numVals;
00251                             for (int nv = 0; nv < numVals; nv++)
00252                             {
00253                                    fp >> xval;
00254                                    fp >> yval;
00255                                    curve2.addPoint(xval, yval);
00256                             }
00257                             int lin2;
00258                             fp >> lin2;
00259                             FPointArray curve3;
00260                             curve3.resize(0);
00261                             fp >> numVals;
00262                             for (int nv = 0; nv < numVals; nv++)
00263                             {
00264                                    fp >> xval;
00265                                    fp >> yval;
00266                                    curve3.addPoint(xval, yval);
00267                             }
00268                             int lin3;
00269                             fp >> lin3;
00270                             tritone(doc, colors[col1], shading1, curve1, lin1, colors[col2], shading2, curve2, lin2, colors[col3], shading3, curve3, lin3, cmyk);
00271                      }
00272                      if ((*effectsList.at(a)).effectCode == EF_QUADTONE)
00273                      {
00274                             QString tmpstr = (*effectsList.at(a)).effectParameters;
00275                             QString col1 = CommonStrings::None;
00276                             QString col2 = CommonStrings::None;
00277                             QString col3 = CommonStrings::None;
00278                             QString col4 = CommonStrings::None;
00279                             int shading1 = 100;
00280                             int shading2 = 100;
00281                             int shading3 = 100;
00282                             int shading4 = 100;
00283                             QTextStream fp(&tmpstr, IO_ReadOnly);
00284                             col1 = fp.readLine();
00285                             col2 = fp.readLine();
00286                             col3 = fp.readLine();
00287                             col4 = fp.readLine();
00288                             fp >> shading1;
00289                             fp >> shading2;
00290                             fp >> shading3;
00291                             fp >> shading4;
00292                             int numVals;
00293                             double xval, yval;
00294                             FPointArray curve1;
00295                             curve1.resize(0);
00296                             fp >> numVals;
00297                             for (int nv = 0; nv < numVals; nv++)
00298                             {
00299                                    fp >> xval;
00300                                    fp >> yval;
00301                                    curve1.addPoint(xval, yval);
00302                             }
00303                             int lin1;
00304                             fp >> lin1;
00305                             FPointArray curve2;
00306                             curve2.resize(0);
00307                             fp >> numVals;
00308                             for (int nv = 0; nv < numVals; nv++)
00309                             {
00310                                    fp >> xval;
00311                                    fp >> yval;
00312                                    curve2.addPoint(xval, yval);
00313                             }
00314                             int lin2;
00315                             fp >> lin2;
00316                             FPointArray curve3;
00317                             curve3.resize(0);
00318                             fp >> numVals;
00319                             for (int nv = 0; nv < numVals; nv++)
00320                             {
00321                                    fp >> xval;
00322                                    fp >> yval;
00323                                    curve3.addPoint(xval, yval);
00324                             }
00325                             int lin3;
00326                             fp >> lin3;
00327                             FPointArray curve4;
00328                             curve4.resize(0);
00329                             fp >> numVals;
00330                             for (int nv = 0; nv < numVals; nv++)
00331                             {
00332                                    fp >> xval;
00333                                    fp >> yval;
00334                                    curve4.addPoint(xval, yval);
00335                             }
00336                             int lin4;
00337                             fp >> lin4;
00338                             quadtone(doc, colors[col1], shading1, curve1, lin1, colors[col2], shading2, curve2, lin2, colors[col3], shading3, curve3, lin3, colors[col4], shading4, curve4, lin4, cmyk);
00339                      }
00340                      if ((*effectsList.at(a)).effectCode == EF_GRADUATE)
00341                      {
00342                             QString tmpstr = (*effectsList.at(a)).effectParameters;
00343                             int numVals;
00344                             double xval, yval;
00345                             FPointArray curve;
00346                             curve.resize(0);
00347                             QTextStream fp(&tmpstr, IO_ReadOnly);
00348                             fp >> numVals;
00349                             for (int nv = 0; nv < numVals; nv++)
00350                             {
00351                                    fp >> xval;
00352                                    fp >> yval;
00353                                    curve.addPoint(xval, yval);
00354                             }
00355                             int lin;
00356                             fp >> lin;
00357                             doGraduate(curve, cmyk, lin);
00358                      }
00359               }
00360        }
00361 }
00362 /*
00363 void ScImage::liberateMemory(void **memory)
00364 {
00365        assert(memory != (void **)NULL);
00366        if(*memory == (void *)NULL)
00367               return;
00368        free(*memory);
00369        *memory=(void *) NULL;
00370 }
00371 */
00372 void ScImage::solarize(double factor, bool cmyk)
00373 {
00374        curveTable.resize(256);
00375        int fk = qRound(255 / factor);
00376        for (int i = 0; i < 256; ++i)
00377        {
00378               curveTable[i] = QMIN(255, static_cast<int>(i / fk) * fk);
00379        }
00380        applyCurve(cmyk);
00381 }
00382 
00383 // Stack Blur Algorithm by Mario Klingemann <mario@quasimondo.com>
00384 void ScImage::blur(int radius)
00385 {
00386     if (radius < 1) {
00387         return;
00388     }
00389 
00390     QRgb *pix = (QRgb*)bits();
00391     int w   = width();
00392     int h   = height();
00393     int wm  = w-1;
00394     int hm  = h-1;
00395     int wh  = w*h;
00396     int div = radius+radius+1;
00397 
00398     int *r = new int[wh];
00399     int *g = new int[wh];
00400     int *b = new int[wh];
00401     int *a = new int[wh];
00402     int rsum, gsum, bsum, asum, x, y, i, yp, yi, yw;
00403     QRgb p;
00404     int *vmin = new int[QMAX(w,h)];
00405 
00406     int divsum = (div+1)>>1;
00407     divsum *= divsum;
00408     int *dv = new int[256*divsum];
00409     for (i=0; i < 256*divsum; ++i) {
00410         dv[i] = (i/divsum);
00411     }
00412 
00413     yw = yi = 0;
00414 
00415     int **stack = new int*[div];
00416     for(int i = 0; i < div; ++i) {
00417         stack[i] = new int[4];
00418     }
00419 
00420 
00421     int stackpointer;
00422     int stackstart;
00423     int *sir;
00424     int rbs;
00425     int r1 = radius+1;
00426     int routsum, goutsum, boutsum, aoutsum;
00427     int rinsum, ginsum, binsum, ainsum;
00428 
00429     for (y = 0; y < h; ++y){
00430         rinsum = ginsum = binsum = ainsum
00431                = routsum = goutsum = boutsum = aoutsum
00432                = rsum = gsum = bsum = asum = 0;
00433         for(i =- radius; i <= radius; ++i) {
00434             p = pix[yi+QMIN(wm,QMAX(i,0))];
00435             sir = stack[i+radius];
00436             sir[0] = qRed(p);
00437             sir[1] = qGreen(p);
00438             sir[2] = qBlue(p);
00439             sir[3] = qAlpha(p);
00440             
00441             rbs = r1-abs(i);
00442             rsum += sir[0]*rbs;
00443             gsum += sir[1]*rbs;
00444             bsum += sir[2]*rbs;
00445             asum += sir[3]*rbs;
00446             
00447             if (i > 0){
00448                 rinsum += sir[0];
00449                 ginsum += sir[1];
00450                 binsum += sir[2];
00451                 ainsum += sir[3];
00452             } else {
00453                 routsum += sir[0];
00454                 goutsum += sir[1];
00455                 boutsum += sir[2];
00456                 aoutsum += sir[3];
00457             }
00458         }
00459         stackpointer = radius;
00460 
00461         for (x=0; x < w; ++x) {
00462 
00463             r[yi] = dv[rsum];
00464             g[yi] = dv[gsum];
00465             b[yi] = dv[bsum];
00466             a[yi] = dv[asum];
00467 
00468             rsum -= routsum;
00469             gsum -= goutsum;
00470             bsum -= boutsum;
00471             asum -= aoutsum;
00472 
00473             stackstart = stackpointer-radius+div;
00474             sir = stack[stackstart%div];
00475 
00476             routsum -= sir[0];
00477             goutsum -= sir[1];
00478             boutsum -= sir[2];
00479             aoutsum -= sir[3];
00480 
00481             if (y == 0) {
00482                 vmin[x] = QMIN(x+radius+1,wm);
00483             }
00484             p = pix[yw+vmin[x]];
00485 
00486             sir[0] = qRed(p);
00487             sir[1] = qGreen(p);
00488             sir[2] = qBlue(p);
00489             sir[3] = qAlpha(p);
00490 
00491             rinsum += sir[0];
00492             ginsum += sir[1];
00493             binsum += sir[2];
00494             ainsum += sir[3];
00495 
00496             rsum += rinsum;
00497             gsum += ginsum;
00498             bsum += binsum;
00499             asum += ainsum;
00500 
00501             stackpointer = (stackpointer+1)%div;
00502             sir = stack[(stackpointer)%div];
00503 
00504             routsum += sir[0];
00505             goutsum += sir[1];
00506             boutsum += sir[2];
00507             aoutsum += sir[3];
00508 
00509             rinsum -= sir[0];
00510             ginsum -= sir[1];
00511             binsum -= sir[2];
00512             ainsum -= sir[3];
00513 
00514             ++yi;
00515         }
00516         yw += w;
00517     }
00518     for (x=0; x < w; ++x){
00519         rinsum = ginsum = binsum = ainsum 
00520                = routsum = goutsum = boutsum = aoutsum 
00521                = rsum = gsum = bsum = asum = 0;
00522         
00523         yp =- radius * w;
00524         
00525         for(i=-radius; i <= radius; ++i) {
00526             yi=QMAX(0,yp)+x;
00527 
00528             sir = stack[i+radius];
00529 
00530             sir[0] = r[yi];
00531             sir[1] = g[yi];
00532             sir[2] = b[yi];
00533             sir[3] = a[yi];
00534 
00535             rbs = r1-abs(i);
00536 
00537             rsum += r[yi]*rbs;
00538             gsum += g[yi]*rbs;
00539             bsum += b[yi]*rbs;
00540             asum += a[yi]*rbs;
00541 
00542             if (i > 0) {
00543                 rinsum += sir[0];
00544                 ginsum += sir[1];
00545                 binsum += sir[2];
00546                 ainsum += sir[3];
00547             } else {
00548                 routsum += sir[0];
00549                 goutsum += sir[1];
00550                 boutsum += sir[2];
00551                 aoutsum += sir[3];
00552             }
00553 
00554             if (i < hm){
00555                 yp += w;
00556             }
00557         }
00558 
00559         yi = x;
00560         stackpointer = radius;
00561 
00562         for (y=0; y < h; ++y){
00563             pix[yi] = qRgba(dv[rsum], dv[gsum], dv[bsum], dv[asum]);
00564 
00565             rsum -= routsum;
00566             gsum -= goutsum;
00567             bsum -= boutsum;
00568             asum -= aoutsum;
00569 
00570             stackstart = stackpointer-radius+div;
00571             sir = stack[stackstart%div];
00572 
00573             routsum -= sir[0];
00574             goutsum -= sir[1];
00575             boutsum -= sir[2];
00576             aoutsum -= sir[3];
00577 
00578             if (x==0){
00579                 vmin[y] = QMIN(y+r1,hm)*w;
00580             }
00581             p = x+vmin[y];
00582 
00583             sir[0] = r[p];
00584             sir[1] = g[p];
00585             sir[2] = b[p];
00586             sir[3] = a[p];
00587 
00588             rinsum += sir[0];
00589             ginsum += sir[1];
00590             binsum += sir[2];
00591             ainsum += sir[3];
00592 
00593             rsum += rinsum;
00594             gsum += ginsum;
00595             bsum += binsum;
00596             asum += ainsum;
00597 
00598             stackpointer = (stackpointer+1)%div;
00599             sir = stack[stackpointer];
00600 
00601             routsum += sir[0];
00602             goutsum += sir[1];
00603             boutsum += sir[2];
00604             aoutsum += sir[3];
00605 
00606             rinsum -= sir[0];
00607             ginsum -= sir[1];
00608             binsum -= sir[2];
00609             ainsum -= sir[3];
00610 
00611             yi += w;
00612         }
00613     }
00614     delete [] r;
00615     delete [] g;
00616     delete [] b;
00617     delete [] a;
00618     delete [] vmin;
00619     delete [] dv;
00620 
00621     for(int i = 0; i < div; ++i) {
00622         delete [] stack[i];
00623     }
00624     delete [] stack;
00625 }
00626 
00627 bool ScImage::convolveImage(QImage *dest, const unsigned int order, const double *kernel)
00628 {
00629        long widthk;
00630        double red, green, blue, alpha;
00631        double normalize, *normal_kernel;
00632        register const double *k;
00633        register unsigned int *q;
00634        int x, y, mx, my, sx, sy;
00635        long i;
00636        int mcx, mcy;
00637        widthk = order;
00638        if((widthk % 2) == 0)
00639               return(false);
00640        normal_kernel = (double *)malloc(widthk*widthk*sizeof(double));
00641        if(!normal_kernel)
00642               return(false);
00643        dest->reset();
00644        dest->create(width(), height(), 32);
00645        normalize=0.0;
00646        for(i=0; i < (widthk*widthk); i++)
00647               normalize += kernel[i];
00648        if(fabs(normalize) <= 1.0e-12)
00649               normalize=1.0;
00650        normalize=1.0/normalize;
00651        for(i=0; i < (widthk*widthk); i++)
00652               normal_kernel[i] = normalize*kernel[i];
00653        unsigned int **jumpTablek = (unsigned int **)jumpTable();
00654        for(y=0; y < dest->height(); ++y)
00655        {
00656               sy = y-(widthk/2);
00657               q = (unsigned int *)dest->scanLine(y);
00658               for(x=0; x < dest->width(); ++x)
00659               {
00660                      k = normal_kernel;
00661                      red = green = blue = alpha = 0;
00662                      sy = y-(widthk/2);
00663                      for(mcy=0; mcy < widthk; ++mcy, ++sy)
00664                      {
00665                             my = sy < 0 ? 0 : sy > height()-1 ? height()-1 : sy;
00666                             sx = x+(-widthk/2);
00667                             for(mcx=0; mcx < widthk; ++mcx, ++sx)
00668                             {
00669                                    mx = sx < 0 ? 0 : sx > width()-1 ? width()-1 : sx;
00670                                    red += (*k)*(qRed(jumpTablek[my][mx])*257);
00671                                    green += (*k)*(qGreen(jumpTablek[my][mx])*257);
00672                                    blue += (*k)*(qBlue(jumpTablek[my][mx])*257);
00673                                    alpha += (*k)*(qAlpha(jumpTablek[my][mx])*257);
00674                                    ++k;
00675                             }
00676                      }
00677                      red = red < 0 ? 0 : red > 65535 ? 65535 : red+0.5;
00678                      green = green < 0 ? 0 : green > 65535 ? 65535 : green+0.5;
00679                      blue = blue < 0 ? 0 : blue > 65535 ? 65535 : blue+0.5;
00680                      alpha = alpha < 0 ? 0 : alpha > 65535 ? 65535 : alpha+0.5;
00681                      *q++ = qRgba((unsigned char)(red/257UL),
00682                                   (unsigned char)(green/257UL),
00683                                   (unsigned char)(blue/257UL),
00684                                   (unsigned char)(alpha/257UL));
00685               }
00686        }
00687        free(normal_kernel);
00688        return(true);
00689 }
00690 
00691 int ScImage::getOptimalKernelWidth(double radius, double sigma)
00692 {
00693        double normalize, value;
00694        long width;
00695        register long u;
00696        assert(sigma != 0.0);
00697        if(radius > 0.0)
00698               return((int)(2.0*ceil(radius)+1.0));
00699        for(width=5; ;)
00700        {
00701               normalize=0.0;
00702               for(u=(-width/2); u <= (width/2); u++)
00703                      normalize+=exp(-((double) u*u)/(2.0*sigma*sigma))/(2.50662827463100024161235523934010416269302368164062*sigma);
00704               u=width/2;
00705               value=exp(-((double) u*u)/(2.0*sigma*sigma))/(2.50662827463100024161235523934010416269302368164062*sigma)/normalize;
00706               if((long)(65535*value) <= 0)
00707                      break;
00708               width+=2;
00709        }
00710        return((int)width-2);
00711 }
00712 
00713 void ScImage::sharpen(double radius, double sigma)
00714 {
00715        double alpha, normalize, *kernel;
00716        int widthk;
00717        register long i, u, v;
00718        QImage dest;
00719        if(sigma == 0.0)
00720               return;
00721        widthk = getOptimalKernelWidth(radius, sigma);
00722        if(width() < widthk)
00723               return;
00724        kernel = (double *)malloc(widthk*widthk*sizeof(double));
00725        if(!kernel)
00726               return;
00727        i = 0;
00728        normalize=0.0;
00729        for (v=(-widthk/2); v <= (widthk/2); v++)
00730        {
00731               for (u=(-widthk/2); u <= (widthk/2); u++)
00732               {
00733                      alpha=exp(-((double) u*u+v*v)/(2.0*sigma*sigma));
00734                      kernel[i]=alpha/(2.0*3.14159265358979323846264338327950288419716939937510*sigma*sigma);
00735                      normalize+=kernel[i];
00736                      i++;
00737               }
00738        }
00739        kernel[i/2]=(-2.0)*normalize;
00740        convolveImage(&dest, widthk, kernel);
00741        free(kernel);
00742 //     liberateMemory((void **) &kernel);
00743        for( int yi=0; yi < dest.height(); ++yi )
00744        {
00745               QRgb *s = (QRgb*)(dest.scanLine( yi ));
00746               QRgb *d = (QRgb*)(scanLine( yi ));
00747               for(int xi=0; xi < dest.width(); ++xi )
00748               {
00749                      (*d) = (*s);
00750                      s++;
00751                      d++;
00752               }
00753        }
00754        return;
00755 }
00756 
00757 void ScImage::contrast(int contrastValue, bool cmyk)
00758 {
00759        curveTable.resize(256);
00760        QPoint p1(0,0 - contrastValue);
00761        QPoint p2(256, 256 + contrastValue);
00762        double mc = (p1.y() - p2.y()) / (double)(p1.x() - p2.x());
00763        for (int i = 0; i < 256; ++i)
00764        {
00765               curveTable[i] = QMIN(255, QMAX(0, int(i * mc) + p1.y()));
00766        }
00767        applyCurve(cmyk);
00768 }
00769 
00770 void ScImage::brightness(int brightnessValue, bool cmyk)
00771 {
00772        curveTable.resize(256);
00773        QPoint p1(0,0 + brightnessValue);
00774        QPoint p2(256, 256 + brightnessValue);
00775        double mc = (p1.y() - p2.y()) / (double)(p1.x() - p2.x());
00776        for (int i = 0; i < 256; ++i)
00777        {
00778               curveTable[i] = QMIN(255, QMAX(0, int(i * mc) + p1.y()));
00779        }
00780        applyCurve(cmyk);
00781 }
00782 
00783 void ScImage::doGraduate(FPointArray curve, bool cmyk, bool linear)
00784 {
00785        curveTable.resize(256);
00786        for (int x = 0 ; x < 256 ; x++)
00787        {
00788               curveTable[x] = QMIN(255, QMAX(0, qRound(getCurveYValue(curve, x / 255.0, linear) * 255)));
00789        }
00790        applyCurve(cmyk);
00791 }
00792 
00793 void ScImage::applyCurve(bool cmyk)
00794 {
00795        int h = height();
00796        int w = width();
00797        QRgb *s;
00798        QRgb r;
00799        int c, m, y, k;
00800        unsigned char *p;
00801        unsigned char rc, gc, bc;
00802        for( int yi=0; yi < h; ++yi )
00803        {
00804               s = (QRgb*)(scanLine( yi ));
00805               for( int xi=0; xi < w; ++xi )
00806               {
00807                      r = *s;
00808                      if (cmyk)
00809                      {
00810                             p = (unsigned char *) s;
00811                             rc = 255 - QMIN(255, p[0] + p[3]);
00812                             gc = 255 - QMIN(255, p[1] + p[3]);
00813                             bc = 255 - QMIN(255, p[2] + p[3]);
00814                             c = 255 - curveTable[(int)rc];
00815                             m = 255 - curveTable[(int)gc];
00816                             y = 255 - curveTable[(int)bc];
00817                             k = QMIN(QMIN(c, m), y);
00818                             *s = qRgba(y - k, m - k, c - k, k );
00819                      }
00820                      else
00821                      {
00822                             c = curveTable[qRed(r)];
00823                             m = curveTable[qGreen(r)];
00824                             y = curveTable[qBlue(r)];
00825                             k = qAlpha(r);
00826                             *s = qRgba(c, m, y, k);
00827                      }
00828                      s++;
00829               }
00830        }
00831 }
00832 
00833 void ScImage::colorize(ScribusDoc* doc, ScColor color, int shade, bool cmyk)
00834 {
00835        int h = height();
00836        int w = width();
00837        int cc, cm, cy, ck;
00838        int hu, sa, v;
00839        ScColor tmp2;
00840        QColor tmpR;
00841        QRgb *s;
00842        QRgb r;
00843        double k;
00844        int cc2, cm2, cy2, k2;
00845        if (cmyk)
00846        {
00847               CMYKColor cmykCol;
00848               ScColorEngine::getShadeColorCMYK(color, doc, cmykCol, shade);
00849               cmykCol.getValues(cc, cm, cy, ck);
00850        }
00851        else
00852        {
00853               ck = 0;
00854               RGBColor rgbCol;
00855               ScColorEngine::getShadeColorRGB(color, doc, rgbCol, shade);
00856               rgbCol.getValues(cc, cm, cy);
00857        }
00858        for( int yi=0; yi < h; ++yi )
00859        {
00860               s = (QRgb*)(scanLine( yi ));
00861               for( int xi=0; xi < w; ++xi )
00862               {
00863                      r = *s;
00864                      if (cmyk)
00865                      {
00866                             k = QMIN(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r) + qAlpha(r)), 255) / 255.0;
00867                             *s = qRgba(QMIN(qRound(cc*k), 255), QMIN(qRound(cm*k), 255), QMIN(qRound(cy*k), 255), QMIN(qRound(ck*k), 255));
00868                      }
00869                      else
00870                      {
00871                             k2 = 255 - QMIN(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r)), 255);
00872                             tmpR.setRgb(cc, cm, cy);
00873                             tmpR.hsv(&hu, &sa, &v);
00874                             tmpR.setHsv(hu, sa * k2 / 255, 255 - ((255 - v) * k2 / 255));
00875                             tmpR.getRgb(&cc2, &cm2, &cy2);
00876                             *s = qRgba(cc2, cm2, cy2, qAlpha(r));
00877                      }
00878                      s++;
00879               }
00880        }
00881 }
00882 
00883 void ScImage::duotone(ScribusDoc* doc, ScColor color1, int shade1, FPointArray curve1, bool lin1, ScColor color2, int shade2, FPointArray curve2, bool lin2, bool cmyk)
00884 {
00885        int h = height();
00886        int w = width();
00887        int c, c1, m, m1, y, y1, k, k1;
00888        int cn, c1n, mn, m1n, yn, y1n, kn, k1n;
00889        uchar cb;
00890        QMemArray<int> curveTable1;
00891        QMemArray<int> curveTable2;
00892        CMYKColor cmykCol;
00893        ScColorEngine::getShadeColorCMYK(color1, doc, cmykCol, shade1);
00894        cmykCol.getValues(c, m, y, k);
00895        ScColorEngine::getShadeColorCMYK(color2, doc, cmykCol, shade2);
00896        cmykCol.getValues(c1, m1, y1, k1);
00897        curveTable1.resize(256);
00898        for (int x = 0 ; x < 256 ; x++)
00899        {
00900               curveTable1[x] = QMIN(255, QMAX(0, qRound(getCurveYValue(curve1, x / 255.0, lin1) * 255)));
00901        }
00902        curveTable2.resize(256);
00903        for (int x = 0 ; x < 256 ; x++)
00904        {
00905               curveTable2[x] = QMIN(255, QMAX(0, qRound(getCurveYValue(curve2, x / 255.0, lin2) * 255)));
00906        }
00907        for( int yi=0; yi < h; ++yi )
00908        {
00909               QRgb * s = (QRgb*)(scanLine( yi ));
00910               for( int xi=0; xi < w; ++xi )
00911               {
00912                      QRgb r=*s;
00913                      if (cmyk)
00914                             cb = QMIN(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r) + qAlpha(r)), 255);
00915                      else
00916                             cb = 255 - QMIN(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r)), 255);
00917                      cn = QMIN((c * curveTable1[(int)cb]) >> 8, 255);
00918                      mn = QMIN((m * curveTable1[(int)cb]) >> 8, 255);
00919                      yn = QMIN((y * curveTable1[(int)cb]) >> 8, 255);
00920                      kn = QMIN((k * curveTable1[(int)cb]) >> 8, 255);
00921                      c1n = QMIN((c1 * curveTable1[(int)cb]) >> 8, 255);
00922                      m1n = QMIN((m1 * curveTable2[(int)cb]) >> 8, 255);
00923                      y1n = QMIN((y1 * curveTable2[(int)cb]) >> 8, 255);
00924                      k1n = QMIN((k1 * curveTable2[(int)cb]) >> 8, 255);
00925                      ScColor col = ScColor(QMIN(cn+c1n, 255), QMIN(mn+m1n, 255), QMIN(yn+y1n, 255), QMIN(kn+k1n, 255));
00926                      if (cmyk)
00927                             col.getCMYK(&cn, &mn, &yn, &kn);
00928                      else
00929                      {
00930                             col.getRawRGBColor(&cn, &mn, &yn);
00931                             kn = qAlpha(r);
00932                      }
00933                      *s = qRgba(cn, mn, yn, kn);
00934                      s++;
00935               }
00936        }
00937 }
00938 
00939 void ScImage::tritone(ScribusDoc* doc, ScColor color1, int shade1, FPointArray curve1, bool lin1, ScColor color2, int shade2, FPointArray curve2, bool lin2, ScColor color3, int shade3, FPointArray curve3, bool lin3, bool cmyk)
00940 {
00941        int h = height();
00942        int w = width();
00943        int c, c1, c2, m, m1, m2, y, y1, y2, k, k1, k2;
00944        int cn, c1n, c2n, mn, m1n, m2n, yn, y1n, y2n, kn, k1n, k2n;
00945        uchar cb;
00946        CMYKColor cmykCol;
00947        QMemArray<int> curveTable1;
00948        QMemArray<int> curveTable2;
00949        QMemArray<int> curveTable3;
00950        ScColorEngine::getShadeColorCMYK(color1, doc, cmykCol, shade1);
00951        cmykCol.getValues(c, m, y, k);
00952        ScColorEngine::getShadeColorCMYK(color2, doc, cmykCol, shade2);
00953        cmykCol.getValues(c1, m1, y1, k1);
00954        ScColorEngine::getShadeColorCMYK(color3, doc, cmykCol, shade3);
00955        cmykCol.getValues(c2, m2, y2, k2);
00956        curveTable1.resize(256);
00957        for (int x = 0 ; x < 256 ; x++)
00958        {
00959               curveTable1[x] = QMIN(255, QMAX(0, qRound(getCurveYValue(curve1, x / 255.0, lin1) * 255)));
00960        }
00961        curveTable2.resize(256);
00962        for (int x = 0 ; x < 256 ; x++)
00963        {
00964               curveTable2[x] = QMIN(255, QMAX(0, qRound(getCurveYValue(curve2, x / 255.0, lin2) * 255)));
00965        }
00966        curveTable3.resize(256);
00967        for (int x = 0 ; x < 256 ; x++)
00968        {
00969               curveTable3[x] = QMIN(255, QMAX(0, qRound(getCurveYValue(curve2, x / 255.0, lin3) * 255)));
00970        }
00971        for( int yi=0; yi < h; ++yi )
00972        {
00973               QRgb * s = (QRgb*)(scanLine( yi ));
00974               for( int xi=0; xi < w; ++xi )
00975               {
00976                      QRgb r=*s;
00977                      if (cmyk)
00978                             cb = QMIN(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r) + qAlpha(r)), 255);
00979                      else
00980                             cb = 255 - QMIN(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r)), 255);
00981                      cn = QMIN((c * curveTable1[(int)cb]) >> 8, 255);
00982                      mn = QMIN((m * curveTable1[(int)cb]) >> 8, 255);
00983                      yn = QMIN((y * curveTable1[(int)cb]) >> 8, 255);
00984                      kn = QMIN((k * curveTable1[(int)cb]) >> 8, 255);
00985                      c1n = QMIN((c1 * curveTable2[(int)cb]) >> 8, 255);
00986                      m1n = QMIN((m1 * curveTable2[(int)cb]) >> 8, 255);
00987                      y1n = QMIN((y1 * curveTable2[(int)cb]) >> 8, 255);
00988                      k1n = QMIN((k1 * curveTable2[(int)cb]) >> 8, 255);
00989                      c2n = QMIN((c2 * curveTable3[(int)cb]) >> 8, 255);
00990                      m2n = QMIN((m2 * curveTable3[(int)cb]) >> 8, 255);
00991                      y2n = QMIN((y2 * curveTable3[(int)cb]) >> 8, 255);
00992                      k2n = QMIN((k2 * curveTable3[(int)cb]) >> 8, 255);
00993                      ScColor col = ScColor(QMIN(cn+c1n+c2n, 255), QMIN(mn+m1n+m2n, 255), QMIN(yn+y1n+y2n, 255), QMIN(kn+k1n+k2n, 255));
00994                      if (cmyk)
00995                             col.getCMYK(&cn, &mn, &yn, &kn);
00996                      else
00997                      {
00998                             col.getRawRGBColor(&cn, &mn, &yn);
00999                             kn = qAlpha(r);
01000                      }
01001                      *s = qRgba(cn, mn, yn, kn);
01002                      s++;
01003               }
01004        }
01005 }
01006 
01007 void ScImage::quadtone(ScribusDoc* doc, ScColor color1, int shade1, FPointArray curve1, bool lin1, ScColor color2, int shade2, FPointArray curve2, bool lin2, ScColor color3, int shade3, FPointArray curve3, bool lin3, ScColor color4, int shade4, FPointArray curve4, bool lin4, bool cmyk)
01008 {
01009        int h = height();
01010        int w = width();
01011        int c, c1, c2, c3, m, m1, m2, m3, y, y1, y2, y3, k, k1, k2, k3;
01012        int cn, c1n, c2n, c3n, mn, m1n, m2n, m3n, yn, y1n, y2n, y3n, kn, k1n, k2n, k3n;
01013        uchar cb;
01014        CMYKColor cmykCol;
01015        QMemArray<int> curveTable1;
01016        QMemArray<int> curveTable2;
01017        QMemArray<int> curveTable3;
01018        QMemArray<int> curveTable4;
01019        ScColorEngine::getShadeColorCMYK(color1, doc, cmykCol, shade1);
01020        cmykCol.getValues(c, m, y, k);
01021        ScColorEngine::getShadeColorCMYK(color2, doc, cmykCol, shade2);
01022        cmykCol.getValues(c1, m1, y1, k1);
01023        ScColorEngine::getShadeColorCMYK(color3, doc, cmykCol, shade3);
01024        cmykCol.getValues(c2, m2, y2, k2);
01025        ScColorEngine::getShadeColorCMYK(color4, doc, cmykCol, shade4);
01026        cmykCol.getValues(c3, m3, y3, k3);
01027        curveTable1.resize(256);
01028        for (int x = 0 ; x < 256 ; x++)
01029        {
01030               curveTable1[x] = QMIN(255, QMAX(0, qRound(getCurveYValue(curve1, x / 255.0, lin1) * 255)));
01031        }
01032        curveTable2.resize(256);
01033        for (int x = 0 ; x < 256 ; x++)
01034        {
01035               curveTable2[x] = QMIN(255, QMAX(0, qRound(getCurveYValue(curve2, x / 255.0, lin2) * 255)));
01036        }
01037        curveTable3.resize(256);
01038        for (int x = 0 ; x < 256 ; x++)
01039        {
01040               curveTable3[x] = QMIN(255, QMAX(0, qRound(getCurveYValue(curve3, x / 255.0, lin3) * 255)));
01041        }
01042        curveTable4.resize(256);
01043        for (int x = 0 ; x < 256 ; x++)
01044        {
01045               curveTable4[x] = QMIN(255, QMAX(0, qRound(getCurveYValue(curve4, x / 255.0, lin4) * 255)));
01046        }
01047        for( int yi=0; yi < h; ++yi )
01048        {
01049               QRgb * s = (QRgb*)(scanLine( yi ));
01050               for( int xi=0; xi < w; ++xi )
01051               {
01052                      QRgb r=*s;
01053                      if (cmyk)
01054                             cb = QMIN(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r) + qAlpha(r)), 255);
01055                      else
01056                             cb = 255 - QMIN(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r)), 255);
01057                      cn = QMIN((c * curveTable1[(int)cb]) >> 8, 255);
01058                      mn = QMIN((m * curveTable1[(int)cb]) >> 8, 255);
01059                      yn = QMIN((y * curveTable1[(int)cb]) >> 8, 255);
01060                      kn = QMIN((k * curveTable1[(int)cb]) >> 8, 255);
01061                      c1n = QMIN((c1 * curveTable2[(int)cb]) >> 8, 255);
01062                      m1n = QMIN((m1 * curveTable2[(int)cb]) >> 8, 255);
01063                      y1n = QMIN((y1 * curveTable2[(int)cb]) >> 8, 255);
01064                      k1n = QMIN((k1 * curveTable2[(int)cb]) >> 8, 255);
01065                      c2n = QMIN((c2 * curveTable3[(int)cb]) >> 8, 255);
01066                      m2n = QMIN((m2 * curveTable3[(int)cb]) >> 8, 255);
01067                      y2n = QMIN((y2 * curveTable3[(int)cb]) >> 8, 255);
01068                      k2n = QMIN((k2 * curveTable3[(int)cb]) >> 8, 255);
01069                      c3n = QMIN((c3 * curveTable4[(int)cb]) >> 8, 255);
01070                      m3n = QMIN((m3 * curveTable4[(int)cb]) >> 8, 255);
01071                      y3n = QMIN((y3 * curveTable4[(int)cb]) >> 8, 255);
01072                      k3n = QMIN((k3 * curveTable4[(int)cb]) >> 8, 255);
01073                      ScColor col = ScColor(QMIN(cn+c1n+c2n+c3n, 255), QMIN(mn+m1n+m2n+m3n, 255), QMIN(yn+y1n+y2n+y3n, 255), QMIN(kn+k1n+k2n+k3n, 255));
01074                      if (cmyk)
01075                             col.getCMYK(&cn, &mn, &yn, &kn);
01076                      else
01077                      {
01078                             col.getRawRGBColor(&cn, &mn, &yn);
01079                             kn = qAlpha(r);
01080                      }
01081                      *s = qRgba(cn, mn, yn, kn);
01082                      s++;
01083               }
01084        }
01085 }
01086 
01087 void ScImage::invert(bool cmyk)
01088 {
01089        int h = height();
01090        int w = width();
01091        unsigned char *p;
01092        QRgb * s;
01093        unsigned char c, m, y, k;
01094        for( int yi=0; yi < h; ++yi )
01095        {
01096               s = (QRgb*)(scanLine( yi ));
01097               for( int xi=0; xi < w; ++xi )
01098               {
01099                      if (cmyk)
01100                      {
01101                             p = (unsigned char *) s;
01102                             c = 255 - QMIN(255, p[0] + p[3]);
01103                             m = 255 - QMIN(255, p[1] + p[3]);
01104                             y = 255 - QMIN(255, p[2] + p[3]);
01105                             k = QMIN(QMIN(c, m), y);
01106                             p[0] = c - k;
01107                             p[1] = m - k;
01108                             p[2] = y - k;
01109                             p[3] = k;
01110                      }
01111                      else
01112                             *s ^= 0x00ffffff;
01113                      s++;
01114               }
01115        }
01116 }
01117 
01118 void ScImage::toGrayscale(bool cmyk)
01119 {
01120        int h = height();
01121        int w = width();
01122        int k;
01123        QRgb * s;
01124        QRgb r;
01125        for( int yi=0; yi < h; ++yi )
01126        {
01127               s = (QRgb*)(scanLine( yi ));
01128               for( int xi=0; xi < w; ++xi )
01129               {
01130                      r = *s;
01131                      if (cmyk)
01132                      {
01133                             k = QMIN(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r) + qAlpha(r)), 255);
01134                             *s = qRgba(0, 0, 0, k);
01135                      }
01136                      else
01137                      {
01138                             k = QMIN(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r)), 255);
01139                             *s = qRgba(k, k, k, qAlpha(r));
01140                      }
01141                      s++;
01142               }
01143        }
01144 }
01145 
01146 void ScImage::swapRGBA()
01147 {
01148        unsigned int *ptr;
01149        unsigned char *p;
01150        unsigned char r, b;
01151        for (int i = 0; i < height(); ++i)
01152        {
01153               ptr = (unsigned int *) scanLine(i);
01154               for (int j = 0; j < width(); ++j)
01155               {
01156                      p = (unsigned char *) ptr;
01157                      r = p[0];
01158                      b = p[2];
01159                      p[2] = r;
01160                      p[0] = b;
01161                      ptr++;
01162               }
01163        }
01164 }
01165 
01166 void ScImage::createLowRes(double scale)
01167 {
01168        int w = qRound(width() / scale);
01169        int h = qRound(height() / scale);
01170        QImage tmp = smoothScale(w, h);
01171        create(w, h, 32);
01172        setAlphaBuffer(true);
01173        tmp = tmp.convertDepth(32);
01174        QRgb *s;
01175        QRgb *d;
01176        for( int yi=0; yi < tmp.height(); ++yi )
01177        {
01178               s = (QRgb*)(tmp.scanLine( yi ));
01179               d = (QRgb*)(scanLine( yi ));
01180               for(int xi=0; xi < tmp.width(); ++xi )
01181               {
01182                      (*d) = (*s);
01183                      s++;
01184                      d++;
01185               }
01186        }
01187 }
01188 
01189 void ScImage::Convert2JPG(QString fn, int Quality, bool isCMYK, bool isGray)
01190 {
01191        struct jpeg_compress_struct cinfo;
01192        struct my_error_mgr         jerr;
01193        FILE     *outfile;
01194        JSAMPROW row_pointer[1];
01195        row_pointer[0] = 0;
01196        cinfo.err = jpeg_std_error (&jerr.pub);
01197        jerr.pub.error_exit = my_error_exit;
01198        outfile = NULL;
01199        if (setjmp (jerr.setjmp_buffer))
01200        {
01201               jpeg_destroy_compress (&cinfo);
01202               if (outfile)
01203                      fclose (outfile);
01204               return;
01205        }
01206        jpeg_create_compress (&cinfo);
01207        if ((outfile = fopen (fn.local8Bit(), "wb")) == NULL)
01208               return;
01209        jpeg_stdio_dest (&cinfo, outfile);
01210        cinfo.image_width  = width();
01211        cinfo.image_height = height();
01212        if (isCMYK)
01213        {
01214               cinfo.in_color_space = JCS_CMYK;
01215               cinfo.input_components = 4;
01216        }
01217        else
01218        {
01219               if (isGray)
01220               {
01221                      cinfo.in_color_space = JCS_GRAYSCALE;
01222                      cinfo.input_components = 1;
01223               }
01224               else
01225               {
01226                      cinfo.in_color_space = JCS_RGB;
01227                      cinfo.input_components = 3;
01228               }
01229        }
01230        jpeg_set_defaults (&cinfo);
01231        int qual[] = { 95, 85, 75, 50, 25 };  // These are the JPEG Quality settings 100 means best, 0 .. don't discuss
01232        jpeg_set_quality (&cinfo, qual[Quality], true);
01233        jpeg_start_compress (&cinfo, true);
01234        row_pointer[0] = new uchar[cinfo.image_width*cinfo.input_components];
01235        int w = cinfo.image_width;
01236        while (cinfo.next_scanline < cinfo.image_height)
01237        {
01238               uchar *row = row_pointer[0];
01239               if (isCMYK)
01240               {
01241                      QRgb* rgba = (QRgb*)scanLine(cinfo.next_scanline);
01242                      for (int i=0; i<w; ++i)
01243                      {
01244                             *row++ = 255-qRed(*rgba);
01245                             *row++ = 255-qGreen(*rgba);
01246                             *row++ = 255-qBlue(*rgba);
01247                             *row++ = 255-qAlpha(*rgba);
01248                             ++rgba;
01249                      }
01250               }
01251               else
01252               {
01253                      if (isGray)
01254                      {
01255                             QRgb* rgba = (QRgb*)scanLine(cinfo.next_scanline);
01256                             for (int i=0; i<w; ++i)
01257                             {
01258                                    *row++ = qRed(*rgba);
01259                                    ++rgba;
01260                             }
01261                      }
01262                      else
01263                      {
01264                             QRgb* rgb = (QRgb*)scanLine(cinfo.next_scanline);
01265                             for (int i=0; i<w; i++)
01266                             {
01267                                    *row++ = qRed(*rgb);
01268                                    *row++ = qGreen(*rgb);
01269                                    *row++ = qBlue(*rgb);
01270                                    ++rgb;
01271                             }
01272                      }
01273               }
01274               jpeg_write_scanlines (&cinfo, row_pointer, 1);
01275        }
01276        jpeg_finish_compress (&cinfo);
01277        fclose (outfile);
01278        jpeg_destroy_compress (&cinfo);
01279        delete [] row_pointer[0];
01280 }
01281 
01282 QByteArray ScImage::ImageToArray()
01283 {
01284        int i = 0;
01285        int h = height();
01286        int w = width();
01287        unsigned char u;
01288        QRgb *s;
01289        QRgb r;
01290        QByteArray imgArray(3 * h * w);
01291        for( int yi=0; yi < h; ++yi )
01292        {
01293               s = (QRgb*)(scanLine( yi ));
01294               for( int xi=0; xi < w; ++xi )
01295               {
01296                      r = *s++;
01297                      u=qRed(r);
01298                      imgArray[i++] = u;
01299                      u=qGreen(r);
01300                      imgArray[i++] = u;
01301                      u=qBlue(r);
01302                      imgArray[i++] = u;
01303               }
01304        }
01305        return imgArray;
01306 }
01307 
01308 QByteArray ScImage::ImageToGray()
01309 {
01310        int i = 0;
01311        int h = height();
01312        int w = width();
01313        QRgb *s;
01314        QRgb r;
01315        QByteArray imgArray(h * w);
01316        int k;
01317        for( int yi=0; yi < h; ++yi )
01318        {
01319               s = (QRgb*)(scanLine( yi ));
01320               for( int xi=0; xi < w; ++xi )
01321               {
01322                      r = *s;
01323                      k = QMIN(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r)), 255);
01324                      *s = qRgba(k, 0, 0, 0);
01325                      imgArray[i++] = k;
01326                      s++;
01327               }
01328        }
01329        return imgArray;
01330 }
01331 
01332 QByteArray ScImage::ImageToCMYK_PDF(bool pre)
01333 {
01334        int i = 0;
01335        int h = height();
01336        int w = width();
01337        QRgb *s;
01338        QRgb r;
01339        int c, m, y, k;
01340        QByteArray imgArray( 4 * h * w );
01341        if (pre)
01342        {
01343               for( int yi=0; yi < h; ++yi )
01344               {
01345                      s = (QRgb*)(scanLine( yi ));
01346                      for( int xi=0; xi < w; ++xi )
01347                      {
01348                             r = *s;
01349                             imgArray[i++] = static_cast<unsigned char> (qRed(r));
01350                             imgArray[i++] = static_cast<unsigned char> (qGreen(r));
01351                             imgArray[i++] = static_cast<unsigned char> (qBlue(r));
01352                             imgArray[i++] = static_cast<unsigned char> (qAlpha(r));
01353                             s++;
01354                      }
01355               }
01356        }
01357        else
01358        {
01359               for( int yi=0; yi < h; ++yi )
01360               {
01361                      s = (QRgb*)(scanLine( yi ));
01362                      for( int xi=0; xi < w; ++xi )
01363                      {
01364                             r = *s;
01365                             c = 255 - qRed(r);
01366                             m = 255 - qGreen(r);
01367                             y = 255 - qBlue(r);
01368                             k = QMIN(QMIN(c, m), y);
01369                             imgArray[i++] = static_cast<unsigned char> (c - k);
01370                             imgArray[i++] = static_cast<unsigned char> (m - k);
01371                             imgArray[i++] = static_cast<unsigned char> (y - k);
01372                             imgArray[i++] = static_cast<unsigned char> (k);
01373                             s++;
01374                      }
01375               }
01376        }
01377        return imgArray;
01378 }
01379 
01380 QByteArray ScImage::ImageToCMYK_PS(int pl, bool pre)
01381 {
01382        int i = 0;
01383        int h = height();
01384        int w = width();
01385        QByteArray imgArray;
01386        QRgb *s;
01387        QRgb r;
01388        int c, m, y, k;
01389        if(pl == -1)
01390               imgArray.resize(4 * h * w);
01391        else
01392               imgArray.resize(h * w);
01393        if (pre)
01394        {
01395               for( int yi=0; yi < h; ++yi )
01396               {
01397                      s = (QRgb*)(scanLine( yi ));
01398                      for( int xi=0; xi < w; ++xi )
01399                      {
01400                             r = *s++;
01401                             c = qRed(r);
01402                             m = qGreen(r);
01403                             y = qBlue(r);
01404                             k = qAlpha(r);
01405                             if (pl == -1)
01406                             {
01407                                    imgArray[i++] = static_cast<unsigned char> (c);
01408                                    imgArray[i++] = static_cast<unsigned char> (m);
01409                                    imgArray[i++] = static_cast<unsigned char> (y);
01410                                    imgArray[i++] = static_cast<unsigned char> (k);
01411                             }
01412                             else
01413                             {
01414                                    if (pl == -2)
01415                                           imgArray[i++] = static_cast<unsigned char> (QMIN(255, qRound(0.3 * c + 0.59 * m + 0.11 * y + k)));
01416                                    if (pl == 1)
01417                                           imgArray[i++] = static_cast<unsigned char> (c);
01418                                    if (pl == 2)
01419                                           imgArray[i++] = static_cast<unsigned char> (m);
01420                                    if (pl == 3)
01421                                           imgArray[i++] = static_cast<unsigned char> (y);
01422                                    if (pl == 0)
01423                                           imgArray[i++] = static_cast<unsigned char> (k);
01424                             }
01425                      }
01426               }
01427        }
01428        else
01429        {
01430               for( int yi=0; yi < h; ++yi )
01431               {
01432                      s = (QRgb*)(scanLine( yi ));
01433                      for( int xi=0; xi < w; ++xi )
01434                      {
01435                             r = *s++;
01436                             c = 255 - qRed(r);
01437                             m = 255 - qGreen(r);
01438                             y = 255 - qBlue(r);
01439                             k = QMIN(QMIN(c, m), y);
01440                             if (pl == -1)
01441                             {
01442                                    imgArray[i++] = static_cast<unsigned char> (c - k);
01443                                    imgArray[i++] = static_cast<unsigned char> (m - k);
01444                                    imgArray[i++] = static_cast<unsigned char> (y - k);
01445                                    imgArray[i++] = static_cast<unsigned char> (k);
01446                             }
01447                             else
01448                             {
01449                                    if (pl == -2)
01450                                           imgArray[i++] = static_cast<unsigned char> (QMIN(255, qRound(0.3 * c + 0.59 * m + 0.11 * y + k)));
01451                                    if (pl == 1)
01452                                           imgArray[i++] = static_cast<unsigned char> (c - k);
01453                                    if (pl == 2)
01454                                           imgArray[i++] = static_cast<unsigned char> (m - k);
01455                                    if (pl == 3)
01456                                           imgArray[i++] = static_cast<unsigned char> (y - k);
01457                                    if (pl == 0)
01458                                           imgArray[i++] = static_cast<unsigned char> (k);
01459                             }
01460                      }
01461               }
01462        }
01463        return imgArray;
01464 }
01465 
01466 void ScImage::scaleImage(int nwidth, int nheight)
01467 {
01468        QImage dst;
01469        dst.create(nwidth, nheight,32);
01470        QRgb* xelrow = 0;
01471        QRgb* tempxelrow = 0;
01472        register QRgb* xP;
01473        register QRgb* nxP;
01474        int rows, cols, rowsread, newrows, newcols;
01475        register int row, col, needtoreadrow;
01476        const uchar maxval = 255;
01477        double xscale, yscale;
01478        long sxscale, syscale;
01479        register long fracrowtofill, fracrowleft;
01480        long* as;
01481        long* rs;
01482        long* gs;
01483        long* bs;
01484        int rowswritten = 0;
01485        cols = width();
01486        rows = height();
01487        newcols = dst.width();
01488        newrows = dst.height();
01489        long SCALE;
01490        long HALFSCALE;
01491        if (cols > 4096)
01492        {
01493               SCALE = 4096;
01494               HALFSCALE = 2048;
01495        }
01496        else
01497        {
01498               int fac = 4096;
01499               while (cols * fac > 4096)
01500               {
01501                      fac /= 2;
01502               }
01503               SCALE = fac * cols;
01504               HALFSCALE = fac * cols / 2;
01505        }
01506        xscale = (double) newcols / (double) cols;
01507        yscale = (double) newrows / (double) rows;
01508        sxscale = (long)(xscale * SCALE);
01509        syscale = (long)(yscale * SCALE);
01510        if ( newrows != rows )      /* shortcut Y scaling if possible */
01511               tempxelrow = new QRgb[cols];
01512        as = new long[cols];
01513        rs = new long[cols];
01514        gs = new long[cols];
01515        bs = new long[cols];
01516        rowsread = 0;
01517        fracrowleft = syscale;
01518        needtoreadrow = 1;
01519        for ( col = 0; col < cols; ++col )
01520               rs[col] = gs[col] =  as[col] = bs[col] = HALFSCALE;
01521        fracrowtofill = SCALE;
01522        for ( row = 0; row < newrows; ++row )
01523        {
01524               if ( newrows == rows )
01525                      tempxelrow = xelrow = (QRgb*)scanLine(rowsread++);
01526               else
01527               {
01528                      while ( fracrowleft < fracrowtofill )
01529                      {
01530                             if ( needtoreadrow && rowsread < rows )
01531                                    xelrow = (QRgb*)scanLine(rowsread++);
01532                             for ( col = 0, xP = xelrow; col < cols; ++col, ++xP )
01533                             {
01534                                    as[col] += fracrowleft * qAlpha( *xP );
01535                                    rs[col] += fracrowleft * qRed( *xP );
01536                                    gs[col] += fracrowleft * qGreen( *xP );
01537                                    bs[col] += fracrowleft * qBlue( *xP );
01538                             }
01539                             fracrowtofill -= fracrowleft;
01540                             fracrowleft = syscale;
01541                             needtoreadrow = 1;
01542                      }
01543                      if ( needtoreadrow && rowsread < rows )
01544                      {
01545                             xelrow = (QRgb*)scanLine(rowsread++);
01546                             needtoreadrow = 0;
01547                      }
01548                      register long a=0;
01549                      for ( col = 0, xP = xelrow, nxP = tempxelrow; col < cols; ++col, ++xP, ++nxP )
01550                      {
01551                             register long r, g, b;
01552                             a = as[col] + fracrowtofill * qAlpha( *xP );
01553                             r = rs[col] + fracrowtofill * qRed( *xP );
01554                             g = gs[col] + fracrowtofill * qGreen( *xP );
01555                             b = bs[col] + fracrowtofill * qBlue( *xP );
01556                             r /= SCALE;
01557                             if ( r > maxval ) r = maxval;
01558                             g /= SCALE;
01559                             if ( g > maxval ) g = maxval;
01560                             b /= SCALE;
01561                             if ( b > maxval ) b = maxval;
01562                             a /= SCALE;
01563                             if ( a > maxval ) a = maxval;
01564                             *nxP = qRgba( (int)r, (int)g, (int)b , (int)a);
01565                             rs[col] = as[col] = gs[col] = bs[col] = HALFSCALE;
01566                      }
01567                      fracrowleft -= fracrowtofill;
01568                      if ( fracrowleft == 0 )
01569                      {
01570                             fracrowleft = syscale;
01571                             needtoreadrow = 1;
01572                      }
01573                      fracrowtofill = SCALE;
01574               }
01575               if ( newcols == cols )
01576                      memcpy(dst.scanLine(rowswritten++), tempxelrow, newcols*4);
01577               else
01578               {
01579                      register long a, r, g, b;
01580                      register long fraccoltofill, fraccolleft = 0;
01581                      register int needcol;
01582                      nxP = (QRgb*)dst.scanLine(rowswritten++);
01583                      fraccoltofill = SCALE;
01584                      a = r = g = b = HALFSCALE;
01585                      needcol = 0;
01586                      for ( col = 0, xP = tempxelrow; col < cols; ++col, ++xP )
01587                      {
01588                             fraccolleft = sxscale;
01589                             while ( fraccolleft >= fraccoltofill )
01590                             {
01591                                    if ( needcol )
01592                                    {
01593                                           ++nxP;
01594                                           a = r = g = b = HALFSCALE;
01595                                    }
01596                                    a += fraccoltofill * qAlpha( *xP );
01597                                    r += fraccoltofill * qRed( *xP );
01598                                    g += fraccoltofill * qGreen( *xP );
01599                                    b += fraccoltofill * qBlue( *xP );
01600                                    r /= SCALE;
01601                                    if ( r > maxval ) r = maxval;
01602                                    g /= SCALE;
01603                                    if ( g > maxval ) g = maxval;
01604                                    b /= SCALE;
01605                                    if ( b > maxval ) b = maxval;
01606                                    a /= SCALE;
01607                                    if ( a > maxval ) a = maxval;
01608                                    *nxP = qRgba( (int)r, (int)g, (int)b, (int)a );
01609                                    fraccolleft -= fraccoltofill;
01610                                    fraccoltofill = SCALE;
01611                                    needcol = 1;
01612                             }
01613                             if ( fraccolleft > 0 )
01614                             {
01615                                    if ( needcol )
01616                                    {
01617                                           ++nxP;
01618                                           a = r = g = b = HALFSCALE;
01619                                           needcol = 0;
01620                                    }
01621                                    a += fraccolleft * qAlpha( *xP );
01622                                    r += fraccolleft * qRed( *xP );
01623                                    g += fraccolleft * qGreen( *xP );
01624                                    b += fraccolleft * qBlue( *xP );
01625                                    fraccoltofill -= fraccolleft;
01626                             }
01627                      }
01628                      if ( fraccoltofill > 0 )
01629                      {
01630                             --xP;
01631                             a += fraccolleft * qAlpha( *xP );
01632                             r += fraccoltofill * qRed( *xP );
01633                             g += fraccoltofill * qGreen( *xP );
01634                             b += fraccoltofill * qBlue( *xP );
01635                      }
01636                      if ( ! needcol )
01637                      {
01638                             r /= SCALE;
01639                             if ( r > maxval ) r = maxval;
01640                             g /= SCALE;
01641                             if ( g > maxval ) g = maxval;
01642                             b /= SCALE;
01643                             if ( b > maxval ) b = maxval;
01644                             a /= SCALE;
01645                             if ( a > maxval ) a = maxval;
01646                             *nxP = qRgba( (int)r, (int)g, (int)b, (int)a );
01647                      }
01648               }
01649        }
01650        if ( newrows != rows && tempxelrow )// Robust, tempxelrow might be 0 1 day
01651               delete [] tempxelrow;
01652        if ( as )                          // Avoid purify complaint
01653               delete [] as;
01654        if ( rs )                          // Robust, rs might be 0 one day
01655               delete [] rs;
01656        if ( gs )                          // Robust, gs might be 0 one day
01657               delete [] gs;
01658        if ( bs )                          // Robust, bs might be 0 one day
01659               delete [] bs;
01660        create(nwidth, nheight,32);
01661        for( int yi=0; yi < dst.height(); ++yi )
01662        {
01663               QRgb *s = (QRgb*)(dst.scanLine( yi ));
01664               QRgb *d = (QRgb*)(scanLine( yi ));
01665               for(int xi=0; xi < dst.width(); ++xi )
01666               {
01667                      (*d) = (*s);
01668                      s++;
01669                      d++;
01670               }
01671        }
01672        return;
01673 }
01674 
01675 QByteArray ScImage::getAlpha(QString fn, bool PDF, bool pdf14, int gsRes, int scaleXSize, int scaleYSize)
01676 {
01677        QByteArray retArray;
01678        ScImgDataLoader* pDataLoader = NULL;
01679        imgInfo.valid = false;
01680        imgInfo.clipPath = "";
01681        imgInfo.PDSpathData.clear();
01682        imgInfo.layerInfo.clear();
01683        QFileInfo fi = QFileInfo(fn);
01684        if (!fi.exists())
01685               return retArray;
01686        QString tmp, BBox, tmp2;
01687        QString ext = fi.extension(false).lower();
01688        if ((ext == "jpg") || (ext == "jpeg"))
01689               return retArray;
01690        if (ext == "pdf")
01691               pDataLoader = new ScImgDataLoader_PDF();
01692        else if ((ext == "eps") || (ext == "epsi") || (ext == "ps"))
01693               pDataLoader = new ScImgDataLoader_PS();
01694        else if ((ext == "tif") || (ext == "tiff"))
01695        {
01696               pDataLoader = new ScImgDataLoader_TIFF();
01697               if     (pDataLoader)
01698                      pDataLoader->setRequest(imgInfo.isRequest, imgInfo.RequestProps);
01699        }
01700        else if (ext == "psd")
01701        {
01702               pDataLoader = new ScImgDataLoader_PSD();
01703               if     (pDataLoader)
01704                      pDataLoader->setRequest(imgInfo.isRequest, imgInfo.RequestProps);
01705        }
01706        else
01707               pDataLoader = new ScImgDataLoader_QT();
01708 
01709        if     (pDataLoader)
01710        {
01711               pDataLoader->preloadAlphaChannel(fn, gsRes);
01712               QImage rImage;
01713               if ((ext == "psd") || (ext == "tif") || (ext == "tiff"))
01714               {
01715                      if (pDataLoader->imageInfoRecord().valid)
01716                      {
01717                             if ((pDataLoader->r_image.channels() == 5) || (pDataLoader->imageInfoRecord().colorspace == 1))
01718                                    rImage = pDataLoader->r_image.convertToQImage(true);
01719                             else
01720                                    rImage = pDataLoader->r_image.convertToQImage(false);
01721                      }
01722                      else
01723                      {
01724                             delete pDataLoader;
01725                             return retArray;
01726                      }
01727               }
01728               else
01729                      rImage = pDataLoader->image();
01730               if (rImage.isNull())
01731               {
01732                      delete pDataLoader;
01733                      return retArray;
01734               }
01735               if ((scaleXSize != 0) && (scaleYSize != 0))
01736                      rImage = rImage.smoothScale(scaleXSize, scaleYSize);
01737               int i = 0;
01738               unsigned char u;
01739               int hm = rImage.height();
01740               int wm = rImage.width();
01741               int w2;
01742               QRgb *s;
01743               QRgb r;
01744               if (pdf14)
01745               {
01746                      retArray.resize(hm * wm);
01747                      for( int yi=0; yi < hm; ++yi )
01748                      {
01749                             s = (QRgb*)(rImage.scanLine( yi ));
01750                             for( int xi=0; xi < wm; ++xi )
01751                             {
01752                                    r = *s++;
01753                                    u=qAlpha(r);
01754                                    retArray[i++] = u;
01755                             }
01756                      }
01757               }
01758               else
01759               {
01760                      QImage iMask = rImage.createAlphaMask();
01761                      hm = iMask.height();
01762                      wm = iMask.width();
01763                      w2 = wm / 8;
01764                      if ((wm % 8) != 0)
01765                             w2++;
01766                      retArray.resize(hm * w2);
01767                      uchar * s;
01768                      for( int yi=0; yi < hm; ++yi )
01769                      {
01770                             s = iMask.scanLine( yi );
01771                             for( int xi=0; xi < w2; ++xi )
01772                             {
01773                                    u = *(s+xi);
01774                                    if(PDF) u = ~u;
01775                                    retArray[i++] = u;
01776                             }
01777                      }
01778               }
01779               delete pDataLoader;
01780        }
01781        return retArray;
01782 }
01783 
01784 void ScImage::getEmbeddedProfile(const QString & fn, QByteArray *profile, int *components)
01785 {
01786        Q_ASSERT(profile);
01787        Q_ASSERT(components);
01788        ScImgDataLoader* pDataLoader = NULL;
01789        cmsHPROFILE prof = 0;
01790 
01791        profile->resize(0);
01792        *components = 0;
01793        QFileInfo fi = QFileInfo(fn);
01794        if (!fi.exists())
01795               return;
01796        QString ext = fi.extension(false).lower();
01797 
01798        if (ext == "psd")
01799               pDataLoader = new ScImgDataLoader_PSD();
01800        else if ((ext == "eps") || (ext == "epsi"))
01801               pDataLoader = new ScImgDataLoader_PS();
01802        else if ((ext == "tif") || (ext == "tiff"))
01803               pDataLoader = new ScImgDataLoader_TIFF();
01804        else if ((ext == "jpg") || (ext == "jpeg"))
01805               pDataLoader = new ScImgDataLoader_JPEG();
01806 
01807        if     (pDataLoader)
01808        {
01809               pDataLoader->loadEmbeddedProfile(fn);
01810               QByteArray embeddedProfile = pDataLoader->embeddedProfile();
01811               if     (embeddedProfile.size())
01812               {
01813                      prof = cmsOpenProfileFromMem(embeddedProfile.data(), embeddedProfile.size());
01814                      if (prof)
01815                      {
01816                             if (static_cast<int>(cmsGetColorSpace(prof)) == icSigRgbData)
01817                                    *components = 3;
01818                             if (static_cast<int>(cmsGetColorSpace(prof)) == icSigCmykData)
01819                                    *components = 4;
01820                             *profile = embeddedProfile;
01821                      }
01822                      cmsCloseProfile(prof);
01823               }
01824               delete pDataLoader;
01825        }
01826 }
01827 
01828 bool ScImage::LoadPicture(const QString & fn, const CMSettings& cmSettings,
01829                                             bool useEmbedded, bool useProf, RequestType requestType,
01830                                             int gsRes, bool *realCMYK, bool showMsg)
01831 {
01832        // requestType - 0: CMYK, 1: RGB, 2: RGB Proof 3 : RawData, 4: Thumbnail
01833        // gsRes - is the resolution that ghostscript will render at
01834        bool isCMYK = false;
01835        bool ret = false;
01836        bool inputProfisEmbedded = false;
01837        bool stdProof = false;
01838        if (realCMYK != 0)
01839               *realCMYK = false;
01840        bool bilevel = false;
01841 //     short resolutionunit = 0;
01842        RequestType reqType = requestType;
01843        cmsHTRANSFORM xform = 0;
01844        cmsHPROFILE inputProf = 0;
01845        int cmsFlags = 0;
01846        int cmsProofFlags = 0;
01847        auto_ptr<ScImgDataLoader> pDataLoader;
01848        QFileInfo fi = QFileInfo(fn);
01849        if (!fi.exists())
01850               return ret;
01851        QString ext = fi.extension(false).lower();
01852        QString tmp, dummy, cmd1, cmd2, BBox, tmp2;
01853        QChar tc;
01854 //     bool found = false;
01855 
01856        if (ext.isEmpty())
01857               ext = getImageType(fn);
01858 
01859        if (ext == "pdf")
01860               pDataLoader.reset( new ScImgDataLoader_PDF() );
01861        else if ((ext == "eps") || (ext == "epsi") || (ext == "ps"))
01862               pDataLoader.reset( new ScImgDataLoader_PS() );
01863        else if ((ext == "tif") || (ext == "tiff"))
01864        {
01865               pDataLoader.reset( new ScImgDataLoader_TIFF() );
01866               pDataLoader->setRequest(imgInfo.isRequest, imgInfo.RequestProps);
01867        }
01868        else if (ext == "psd")
01869        {
01870               pDataLoader.reset( new ScImgDataLoader_PSD() );
01871               pDataLoader->setRequest(imgInfo.isRequest, imgInfo.RequestProps);
01872        }
01873        else if ((ext == "jpg") || (ext == "jpeg"))
01874               pDataLoader.reset( new ScImgDataLoader_JPEG() );
01875        else if (ext == "pat")
01876               pDataLoader.reset( new ScImgDataLoader_GIMP() );
01877        else
01878               pDataLoader.reset( new ScImgDataLoader_QT() );
01879 
01880        if     (pDataLoader->loadPicture(fn, gsRes, (requestType == Thumbnail)))
01881        {
01882               *this = pDataLoader->image();
01883               imgInfo = pDataLoader->imageInfoRecord();
01884               if (requestType == Thumbnail)
01885                      reqType = RGBData;
01886               if (!cmSettings.useColorManagement() || !useProf)
01887               {
01888                      imgInfo.isEmbedded = false;
01889                      imgInfo.profileName = "";
01890               }
01891               if (imgInfo.colorspace == 1)
01892               {
01893                      isCMYK = true;
01894                      if(realCMYK)
01895                             *realCMYK = true;
01896               }
01897               else if (imgInfo.colorspace == 2)
01898                      bilevel = true;
01899               pDataLoader->image() = QImage();
01900        }
01901        else
01902        {
01903               if     (ScCore->usingGUI() && pDataLoader->issuedErrorMsg() && showMsg)
01904               {
01905                      QMessageBox::critical(ScCore->primaryMainWindow(), CommonStrings::trWarning, pDataLoader->getMessage(), 1, 0, 0);
01906               }
01907               else if (pDataLoader->issuedErrorMsg())
01908               {
01909                      QString msg = pDataLoader->getMessage();
01910                      qWarning( msg.local8Bit().data() );
01911               }
01912               return false;
01913        }
01914 
01915        if (!((ext == "psd") || (ext == "tif") || (ext == "tiff")))
01916        {
01917               if (isNull())
01918                      return  ret;
01919        }
01920 
01921        QByteArray embeddedProfile = pDataLoader->embeddedProfile();
01922        if (cmSettings.useColorManagement() && useProf)
01923        {
01924               if (embeddedProfile.size() > 0 )
01925               {
01926                      inputProf = cmsOpenProfileFromMem(embeddedProfile.data(), embeddedProfile.size());
01927                      inputProfisEmbedded = true;
01928               }
01929               else
01930               {
01931                      QCString profilePath;
01932                      //CB If this is null, customfiledialog/picsearch/ScPreview might be sending it
01933                      Q_ASSERT(cmSettings.doc()!=0);
01934                      if (isCMYK)
01935                      {
01936                             if (ScCore->InputProfilesCMYK.contains(cmSettings.profileName()) && (cmSettings.profileName() != cmSettings.doc()->CMSSettings.DefaultImageCMYKProfile))
01937                             {
01938                                    imgInfo.profileName = cmSettings.profileName();
01939                                    inputProfisEmbedded = true;
01940                                    profilePath = ScCore->InputProfilesCMYK[imgInfo.profileName].local8Bit();
01941                                    inputProf = cmsOpenProfileFromFile(profilePath.data(), "r");
01942                             }
01943                             else
01944                             {
01945                                    inputProf = cmSettings.doc()->DocInputImageCMYKProf;
01946                                    imgInfo.profileName = cmSettings.doc()->CMSSettings.DefaultImageCMYKProfile;
01947                                    inputProfisEmbedded = false;
01948                             }
01949                      }
01950                      else
01951                      {
01952                             if (ScCore->InputProfiles.contains(cmSettings.profileName()) && (cmSettings.profileName() != cmSettings.doc()->CMSSettings.DefaultImageRGBProfile))
01953                             {
01954                                    imgInfo.profileName = cmSettings.profileName();
01955                                    profilePath = ScCore->InputProfiles[imgInfo.profileName].local8Bit();
01956                                    inputProfisEmbedded = true;
01957                                    inputProf = cmsOpenProfileFromFile(profilePath.data(), "r");
01958                             }
01959                             else
01960                             {
01961                                    inputProf = cmSettings.doc()->DocInputImageRGBProf;
01962                                    imgInfo.profileName = cmSettings.doc()->CMSSettings.DefaultImageRGBProfile;
01963                                    inputProfisEmbedded = false;
01964                             }
01965                      }
01966               }
01967        }
01968        if (cmSettings.useColorManagement() && useProf && inputProf)
01969        {
01970               bool  isPsdTiff = ((ext == "psd") || (ext == "tif") || (ext == "tiff"));
01971               DWORD SC_TYPE_YMCK_8 = (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1));
01972               DWORD inputProfFormat = TYPE_BGRA_8;
01973               DWORD outputProfFormat = SC_TYPE_YMCK_8;
01974               int inputProfColorSpace = static_cast<int>(cmsGetColorSpace(inputProf));
01975               if ( inputProfColorSpace == icSigRgbData )
01976                      inputProfFormat = isPsdTiff ? TYPE_RGBA_8 : TYPE_BGRA_8; // Later make tiff and psd loader use TYPE_BGRA_8
01977               else if (( inputProfColorSpace == icSigCmykData ) && isPsdTiff)
01978               {
01979                      if (pDataLoader->r_image.channels() == 5)
01980                             inputProfFormat = (COLORSPACE_SH(PT_CMYK)|EXTRA_SH(1)|CHANNELS_SH(4)|BYTES_SH(1));
01981                      else
01982                             inputProfFormat = TYPE_CMYK_8;
01983               }
01984               else if ( inputProfColorSpace == icSigCmykData )
01985                      inputProfFormat = SC_TYPE_YMCK_8;
01986               else if ( inputProfColorSpace == icSigGrayData )
01987                      inputProfFormat = TYPE_GRAY_8;
01988               int outputProfColorSpace = static_cast<int>(cmsGetColorSpace(cmSettings.printerProfile()));
01989               if ( outputProfColorSpace == icSigRgbData )
01990                      outputProfFormat = TYPE_BGRA_8;
01991               else if ( outputProfColorSpace == icSigCmykData )
01992                      outputProfFormat = SC_TYPE_YMCK_8;
01993               if (cmSettings.doSoftProofing())
01994               {
01995                      cmsProofFlags |= cmsFLAGS_SOFTPROOFING;
01996                      if (cmSettings.doGamutCheck())
01997                      {
01998                             cmsProofFlags |= cmsFLAGS_GAMUTCHECK;
01999                      }
02000               }
02001               if (cmSettings.useBlackPoint())
02002                      cmsFlags |= cmsFLAGS_BLACKPOINTCOMPENSATION;
02003               switch (reqType)
02004               {
02005               case CMYKData: // CMYK
02006 //                   if ((!isCMYK && (outputProfColorSpace == icSigCmykData)) || (isCMYK && (outputProfColorSpace == icSigRgbData)) )
02007                             xform = scCmsCreateTransform(inputProf, inputProfFormat, cmSettings.printerProfile(), outputProfFormat, cmSettings.imageRenderingIntent(), cmsFlags);
02008                      if (outputProfColorSpace != icSigCmykData )
02009                             *realCMYK = isCMYK = false;
02010                      break;
02011               case Thumbnail:
02012               case RGBData: // RGB
02013                      if (isCMYK)
02014                             xform = scCmsCreateTransform(inputProf, inputProfFormat, cmSettings.monitorProfile(), TYPE_BGRA_8, cmSettings.intent(), cmsFlags);
02015                      else
02016                      {
02017                             if ((ext == "psd") || (ext == "tif") || (ext == "tiff"))
02018                             {
02019                                    *this = pDataLoader->r_image.convertToQImage(false);
02020                                    imgInfo = pDataLoader->imageInfoRecord();
02021                             }
02022                      }
02023                      break;
02024               case RGBProof: // RGB Proof
02025                      {
02026                             if (cmSettings.doSoftProofing())
02027                             {
02028                                    if ((imgInfo.profileName == cmSettings.doc()->CMSSettings.DefaultImageRGBProfile) || (imgInfo.profileName == cmSettings.doc()->CMSSettings.DefaultImageCMYKProfile))
02029                                    {
02030                                           if (isCMYK)
02031                                                  xform = cmSettings.doc()->stdProofImgCMYK;
02032                                           else
02033                                                  xform = cmSettings.doc()->stdProofImg;
02034                                           cmsChangeBuffersFormat(xform, inputProfFormat, TYPE_BGRA_8);
02035                                           stdProof = true;
02036                                    }
02037                                    else
02038                                           xform = scCmsCreateProofingTransform(inputProf, inputProfFormat,
02039                                                         cmSettings.monitorProfile(), TYPE_BGRA_8, cmSettings.printerProfile(),
02040                                                         cmSettings.intent(), INTENT_RELATIVE_COLORIMETRIC, cmsFlags | cmsProofFlags);
02041                             }
02042                             else
02043                                    xform = scCmsCreateTransform(inputProf, inputProfFormat, cmSettings.monitorProfile(), 
02044                                                                        TYPE_BGRA_8, cmSettings.intent(), cmsFlags);
02045                      }
02046                      break;
02047               case RawData: // no Conversion just raw Data
02048                      xform = 0;
02049                      if ((ext == "psd") || (ext == "tif") || (ext == "tiff"))
02050                      {
02051                             *this = pDataLoader->r_image.convertToQImage(true, true);
02052                             imgInfo = pDataLoader->imageInfoRecord();
02053                      }
02054                      break;
02055               }
02056               if (xform)
02057               {
02058                      if ((ext == "psd") || (ext == "tif") || (ext == "tiff"))
02059                      {
02060                             create(pDataLoader->r_image.width(), pDataLoader->r_image.height(), 32);
02061                             setAlphaBuffer( true );
02062                             imgInfo = pDataLoader->imageInfoRecord();
02063                      }
02064                      LPBYTE ptr2 = NULL;
02065                      for (int i = 0; i < height(); i++)
02066                      {
02067                             LPBYTE ptr = scanLine(i);
02068                             if ((ext == "psd") || (ext == "tif") || (ext == "tiff"))
02069                                    ptr2 = pDataLoader->r_image.scanLine(i);
02070                             if ( inputProfFormat == TYPE_GRAY_8 && (reqType != CMYKData) )
02071                             {
02072                                    unsigned char* ucs = ptr + 1;
02073                                    unsigned char* uc = new unsigned char[width()];
02074                                    for( int uci = 0; uci < width(); uci++ )
02075                                    {
02076                                           uc[uci] = *ucs;
02077                                           ucs += 4;
02078                                    }
02079                                    cmsDoTransform(xform, uc, ptr, width());
02080                                    delete[] uc;
02081                             }
02082                             else if ( inputProfFormat == TYPE_GRAY_8 && (reqType == CMYKData) )
02083                             {
02084                                    unsigned char  value;
02085                                    unsigned char* ucs = ptr;
02086                                    for( int uci = 0; uci < width(); uci++ )
02087                                    {
02088                                           value = 255 - *(ucs + 1);
02089                                           ucs[0] = ucs[1] = ucs[2] = 0;
02090                                           ucs[3] = value;
02091                                           ucs += 4;
02092                                    }
02093                             }
02094                             else
02095                             {
02096                                    if ((ext == "psd") || (ext == "tif") || (ext == "tiff"))
02097                                    {
02098                                           cmsDoTransform(xform, ptr2, ptr, width());
02099                                    }
02100                                    else
02101                                           cmsDoTransform(xform, ptr, ptr, width());
02102                             }
02103                             // if transforming from CMYK to RGB, flatten the alpha channel
02104                             // which will still contain the black channel
02105                             if (!((ext == "psd") || (ext == "tif") || (ext == "tiff")))
02106                             {
02107                                    QRgb alphaFF = qRgba(0,0,0,255);
02108                                    QRgb *p;
02109                                    if (isCMYK && reqType != CMYKData && !bilevel)
02110                                    {
02111                                           p = (QRgb *) ptr;
02112                                           for (int j = 0; j < width(); j++, p++)
02113                                                  *p |= alphaFF;
02114                                    }
02115                             }
02116                             else
02117                             {
02118                                    if (reqType != CMYKData && !bilevel)
02119                                    {
02120                                           if (pDataLoader->r_image.channels() == 5)
02121                                           {
02122                                                  QRgb *p = (QRgb *) ptr;
02123                                                  for (int j = 0; j < width(); j++, p++)
02124                                                  {
02125                                                         *p = qRgba(qRed(*p), qGreen(*p), qBlue(*p), ptr2[4]);
02126                                                         ptr2 += 5;
02127                                                  }
02128                                           }
02129                                           else
02130                                           {
02131                                                  QRgb *p = (QRgb *) ptr;
02132                                                  for (int j = 0; j < width(); j++, p++)
02133                                                  {
02134                                                         if (isCMYK)
02135                                                                *p = qRgba(qRed(*p), qGreen(*p), qBlue(*p), 255);
02136                                                         else
02137                                                                *p = qRgba(qRed(*p), qGreen(*p), qBlue(*p), ptr2[3]);
02138                                                         ptr2 += 4;
02139                                                  }
02140                                           }
02141                                    }
02142                             }
02143                      }
02144                      if (!stdProof)
02145                             cmsDeleteTransform (xform);
02146               }
02147               if ((inputProf) && (inputProfisEmbedded))
02148                      cmsCloseProfile(inputProf);
02149               if (isCMYK)
02150                      cmsChangeBuffersFormat(cmSettings.doc()->stdProofImgCMYK, TYPE_CMYK_8, TYPE_RGBA_8);
02151               else
02152                      cmsChangeBuffersFormat(cmSettings.doc()->stdProofImg, TYPE_RGBA_8, TYPE_RGBA_8);
02153        }
02154        else
02155        {
02156               switch (reqType)
02157               {
02158               case CMYKData:
02159                      if (!isCMYK)
02160                      {
02161                             if ((ext == "psd") || (ext == "tif") || (ext == "tiff"))
02162                             {
02163                                    *this = pDataLoader->r_image.convertToQImage(false);
02164                                    imgInfo = pDataLoader->imageInfoRecord();
02165                             }
02166                             unsigned char cc, cm, cy ,ck;
02167                             QRgb *ptr;
02168                             for (int i = 0; i < height(); i++)
02169                             {
02170                                    ptr = (QRgb *) scanLine(i);
02171                                    for (int j = 0; j < width(); j++)
02172                                    {
02173                                           cc = 255 - qRed(*ptr);
02174                                           cm = 255 - qGreen(*ptr);
02175                                           cy = 255 - qBlue(*ptr);
02176                                           ck = QMIN(QMIN(cc, cm), cy);
02177                                           *ptr++ = qRgba(cc-ck,cm-ck,cy-ck,ck);
02178                                    }
02179                             }
02180                      }
02181                      else
02182                      {
02183                             if ((ext == "psd") || (ext == "tif") || (ext == "tiff"))
02184                             {
02185                                    *this = pDataLoader->r_image.convertToQImage(true, true);
02186                                    imgInfo = pDataLoader->imageInfoRecord();
02187                             }
02188                      }
02189                      break;
02190               case RGBData:
02191               case RGBProof:
02192               case Thumbnail:
02193                      if (isCMYK)
02194                      {
02195                             if ((ext == "psd") || (ext == "tif") || (ext == "tiff"))
02196                             {
02197                                    *this = pDataLoader->r_image.convertToQImage(true);
02198                                    imgInfo = pDataLoader->imageInfoRecord();
02199                             }
02200                             else
02201                             {
02202                                    unsigned char cr, cg, cb, ck;
02203                                    QRgb *ptr;
02204                                    for (int i = 0; i < height(); i++)
02205                                    {
02206                                           ptr = (QRgb *) scanLine(i);
02207                                           for (int j = 0; j < width(); j++)
02208                                           {
02209                                                  ck = qAlpha(*ptr);
02210                                                  cr = 255 - QMIN(255, qRed(*ptr) + ck);
02211                                                  cg = 255 - QMIN(255, qGreen(*ptr) + ck);
02212                                                  cb = 255 - QMIN(255, qBlue(*ptr) + ck);
02213                                                  *ptr++ = qRgba(cr,cg,cb,255);
02214                                           }
02215                                    }
02216                             }
02217                      }
02218                      else
02219                      {
02220                             if ((ext == "psd") || (ext == "tif") || (ext == "tiff"))
02221                             {
02222                                    *this = pDataLoader->r_image.convertToQImage(false);
02223                                    imgInfo = pDataLoader->imageInfoRecord();
02224                             }
02225                      }
02226                      break;
02227               case RawData:
02228                             if ((ext == "psd") || (ext == "tif") || (ext == "tiff"))
02229                             {
02230                                    *this = pDataLoader->r_image.convertToQImage(true, true);
02231                                    imgInfo = pDataLoader->imageInfoRecord();
02232                             }
02233                      break;
02234               }
02235        }
02236        if (((reqType == CMYKData) || ((reqType == RawData) && isCMYK)) && !bilevel)
02237               setAlphaBuffer(false);
02238        setDotsPerMeterX (QMAX(2834, (int) (imgInfo.xres / 0.0254)));
02239        setDotsPerMeterY (QMAX(2834, (int) (imgInfo.yres / 0.0254)));
02240        if     (ScCore->usingGUI() && pDataLoader->issuedWarningMsg() && showMsg)
02241        {
02242               QMessageBox::warning(ScCore->primaryMainWindow(), CommonStrings::trWarning, pDataLoader->getMessage(), 1, 0, 0);
02243        }
02244        else if (pDataLoader->issuedErrorMsg())
02245        {
02246               QString msg = pDataLoader->getMessage();
02247               qWarning( msg.local8Bit().data() );
02248        }
02249        return true;
02250 }