00001
00002
00003
00004
00005
00006
00007
00008 #include "cmsettings.h"
00009 #include "scimage.h"
00010 #include "scribus.h"
00011 #include "scpaths.h"
00012 #include "scribuscore.h"
00013 #include "scimgdataloader_gimp.h"
00014 #include "scimgdataloader_jpeg.h"
00015 #include "scimgdataloader_ps.h"
00016 #include "scimgdataloader_psd.h"
00017 #include "scimgdataloader_pdf.h"
00018 #include "scimgdataloader_qt.h"
00019 #include "scimgdataloader_tiff.h"
00020 #include <QMessageBox>
00021 #include <QTextStream>
00022 #include <QList>
00023 #include <QByteArray>
00024 #include <cassert>
00025 #include <cmath>
00026 #include <cstdlib>
00027 #include <memory>
00028 #include <setjmp.h>
00029 #include CMS_INC
00030 #include "util_cms.h"
00031 #include "commonstrings.h"
00032 #include "exif.h"
00033 #include "util_ghostscript.h"
00034 #include "rawimage.h"
00035 #include "sccolorengine.h"
00036 #include "util.h"
00037 #include "util_color.h"
00038 #include "util_formats.h"
00039 #include "scstreamfilter.h"
00040
00041 extern "C"
00042 {
00043 #define XMD_H // shut JPEGlib up
00044 #if defined(Q_OS_UNIXWARE)
00045 # define HAVE_BOOLEAN // libjpeg under Unixware seems to need this
00046 #endif
00047 #include <jpeglib.h>
00048 #include <jerror.h>
00049 #undef HAVE_STDLIB_H
00050 #ifdef const
00051 # undef const // remove crazy C hackery in jconfig.h
00052 #endif
00053 }
00054
00055 using namespace std;
00056
00057 typedef struct my_error_mgr
00058 {
00059 struct jpeg_error_mgr pub;
00060 jmp_buf setjmp_buffer;
00061 }
00062 *my_error_ptr;
00063
00064 static void my_error_exit (j_common_ptr cinfo)
00065 {
00066 my_error_ptr myerr = (my_error_ptr) cinfo->err;
00067 (*cinfo->err->output_message) (cinfo);
00068 longjmp (myerr->setjmp_buffer, 1);
00069 }
00070
00071 ScImage::ScImage(const QImage & image) : QImage(image)
00072 {
00073 initialize();
00074 }
00075
00076
00077
00078 ScImage::ScImage(const ScImage & image) : QImage(image.copy())
00079 {
00080 initialize();
00081 }
00082
00083
00084 ScImage::ScImage() : QImage()
00085 {
00086 initialize();
00087 }
00088
00089 ScImage::ScImage( int width, int height ) : QImage( width, height, QImage::Format_ARGB32 )
00090 {
00091 initialize();
00092 }
00093
00094 const QImage& ScImage::qImage()
00095 {
00096 return *this;
00097 }
00098
00099 QImage* ScImage::qImagePtr()
00100 {
00101 return this;
00102 }
00103
00104 QImage ScImage::scaled(int h, int w, Qt::AspectRatioMode mode, Qt::TransformationMode transformMode) const
00105 {
00106 return QImage::scaled(h, w, mode, transformMode);
00107 }
00108
00109
00110 void ScImage::initialize()
00111 {
00112 imgInfo.xres = 72;
00113 imgInfo.yres = 72;
00114 imgInfo.colorspace = ColorSpaceRGB;
00115 imgInfo.valid = false;
00116 imgInfo.isRequest = false;
00117 imgInfo.isEmbedded = false;
00118 imgInfo.progressive = false;
00119 imgInfo.exifDataValid = false;
00120 imgInfo.lowResType = 1;
00121 imgInfo.lowResScale = 1.0;
00122 imgInfo.PDSpathData.clear();
00123 imgInfo.RequestProps.clear();
00124 imgInfo.clipPath = "";
00125 imgInfo.usedPath = "";
00126 imgInfo.layerInfo.clear();
00127 imgInfo.duotoneColors.clear();
00128 imgInfo.exifInfo.cameraName = "";
00129 imgInfo.exifInfo.cameraVendor = "";
00130 imgInfo.exifInfo.thumbnail = QImage();
00131 imgInfo.BBoxX = 0;
00132 imgInfo.BBoxH = 0;
00133 }
00134
00135 ScImage::~ScImage()
00136 {
00137 curveTable.resize(0);
00138 }
00139
00140 void ScImage::applyEffect(const ScImageEffectList& effectsList, ColorList& colors, bool cmyk)
00141 {
00142 ScribusDoc* doc = colors.document();
00143 if (effectsList.count() != 0)
00144 {
00145 for (int a = 0; a < effectsList.count(); ++a)
00146 {
00147 if (effectsList.at(a).effectCode == EF_INVERT)
00148 invert(cmyk);
00149 if (effectsList.at(a).effectCode == EF_GRAYSCALE)
00150 toGrayscale(cmyk);
00151 if (effectsList.at(a).effectCode == EF_COLORIZE)
00152 {
00153 QString tmpstr = effectsList.at(a).effectParameters;
00154 QString col = CommonStrings::None;
00155 int shading = 100;
00156 QTextStream fp(&tmpstr, QIODevice::ReadOnly);
00157 fp >> col;
00158 fp >> shading;
00159 colorize(doc, colors[col], shading, cmyk);
00160 }
00161 if (effectsList.at(a).effectCode == EF_BRIGHTNESS)
00162 {
00163 QString tmpstr = effectsList.at(a).effectParameters;
00164 int brightnessValue = 0;
00165 QTextStream fp(&tmpstr, QIODevice::ReadOnly);
00166 fp >> brightnessValue;
00167 brightness(brightnessValue, cmyk);
00168 }
00169 if (effectsList.at(a).effectCode == EF_CONTRAST)
00170 {
00171 QString tmpstr = effectsList.at(a).effectParameters;
00172 int contrastValue = 0;
00173 QTextStream fp(&tmpstr, QIODevice::ReadOnly);
00174 fp >> contrastValue;
00175 contrast(contrastValue, cmyk);
00176 }
00177 if (effectsList.at(a).effectCode == EF_SHARPEN)
00178 {
00179 QString tmpstr = effectsList.at(a).effectParameters;
00180 double radius, sigma;
00181 QTextStream fp(&tmpstr, QIODevice::ReadOnly);
00182 fp >> radius;
00183 fp >> sigma;
00184 sharpen(radius, sigma);
00185 }
00186 if (effectsList.at(a).effectCode == EF_BLUR)
00187 {
00188 QString tmpstr = effectsList.at(a).effectParameters;
00189 double radius, sigma;
00190 QTextStream fp(&tmpstr, QIODevice::ReadOnly);
00191 fp >> radius;
00192 fp >> sigma;
00193 blur(static_cast<int>(radius));
00194 }
00195 if (effectsList.at(a).effectCode == EF_SOLARIZE)
00196 {
00197 QString tmpstr = effectsList.at(a).effectParameters;
00198 double sigma;
00199 QTextStream fp(&tmpstr, QIODevice::ReadOnly);
00200 fp >> sigma;
00201 solarize(sigma, cmyk);
00202 }
00203 if (effectsList.at(a).effectCode == EF_DUOTONE)
00204 {
00205 QString tmpstr = effectsList.at(a).effectParameters;
00206 QString col1 = CommonStrings::None;
00207 int shading1 = 100;
00208 QString col2 = CommonStrings::None;
00209 int shading2 = 100;
00210 QTextStream fp(&tmpstr, QIODevice::ReadOnly);
00211 col1 = fp.readLine();
00212 col2 = fp.readLine();
00213 fp >> shading1;
00214 fp >> shading2;
00215 int numVals;
00216 double xval, yval;
00217 FPointArray curve1;
00218 curve1.resize(0);
00219 fp >> numVals;
00220 for (int nv = 0; nv < numVals; nv++)
00221 {
00222 fp >> xval;
00223 fp >> yval;
00224 curve1.addPoint(xval, yval);
00225 }
00226 int lin1;
00227 fp >> lin1;
00228 FPointArray curve2;
00229 curve2.resize(0);
00230 fp >> numVals;
00231 for (int nv = 0; nv < numVals; nv++)
00232 {
00233 fp >> xval;
00234 fp >> yval;
00235 curve2.addPoint(xval, yval);
00236 }
00237 int lin2;
00238 fp >> lin2;
00239 duotone(doc, colors[col1], shading1, curve1, lin1, colors[col2], shading2, curve2, lin2, cmyk);
00240 }
00241 if (effectsList.at(a).effectCode == EF_TRITONE)
00242 {
00243 QString tmpstr = effectsList.at(a).effectParameters;
00244 QString col1 = CommonStrings::None;
00245 QString col2 = CommonStrings::None;
00246 QString col3 = CommonStrings::None;
00247 int shading1 = 100;
00248 int shading2 = 100;
00249 int shading3 = 100;
00250 QTextStream fp(&tmpstr, QIODevice::ReadOnly);
00251 col1 = fp.readLine();
00252 col2 = fp.readLine();
00253 col3 = fp.readLine();
00254 fp >> shading1;
00255 fp >> shading2;
00256 fp >> shading3;
00257 int numVals;
00258 double xval, yval;
00259 FPointArray curve1;
00260 curve1.resize(0);
00261 fp >> numVals;
00262 for (int nv = 0; nv < numVals; nv++)
00263 {
00264 fp >> xval;
00265 fp >> yval;
00266 curve1.addPoint(xval, yval);
00267 }
00268 int lin1;
00269 fp >> lin1;
00270 FPointArray curve2;
00271 curve2.resize(0);
00272 fp >> numVals;
00273 for (int nv = 0; nv < numVals; nv++)
00274 {
00275 fp >> xval;
00276 fp >> yval;
00277 curve2.addPoint(xval, yval);
00278 }
00279 int lin2;
00280 fp >> lin2;
00281 FPointArray curve3;
00282 curve3.resize(0);
00283 fp >> numVals;
00284 for (int nv = 0; nv < numVals; nv++)
00285 {
00286 fp >> xval;
00287 fp >> yval;
00288 curve3.addPoint(xval, yval);
00289 }
00290 int lin3;
00291 fp >> lin3;
00292 tritone(doc, colors[col1], shading1, curve1, lin1, colors[col2], shading2, curve2, lin2, colors[col3], shading3, curve3, lin3, cmyk);
00293 }
00294 if (effectsList.at(a).effectCode == EF_QUADTONE)
00295 {
00296 QString tmpstr = effectsList.at(a).effectParameters;
00297 QString col1 = CommonStrings::None;
00298 QString col2 = CommonStrings::None;
00299 QString col3 = CommonStrings::None;
00300 QString col4 = CommonStrings::None;
00301 int shading1 = 100;
00302 int shading2 = 100;
00303 int shading3 = 100;
00304 int shading4 = 100;
00305 QTextStream fp(&tmpstr, QIODevice::ReadOnly);
00306 col1 = fp.readLine();
00307 col2 = fp.readLine();
00308 col3 = fp.readLine();
00309 col4 = fp.readLine();
00310 fp >> shading1;
00311 fp >> shading2;
00312 fp >> shading3;
00313 fp >> shading4;
00314 int numVals;
00315 double xval, yval;
00316 FPointArray curve1;
00317 curve1.resize(0);
00318 fp >> numVals;
00319 for (int nv = 0; nv < numVals; nv++)
00320 {
00321 fp >> xval;
00322 fp >> yval;
00323 curve1.addPoint(xval, yval);
00324 }
00325 int lin1;
00326 fp >> lin1;
00327 FPointArray curve2;
00328 curve2.resize(0);
00329 fp >> numVals;
00330 for (int nv = 0; nv < numVals; nv++)
00331 {
00332 fp >> xval;
00333 fp >> yval;
00334 curve2.addPoint(xval, yval);
00335 }
00336 int lin2;
00337 fp >> lin2;
00338 FPointArray curve3;
00339 curve3.resize(0);
00340 fp >> numVals;
00341 for (int nv = 0; nv < numVals; nv++)
00342 {
00343 fp >> xval;
00344 fp >> yval;
00345 curve3.addPoint(xval, yval);
00346 }
00347 int lin3;
00348 fp >> lin3;
00349 FPointArray curve4;
00350 curve4.resize(0);
00351 fp >> numVals;
00352 for (int nv = 0; nv < numVals; nv++)
00353 {
00354 fp >> xval;
00355 fp >> yval;
00356 curve4.addPoint(xval, yval);
00357 }
00358 int lin4;
00359 fp >> lin4;
00360 quadtone(doc, colors[col1], shading1, curve1, lin1, colors[col2], shading2, curve2, lin2, colors[col3], shading3, curve3, lin3, colors[col4], shading4, curve4, lin4, cmyk);
00361 }
00362 if (effectsList.at(a).effectCode == EF_GRADUATE)
00363 {
00364 QString tmpstr = effectsList.at(a).effectParameters;
00365 int numVals;
00366 double xval, yval;
00367 FPointArray curve;
00368 curve.resize(0);
00369 QTextStream fp(&tmpstr, QIODevice::ReadOnly);
00370 fp >> numVals;
00371 for (int nv = 0; nv < numVals; nv++)
00372 {
00373 fp >> xval;
00374 fp >> yval;
00375 curve.addPoint(xval, yval);
00376 }
00377 int lin;
00378 fp >> lin;
00379 doGraduate(curve, cmyk, lin);
00380 }
00381 }
00382 }
00383 }
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394 void ScImage::solarize(double factor, bool cmyk)
00395 {
00396 curveTable.resize(256);
00397 int fk = qRound(255 / factor);
00398 for (int i = 0; i < 256; ++i)
00399 {
00400 curveTable[i] = qMin(255, static_cast<int>(i / fk) * fk);
00401 }
00402 applyCurve(cmyk);
00403 }
00404
00405
00406 void ScImage::blur(int radius)
00407 {
00408 if (radius < 1) {
00409 return;
00410 }
00411
00412 QRgb *pix = (QRgb*)bits();
00413 int w = width();
00414 int h = height();
00415 int wm = w-1;
00416 int hm = h-1;
00417 int wh = w*h;
00418 int div = radius+radius+1;
00419
00420 int *r = new int[wh];
00421 int *g = new int[wh];
00422 int *b = new int[wh];
00423 int *a = new int[wh];
00424 int rsum, gsum, bsum, asum, x, y, i, yp, yi, yw;
00425 QRgb p;
00426 int *vmin = new int[qMax(w,h)];
00427
00428 int divsum = (div+1)>>1;
00429 divsum *= divsum;
00430 int *dv = new int[256*divsum];
00431 for (i=0; i < 256*divsum; ++i) {
00432 dv[i] = (i/divsum);
00433 }
00434
00435 yw = yi = 0;
00436
00437 int **stack = new int*[div];
00438 for(int i = 0; i < div; ++i) {
00439 stack[i] = new int[4];
00440 }
00441
00442
00443 int stackpointer;
00444 int stackstart;
00445 int *sir;
00446 int rbs;
00447 int r1 = radius+1;
00448 int routsum, goutsum, boutsum, aoutsum;
00449 int rinsum, ginsum, binsum, ainsum;
00450
00451 for (y = 0; y < h; ++y){
00452 rinsum = ginsum = binsum = ainsum
00453 = routsum = goutsum = boutsum = aoutsum
00454 = rsum = gsum = bsum = asum = 0;
00455 for(i =- radius; i <= radius; ++i) {
00456 p = pix[yi+qMin(wm,qMax(i,0))];
00457 sir = stack[i+radius];
00458 sir[0] = qRed(p);
00459 sir[1] = qGreen(p);
00460 sir[2] = qBlue(p);
00461 sir[3] = qAlpha(p);
00462
00463 rbs = r1-abs(i);
00464 rsum += sir[0]*rbs;
00465 gsum += sir[1]*rbs;
00466 bsum += sir[2]*rbs;
00467 asum += sir[3]*rbs;
00468
00469 if (i > 0){
00470 rinsum += sir[0];
00471 ginsum += sir[1];
00472 binsum += sir[2];
00473 ainsum += sir[3];
00474 } else {
00475 routsum += sir[0];
00476 goutsum += sir[1];
00477 boutsum += sir[2];
00478 aoutsum += sir[3];
00479 }
00480 }
00481 stackpointer = radius;
00482
00483 for (x=0; x < w; ++x) {
00484
00485 r[yi] = dv[rsum];
00486 g[yi] = dv[gsum];
00487 b[yi] = dv[bsum];
00488 a[yi] = dv[asum];
00489
00490 rsum -= routsum;
00491 gsum -= goutsum;
00492 bsum -= boutsum;
00493 asum -= aoutsum;
00494
00495 stackstart = stackpointer-radius+div;
00496 sir = stack[stackstart%div];
00497
00498 routsum -= sir[0];
00499 goutsum -= sir[1];
00500 boutsum -= sir[2];
00501 aoutsum -= sir[3];
00502
00503 if (y == 0) {
00504 vmin[x] = qMin(x+radius+1,wm);
00505 }
00506 p = pix[yw+vmin[x]];
00507
00508 sir[0] = qRed(p);
00509 sir[1] = qGreen(p);
00510 sir[2] = qBlue(p);
00511 sir[3] = qAlpha(p);
00512
00513 rinsum += sir[0];
00514 ginsum += sir[1];
00515 binsum += sir[2];
00516 ainsum += sir[3];
00517
00518 rsum += rinsum;
00519 gsum += ginsum;
00520 bsum += binsum;
00521 asum += ainsum;
00522
00523 stackpointer = (stackpointer+1)%div;
00524 sir = stack[(stackpointer)%div];
00525
00526 routsum += sir[0];
00527 goutsum += sir[1];
00528 boutsum += sir[2];
00529 aoutsum += sir[3];
00530
00531 rinsum -= sir[0];
00532 ginsum -= sir[1];
00533 binsum -= sir[2];
00534 ainsum -= sir[3];
00535
00536 ++yi;
00537 }
00538 yw += w;
00539 }
00540 for (x=0; x < w; ++x){
00541 rinsum = ginsum = binsum = ainsum
00542 = routsum = goutsum = boutsum = aoutsum
00543 = rsum = gsum = bsum = asum = 0;
00544
00545 yp =- radius * w;
00546
00547 for(i=-radius; i <= radius; ++i) {
00548 yi=qMax(0,yp)+x;
00549
00550 sir = stack[i+radius];
00551
00552 sir[0] = r[yi];
00553 sir[1] = g[yi];
00554 sir[2] = b[yi];
00555 sir[3] = a[yi];
00556
00557 rbs = r1-abs(i);
00558
00559 rsum += r[yi]*rbs;
00560 gsum += g[yi]*rbs;
00561 bsum += b[yi]*rbs;
00562 asum += a[yi]*rbs;
00563
00564 if (i > 0) {
00565 rinsum += sir[0];
00566 ginsum += sir[1];
00567 binsum += sir[2];
00568 ainsum += sir[3];
00569 } else {
00570 routsum += sir[0];
00571 goutsum += sir[1];
00572 boutsum += sir[2];
00573 aoutsum += sir[3];
00574 }
00575
00576 if (i < hm){
00577 yp += w;
00578 }
00579 }
00580
00581 yi = x;
00582 stackpointer = radius;
00583
00584 for (y=0; y < h; ++y){
00585 pix[yi] = qRgba(dv[rsum], dv[gsum], dv[bsum], dv[asum]);
00586
00587 rsum -= routsum;
00588 gsum -= goutsum;
00589 bsum -= boutsum;
00590 asum -= aoutsum;
00591
00592 stackstart = stackpointer-radius+div;
00593 sir = stack[stackstart%div];
00594
00595 routsum -= sir[0];
00596 goutsum -= sir[1];
00597 boutsum -= sir[2];
00598 aoutsum -= sir[3];
00599
00600 if (x==0){
00601 vmin[y] = qMin(y+r1,hm)*w;
00602 }
00603 p = x+vmin[y];
00604
00605 sir[0] = r[p];
00606 sir[1] = g[p];
00607 sir[2] = b[p];
00608 sir[3] = a[p];
00609
00610 rinsum += sir[0];
00611 ginsum += sir[1];
00612 binsum += sir[2];
00613 ainsum += sir[3];
00614
00615 rsum += rinsum;
00616 gsum += ginsum;
00617 bsum += binsum;
00618 asum += ainsum;
00619
00620 stackpointer = (stackpointer+1)%div;
00621 sir = stack[stackpointer];
00622
00623 routsum += sir[0];
00624 goutsum += sir[1];
00625 boutsum += sir[2];
00626 aoutsum += sir[3];
00627
00628 rinsum -= sir[0];
00629 ginsum -= sir[1];
00630 binsum -= sir[2];
00631 ainsum -= sir[3];
00632
00633 yi += w;
00634 }
00635 }
00636 delete [] r;
00637 delete [] g;
00638 delete [] b;
00639 delete [] a;
00640 delete [] vmin;
00641 delete [] dv;
00642
00643 for(int i = 0; i < div; ++i) {
00644 delete [] stack[i];
00645 }
00646 delete [] stack;
00647 }
00648
00649 bool ScImage::convolveImage(QImage *dest, const unsigned int order, const double *kernel)
00650 {
00651 long widthk;
00652 double red, green, blue, alpha;
00653 double normalize, *normal_kernel;
00654 register const double *k;
00655 register unsigned int *q;
00656 int x, y, mx, my, sx, sy;
00657 long i;
00658 int mcx, mcy;
00659 widthk = order;
00660 if((widthk % 2) == 0)
00661 return(false);
00662 normal_kernel = (double *)malloc(widthk*widthk*sizeof(double));
00663 if(!normal_kernel)
00664 return(false);
00665 *dest = QImage();
00666 *dest = QImage(width(), height(), QImage::Format_ARGB32);
00667 normalize=0.0;
00668 for(i=0; i < (widthk*widthk); i++)
00669 normalize += kernel[i];
00670 if(fabs(normalize) <= 1.0e-12)
00671 normalize=1.0;
00672 normalize=1.0/normalize;
00673 for(i=0; i < (widthk*widthk); i++)
00674 normal_kernel[i] = normalize*kernel[i];
00675 for(y=0; y < dest->height(); ++y)
00676 {
00677 sy = y-(widthk/2);
00678 q = (unsigned int *)dest->scanLine(y);
00679 for(x=0; x < dest->width(); ++x)
00680 {
00681 k = normal_kernel;
00682 red = green = blue = alpha = 0;
00683 sy = y-(widthk/2);
00684 for(mcy=0; mcy < widthk; ++mcy, ++sy)
00685 {
00686 my = sy < 0 ? 0 : sy > height()-1 ? height()-1 : sy;
00687 sx = x+(-widthk/2);
00688 for(mcx=0; mcx < widthk; ++mcx, ++sx)
00689 {
00690 mx = sx < 0 ? 0 : sx > width()-1 ? width()-1 : sx;
00691 red += (*k)*(qRed(scanLine(my)[mx])*257);
00692 green += (*k)*(qGreen(scanLine(my)[mx])*257);
00693 blue += (*k)*(qBlue(scanLine(my)[mx])*257);
00694 alpha += (*k)*(qAlpha(scanLine(my)[mx])*257);
00695 ++k;
00696 }
00697 }
00698 red = red < 0 ? 0 : red > 65535 ? 65535 : red+0.5;
00699 green = green < 0 ? 0 : green > 65535 ? 65535 : green+0.5;
00700 blue = blue < 0 ? 0 : blue > 65535 ? 65535 : blue+0.5;
00701 alpha = alpha < 0 ? 0 : alpha > 65535 ? 65535 : alpha+0.5;
00702 *q++ = qRgba((unsigned char)(red/257UL),
00703 (unsigned char)(green/257UL),
00704 (unsigned char)(blue/257UL),
00705 (unsigned char)(alpha/257UL));
00706 }
00707 }
00708 free(normal_kernel);
00709 return(true);
00710 }
00711
00712 int ScImage::getOptimalKernelWidth(double radius, double sigma)
00713 {
00714 double normalize, value;
00715 long width;
00716 register long u;
00717 assert(sigma != 0.0);
00718 if(radius > 0.0)
00719 return((int)(2.0*ceil(radius)+1.0));
00720 for(width=5; ;)
00721 {
00722 normalize=0.0;
00723 for(u=(-width/2); u <= (width/2); u++)
00724 normalize+=exp(-((double) u*u)/(2.0*sigma*sigma))/(2.50662827463100024161235523934010416269302368164062*sigma);
00725 u=width/2;
00726 value=exp(-((double) u*u)/(2.0*sigma*sigma))/(2.50662827463100024161235523934010416269302368164062*sigma)/normalize;
00727 if((long)(65535*value) <= 0)
00728 break;
00729 width+=2;
00730 }
00731 return((int)width-2);
00732 }
00733
00734 void ScImage::sharpen(double radius, double sigma)
00735 {
00736 double alpha, normalize, *kernel;
00737 int widthk;
00738 register long i, u, v;
00739 QImage dest;
00740 if(sigma == 0.0)
00741 return;
00742 widthk = getOptimalKernelWidth(radius, sigma);
00743 if(width() < widthk)
00744 return;
00745 kernel = (double *)malloc(widthk*widthk*sizeof(double));
00746 if(!kernel)
00747 return;
00748 i = 0;
00749 normalize=0.0;
00750 for (v=(-widthk/2); v <= (widthk/2); v++)
00751 {
00752 for (u=(-widthk/2); u <= (widthk/2); u++)
00753 {
00754 alpha=exp(-((double) u*u+v*v)/(2.0*sigma*sigma));
00755 kernel[i]=alpha/(2.0*3.14159265358979323846264338327950288419716939937510*sigma*sigma);
00756 normalize+=kernel[i];
00757 i++;
00758 }
00759 }
00760 kernel[i/2]=(-2.0)*normalize;
00761 convolveImage(&dest, widthk, kernel);
00762 free(kernel);
00763
00764 for( int yi=0; yi < dest.height(); ++yi )
00765 {
00766 QRgb *s = (QRgb*)(dest.scanLine( yi ));
00767 QRgb *d = (QRgb*)(scanLine( yi ));
00768 for(int xi=0; xi < dest.width(); ++xi )
00769 {
00770 (*d) = (*s);
00771 s++;
00772 d++;
00773 }
00774 }
00775 return;
00776 }
00777
00778 void ScImage::contrast(int contrastValue, bool cmyk)
00779 {
00780 curveTable.resize(256);
00781 QPoint p1(0,0 - contrastValue);
00782 QPoint p2(256, 256 + contrastValue);
00783 double mc = (p1.y() - p2.y()) / (double)(p1.x() - p2.x());
00784 for (int i = 0; i < 256; ++i)
00785 {
00786 curveTable[i] = qMin(255, qMax(0, int(i * mc) + p1.y()));
00787 }
00788 applyCurve(cmyk);
00789 }
00790
00791 void ScImage::brightness(int brightnessValue, bool cmyk)
00792 {
00793 curveTable.resize(256);
00794 QPoint p1(0,0 + brightnessValue);
00795 QPoint p2(256, 256 + brightnessValue);
00796 double mc = (p1.y() - p2.y()) / (double)(p1.x() - p2.x());
00797 for (int i = 0; i < 256; ++i)
00798 {
00799 curveTable[i] = qMin(255, qMax(0, int(i * mc) + p1.y()));
00800 }
00801 applyCurve(cmyk);
00802 }
00803
00804 void ScImage::doGraduate(FPointArray curve, bool cmyk, bool linear)
00805 {
00806 curveTable.resize(256);
00807 for (int x = 0 ; x < 256 ; x++)
00808 {
00809 curveTable[x] = qMin(255, qMax(0, qRound(getCurveYValue(curve, x / 255.0, linear) * 255)));
00810 }
00811 applyCurve(cmyk);
00812 }
00813
00814 void ScImage::applyCurve(bool cmyk)
00815 {
00816 int h = height();
00817 int w = width();
00818 QRgb *s;
00819 QRgb r;
00820 int c, m, y, k;
00821 unsigned char *p;
00822 unsigned char rc, gc, bc;
00823 for( int yi=0; yi < h; ++yi )
00824 {
00825 s = (QRgb*)(scanLine( yi ));
00826 for( int xi=0; xi < w; ++xi )
00827 {
00828 r = *s;
00829 if (cmyk)
00830 {
00831 p = (unsigned char *) s;
00832 rc = 255 - qMin(255, p[0] + p[3]);
00833 gc = 255 - qMin(255, p[1] + p[3]);
00834 bc = 255 - qMin(255, p[2] + p[3]);
00835 c = 255 - curveTable[(int)rc];
00836 m = 255 - curveTable[(int)gc];
00837 y = 255 - curveTable[(int)bc];
00838 k = qMin(qMin(c, m), y);
00839 *s = qRgba(y - k, m - k, c - k, k );
00840 }
00841 else
00842 {
00843 c = curveTable[qRed(r)];
00844 m = curveTable[qGreen(r)];
00845 y = curveTable[qBlue(r)];
00846 k = qAlpha(r);
00847 *s = qRgba(c, m, y, k);
00848 }
00849 s++;
00850 }
00851 }
00852 }
00853
00854 void ScImage::colorize(ScribusDoc* doc, ScColor color, int shade, bool cmyk)
00855 {
00856 int h = height();
00857 int w = width();
00858 int cc, cm, cy, ck;
00859 int hu, sa, v;
00860 ScColor tmp2;
00861 QColor tmpR;
00862 QRgb *s;
00863 QRgb r;
00864 double k;
00865 int cc2, cm2, cy2, k2;
00866 if (cmyk)
00867 {
00868 CMYKColor cmykCol;
00869 ScColorEngine::getShadeColorCMYK(color, doc, cmykCol, shade);
00870 cmykCol.getValues(cc, cm, cy, ck);
00871 }
00872 else
00873 {
00874 ck = 0;
00875 RGBColor rgbCol;
00876 ScColorEngine::getShadeColorRGB(color, doc, rgbCol, shade);
00877 rgbCol.getValues(cc, cm, cy);
00878 }
00879 for( int yi=0; yi < h; ++yi )
00880 {
00881 s = (QRgb*)(scanLine( yi ));
00882 for( int xi=0; xi < w; ++xi )
00883 {
00884 r = *s;
00885 if (cmyk)
00886 {
00887 k = qMin(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r) + qAlpha(r)), 255) / 255.0;
00888 *s = qRgba(qMin(qRound(cc*k), 255), qMin(qRound(cm*k), 255), qMin(qRound(cy*k), 255), qMin(qRound(ck*k), 255));
00889 }
00890 else
00891 {
00892 k2 = 255 - qMin(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r)), 255);
00893 tmpR.setRgb(cc, cm, cy);
00894 tmpR.getHsv(&hu, &sa, &v);
00895 tmpR.setHsv(hu, sa * k2 / 255, 255 - ((255 - v) * k2 / 255));
00896 tmpR.getRgb(&cc2, &cm2, &cy2);
00897 *s = qRgba(cc2, cm2, cy2, qAlpha(r));
00898 }
00899 s++;
00900 }
00901 }
00902 }
00903
00904 void ScImage::duotone(ScribusDoc* doc, ScColor color1, int shade1, FPointArray curve1, bool lin1, ScColor color2, int shade2, FPointArray curve2, bool lin2, bool cmyk)
00905 {
00906 int h = height();
00907 int w = width();
00908 int c, c1, m, m1, y, y1, k, k1;
00909 int cn, c1n, mn, m1n, yn, y1n, kn, k1n;
00910 uchar cb;
00911 QVector<int> curveTable1;
00912 QVector<int> curveTable2;
00913 CMYKColor cmykCol;
00914 ScColorEngine::getShadeColorCMYK(color1, doc, cmykCol, shade1);
00915 cmykCol.getValues(c, m, y, k);
00916 ScColorEngine::getShadeColorCMYK(color2, doc, cmykCol, shade2);
00917 cmykCol.getValues(c1, m1, y1, k1);
00918 curveTable1.resize(256);
00919 for (int x = 0 ; x < 256 ; x++)
00920 {
00921 curveTable1[x] = qMin(255, qMax(0, qRound(getCurveYValue(curve1, x / 255.0, lin1) * 255)));
00922 }
00923 curveTable2.resize(256);
00924 for (int x = 0 ; x < 256 ; x++)
00925 {
00926 curveTable2[x] = qMin(255, qMax(0, qRound(getCurveYValue(curve2, x / 255.0, lin2) * 255)));
00927 }
00928 for( int yi=0; yi < h; ++yi )
00929 {
00930 QRgb * s = (QRgb*)(scanLine( yi ));
00931 for( int xi=0; xi < w; ++xi )
00932 {
00933 QRgb r=*s;
00934 if (cmyk)
00935 cb = qMin(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r) + qAlpha(r)), 255);
00936 else
00937 cb = 255 - qMin(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r)), 255);
00938 cn = qMin((c * curveTable1[(int)cb]) >> 8, 255);
00939 mn = qMin((m * curveTable1[(int)cb]) >> 8, 255);
00940 yn = qMin((y * curveTable1[(int)cb]) >> 8, 255);
00941 kn = qMin((k * curveTable1[(int)cb]) >> 8, 255);
00942 c1n = qMin((c1 * curveTable1[(int)cb]) >> 8, 255);
00943 m1n = qMin((m1 * curveTable2[(int)cb]) >> 8, 255);
00944 y1n = qMin((y1 * curveTable2[(int)cb]) >> 8, 255);
00945 k1n = qMin((k1 * curveTable2[(int)cb]) >> 8, 255);
00946 ScColor col = ScColor(qMin(cn+c1n, 255), qMin(mn+m1n, 255), qMin(yn+y1n, 255), qMin(kn+k1n, 255));
00947 if (cmyk)
00948 col.getCMYK(&cn, &mn, &yn, &kn);
00949 else
00950 {
00951 col.getRawRGBColor(&cn, &mn, &yn);
00952 kn = qAlpha(r);
00953 }
00954 *s = qRgba(cn, mn, yn, kn);
00955 s++;
00956 }
00957 }
00958 }
00959
00960 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)
00961 {
00962 int h = height();
00963 int w = width();
00964 int c, c1, c2, m, m1, m2, y, y1, y2, k, k1, k2;
00965 int cn, c1n, c2n, mn, m1n, m2n, yn, y1n, y2n, kn, k1n, k2n;
00966 uchar cb;
00967 CMYKColor cmykCol;
00968 QVector<int> curveTable1;
00969 QVector<int> curveTable2;
00970 QVector<int> curveTable3;
00971 ScColorEngine::getShadeColorCMYK(color1, doc, cmykCol, shade1);
00972 cmykCol.getValues(c, m, y, k);
00973 ScColorEngine::getShadeColorCMYK(color2, doc, cmykCol, shade2);
00974 cmykCol.getValues(c1, m1, y1, k1);
00975 ScColorEngine::getShadeColorCMYK(color3, doc, cmykCol, shade3);
00976 cmykCol.getValues(c2, m2, y2, k2);
00977 curveTable1.resize(256);
00978 for (int x = 0 ; x < 256 ; x++)
00979 {
00980 curveTable1[x] = qMin(255, qMax(0, qRound(getCurveYValue(curve1, x / 255.0, lin1) * 255)));
00981 }
00982 curveTable2.resize(256);
00983 for (int x = 0 ; x < 256 ; x++)
00984 {
00985 curveTable2[x] = qMin(255, qMax(0, qRound(getCurveYValue(curve2, x / 255.0, lin2) * 255)));
00986 }
00987 curveTable3.resize(256);
00988 for (int x = 0 ; x < 256 ; x++)
00989 {
00990 curveTable3[x] = qMin(255, qMax(0, qRound(getCurveYValue(curve2, x / 255.0, lin3) * 255)));
00991 }
00992 for( int yi=0; yi < h; ++yi )
00993 {
00994 QRgb * s = (QRgb*)(scanLine( yi ));
00995 for( int xi=0; xi < w; ++xi )
00996 {
00997 QRgb r=*s;
00998 if (cmyk)
00999 cb = qMin(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r) + qAlpha(r)), 255);
01000 else
01001 cb = 255 - qMin(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r)), 255);
01002 cn = qMin((c * curveTable1[(int)cb]) >> 8, 255);
01003 mn = qMin((m * curveTable1[(int)cb]) >> 8, 255);
01004 yn = qMin((y * curveTable1[(int)cb]) >> 8, 255);
01005 kn = qMin((k * curveTable1[(int)cb]) >> 8, 255);
01006 c1n = qMin((c1 * curveTable2[(int)cb]) >> 8, 255);
01007 m1n = qMin((m1 * curveTable2[(int)cb]) >> 8, 255);
01008 y1n = qMin((y1 * curveTable2[(int)cb]) >> 8, 255);
01009 k1n = qMin((k1 * curveTable2[(int)cb]) >> 8, 255);
01010 c2n = qMin((c2 * curveTable3[(int)cb]) >> 8, 255);
01011 m2n = qMin((m2 * curveTable3[(int)cb]) >> 8, 255);
01012 y2n = qMin((y2 * curveTable3[(int)cb]) >> 8, 255);
01013 k2n = qMin((k2 * curveTable3[(int)cb]) >> 8, 255);
01014 ScColor col = ScColor(qMin(cn+c1n+c2n, 255), qMin(mn+m1n+m2n, 255), qMin(yn+y1n+y2n, 255), qMin(kn+k1n+k2n, 255));
01015 if (cmyk)
01016 col.getCMYK(&cn, &mn, &yn, &kn);
01017 else
01018 {
01019 col.getRawRGBColor(&cn, &mn, &yn);
01020 kn = qAlpha(r);
01021 }
01022 *s = qRgba(cn, mn, yn, kn);
01023 s++;
01024 }
01025 }
01026 }
01027
01028 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)
01029 {
01030 int h = height();
01031 int w = width();
01032 int c, c1, c2, c3, m, m1, m2, m3, y, y1, y2, y3, k, k1, k2, k3;
01033 int cn, c1n, c2n, c3n, mn, m1n, m2n, m3n, yn, y1n, y2n, y3n, kn, k1n, k2n, k3n;
01034 uchar cb;
01035 CMYKColor cmykCol;
01036 QVector<int> curveTable1;
01037 QVector<int> curveTable2;
01038 QVector<int> curveTable3;
01039 QVector<int> curveTable4;
01040 ScColorEngine::getShadeColorCMYK(color1, doc, cmykCol, shade1);
01041 cmykCol.getValues(c, m, y, k);
01042 ScColorEngine::getShadeColorCMYK(color2, doc, cmykCol, shade2);
01043 cmykCol.getValues(c1, m1, y1, k1);
01044 ScColorEngine::getShadeColorCMYK(color3, doc, cmykCol, shade3);
01045 cmykCol.getValues(c2, m2, y2, k2);
01046 ScColorEngine::getShadeColorCMYK(color4, doc, cmykCol, shade4);
01047 cmykCol.getValues(c3, m3, y3, k3);
01048 curveTable1.resize(256);
01049 for (int x = 0 ; x < 256 ; x++)
01050 {
01051 curveTable1[x] = qMin(255, qMax(0, qRound(getCurveYValue(curve1, x / 255.0, lin1) * 255)));
01052 }
01053 curveTable2.resize(256);
01054 for (int x = 0 ; x < 256 ; x++)
01055 {
01056 curveTable2[x] = qMin(255, qMax(0, qRound(getCurveYValue(curve2, x / 255.0, lin2) * 255)));
01057 }
01058 curveTable3.resize(256);
01059 for (int x = 0 ; x < 256 ; x++)
01060 {
01061 curveTable3[x] = qMin(255, qMax(0, qRound(getCurveYValue(curve3, x / 255.0, lin3) * 255)));
01062 }
01063 curveTable4.resize(256);
01064 for (int x = 0 ; x < 256 ; x++)
01065 {
01066 curveTable4[x] = qMin(255, qMax(0, qRound(getCurveYValue(curve4, x / 255.0, lin4) * 255)));
01067 }
01068 for( int yi=0; yi < h; ++yi )
01069 {
01070 QRgb * s = (QRgb*)(scanLine( yi ));
01071 for( int xi=0; xi < w; ++xi )
01072 {
01073 QRgb r=*s;
01074 if (cmyk)
01075 cb = qMin(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r) + qAlpha(r)), 255);
01076 else
01077 cb = 255 - qMin(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r)), 255);
01078 cn = qMin((c * curveTable1[(int)cb]) >> 8, 255);
01079 mn = qMin((m * curveTable1[(int)cb]) >> 8, 255);
01080 yn = qMin((y * curveTable1[(int)cb]) >> 8, 255);
01081 kn = qMin((k * curveTable1[(int)cb]) >> 8, 255);
01082 c1n = qMin((c1 * curveTable2[(int)cb]) >> 8, 255);
01083 m1n = qMin((m1 * curveTable2[(int)cb]) >> 8, 255);
01084 y1n = qMin((y1 * curveTable2[(int)cb]) >> 8, 255);
01085 k1n = qMin((k1 * curveTable2[(int)cb]) >> 8, 255);
01086 c2n = qMin((c2 * curveTable3[(int)cb]) >> 8, 255);
01087 m2n = qMin((m2 * curveTable3[(int)cb]) >> 8, 255);
01088 y2n = qMin((y2 * curveTable3[(int)cb]) >> 8, 255);
01089 k2n = qMin((k2 * curveTable3[(int)cb]) >> 8, 255);
01090 c3n = qMin((c3 * curveTable4[(int)cb]) >> 8, 255);
01091 m3n = qMin((m3 * curveTable4[(int)cb]) >> 8, 255);
01092 y3n = qMin((y3 * curveTable4[(int)cb]) >> 8, 255);
01093 k3n = qMin((k3 * curveTable4[(int)cb]) >> 8, 255);
01094 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));
01095 if (cmyk)
01096 col.getCMYK(&cn, &mn, &yn, &kn);
01097 else
01098 {
01099 col.getRawRGBColor(&cn, &mn, &yn);
01100 kn = qAlpha(r);
01101 }
01102 *s = qRgba(cn, mn, yn, kn);
01103 s++;
01104 }
01105 }
01106 }
01107
01108 void ScImage::invert(bool cmyk)
01109 {
01110 int h = height();
01111 int w = width();
01112 unsigned char *p;
01113 QRgb * s;
01114 unsigned char c, m, y, k;
01115 for( int yi=0; yi < h; ++yi )
01116 {
01117 s = (QRgb*)(scanLine( yi ));
01118 for( int xi=0; xi < w; ++xi )
01119 {
01120 if (cmyk)
01121 {
01122 p = (unsigned char *) s;
01123 c = 255 - qMin(255, p[0] + p[3]);
01124 m = 255 - qMin(255, p[1] + p[3]);
01125 y = 255 - qMin(255, p[2] + p[3]);
01126 k = qMin(qMin(c, m), y);
01127 p[0] = c - k;
01128 p[1] = m - k;
01129 p[2] = y - k;
01130 p[3] = k;
01131 }
01132 else
01133 *s ^= 0x00ffffff;
01134 s++;
01135 }
01136 }
01137 }
01138
01139 void ScImage::toGrayscale(bool cmyk)
01140 {
01141 int h = height();
01142 int w = width();
01143 int k;
01144 QRgb * s;
01145 QRgb r;
01146 for( int yi=0; yi < h; ++yi )
01147 {
01148 s = (QRgb*)(scanLine( yi ));
01149 for( int xi=0; xi < w; ++xi )
01150 {
01151 r = *s;
01152 if (cmyk)
01153 {
01154 k = qMin(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r) + qAlpha(r)), 255);
01155 *s = qRgba(0, 0, 0, k);
01156 }
01157 else
01158 {
01159 k = qMin(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r)), 255);
01160 *s = qRgba(k, k, k, qAlpha(r));
01161 }
01162 s++;
01163 }
01164 }
01165 }
01166
01167 void ScImage::swapRGBA()
01168 {
01169 unsigned int *ptr;
01170 unsigned char *p;
01171 unsigned char r, b;
01172 for (int i = 0; i < height(); ++i)
01173 {
01174 ptr = (unsigned int *) scanLine(i);
01175 for (int j = 0; j < width(); ++j)
01176 {
01177 p = (unsigned char *) ptr;
01178 r = p[0];
01179 b = p[2];
01180 p[2] = r;
01181 p[0] = b;
01182 ptr++;
01183 }
01184 }
01185 }
01186
01187 void ScImage::createLowRes(double scale)
01188 {
01189 int w = qRound(width() / scale);
01190 int h = qRound(height() / scale);
01191 QImage tmp = scaled(w, h, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
01192 QImage::operator=(QImage(w, h, QImage::Format_ARGB32));
01193 tmp = tmp.convertToFormat(QImage::Format_ARGB32);
01194 QRgb *s;
01195 QRgb *d;
01196 for( int yi=0; yi < tmp.height(); ++yi )
01197 {
01198 s = (QRgb*)(tmp.scanLine( yi ));
01199 d = (QRgb*)(scanLine( yi ));
01200 for(int xi=0; xi < tmp.width(); ++xi )
01201 {
01202 (*d) = (*s);
01203 s++;
01204 d++;
01205 }
01206 }
01207 }
01208
01209 void ScImage::Convert2JPG(QString fn, int Quality, bool isCMYK, bool isGray)
01210 {
01211 struct jpeg_compress_struct cinfo;
01212 struct my_error_mgr jerr;
01213 FILE *outfile;
01214 JSAMPROW row_pointer[1];
01215 row_pointer[0] = 0;
01216 cinfo.err = jpeg_std_error (&jerr.pub);
01217 jerr.pub.error_exit = my_error_exit;
01218 outfile = NULL;
01219 if (setjmp (jerr.setjmp_buffer))
01220 {
01221 jpeg_destroy_compress (&cinfo);
01222 if (outfile)
01223 fclose (outfile);
01224 return;
01225 }
01226 jpeg_create_compress (&cinfo);
01227 if ((outfile = fopen (fn.toLocal8Bit(), "wb")) == NULL)
01228 return;
01229 jpeg_stdio_dest (&cinfo, outfile);
01230 cinfo.image_width = width();
01231 cinfo.image_height = height();
01232 if (isCMYK)
01233 {
01234 cinfo.in_color_space = JCS_CMYK;
01235 cinfo.input_components = 4;
01236 }
01237 else
01238 {
01239 if (isGray)
01240 {
01241 cinfo.in_color_space = JCS_GRAYSCALE;
01242 cinfo.input_components = 1;
01243 }
01244 else
01245 {
01246 cinfo.in_color_space = JCS_RGB;
01247 cinfo.input_components = 3;
01248 }
01249 }
01250 jpeg_set_defaults (&cinfo);
01251 int qual[] = { 95, 85, 75, 50, 25 };
01252 jpeg_set_quality (&cinfo, qual[Quality], true);
01253 jpeg_start_compress (&cinfo, true);
01254 row_pointer[0] = new uchar[cinfo.image_width*cinfo.input_components];
01255 int w = cinfo.image_width;
01256 while (cinfo.next_scanline < cinfo.image_height)
01257 {
01258 uchar *row = row_pointer[0];
01259 if (isCMYK)
01260 {
01261 QRgb* rgba = (QRgb*)scanLine(cinfo.next_scanline);
01262 for (int i=0; i<w; ++i)
01263 {
01264 *row++ = 255-qRed(*rgba);
01265 *row++ = 255-qGreen(*rgba);
01266 *row++ = 255-qBlue(*rgba);
01267 *row++ = 255-qAlpha(*rgba);
01268 ++rgba;
01269 }
01270 }
01271 else
01272 {
01273 if (isGray)
01274 {
01275 QRgb* rgba = (QRgb*)scanLine(cinfo.next_scanline);
01276 for (int i=0; i<w; ++i)
01277 {
01278 *row++ = qRed(*rgba);
01279 ++rgba;
01280 }
01281 }
01282 else
01283 {
01284 QRgb* rgb = (QRgb*)scanLine(cinfo.next_scanline);
01285 for (int i=0; i<w; i++)
01286 {
01287 *row++ = qRed(*rgb);
01288 *row++ = qGreen(*rgb);
01289 *row++ = qBlue(*rgb);
01290 ++rgb;
01291 }
01292 }
01293 }
01294 jpeg_write_scanlines (&cinfo, row_pointer, 1);
01295 }
01296 jpeg_finish_compress (&cinfo);
01297 fclose (outfile);
01298 jpeg_destroy_compress (&cinfo);
01299 delete [] row_pointer[0];
01300 }
01301
01302 QByteArray ScImage::ImageToArray()
01303 {
01304 int i = 0;
01305 int h = height();
01306 int w = width();
01307 unsigned char u;
01308 QRgb *s;
01309 QRgb r;
01310 QByteArray imgArray(3 * h * w, ' ');
01311 if (imgArray.isNull())
01312 return imgArray;
01313 for( int yi=0; yi < h; ++yi )
01314 {
01315 s = (QRgb*)(scanLine( yi ));
01316 for( int xi=0; xi < w; ++xi )
01317 {
01318 r = *s++;
01319 u=qRed(r);
01320 imgArray[i++] = u;
01321 u=qGreen(r);
01322 imgArray[i++] = u;
01323 u=qBlue(r);
01324 imgArray[i++] = u;
01325 }
01326 }
01327 return imgArray;
01328 }
01329
01330 QByteArray ScImage::ImageToGray()
01331 {
01332 int i = 0, k;
01333 int h = height();
01334 int w = width();
01335 QRgb *s;
01336 QRgb r;
01337 QByteArray imgArray(h * w, ' ');
01338 if (imgArray.isNull())
01339 return imgArray;
01340 for( int yi=0; yi < h; ++yi )
01341 {
01342 s = (QRgb*)(scanLine( yi ));
01343 for( int xi=0; xi < w; ++xi )
01344 {
01345 r = *s;
01346 k = qMin(qRound(0.3 * qRed(r) + 0.59 * qGreen(r) + 0.11 * qBlue(r)), 255);
01347 *s = qRgba(k, 0, 0, 0);
01348 imgArray[i++] = k;
01349 s++;
01350 }
01351 }
01352 return imgArray;
01353 }
01354
01355 QByteArray ScImage::ImageToCMYK_PDF()
01356 {
01357 int i = 0;
01358 int h = height();
01359 int w = width();
01360 QRgb *s;
01361 QRgb r;
01362 QByteArray imgArray( 4 * h * w, ' ' );
01363 if (imgArray.isNull())
01364 return imgArray;
01365 for( int yi=0; yi < h; ++yi )
01366 {
01367 s = (QRgb*)(scanLine( yi ));
01368 for( int xi=0; xi < w; ++xi )