00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <stdio.h>
00020 #include <stdlib.h>
00021 #include <string.h>
00022 #include <unistd.h>
00023
00024 #include <magick/api.h>
00025
00026 #include <qfile.h>
00027 #include <qfileinfo.h>
00028 #include <qstring.h>
00029
00030 #include <kdeversion.h>
00031 #include <kdebug.h>
00032 #include <kapplication.h>
00033 #include <klocale.h>
00034 #include <kurl.h>
00035 #include <kio/netaccess.h>
00036
00037 #include <qcolor.h>
00038
00039 #include "kis_types.h"
00040 #include "kis_global.h"
00041 #include "kis_doc.h"
00042 #include "kis_image.h"
00043 #include "kis_layer.h"
00044 #include "kis_undo_adapter.h"
00045 #include "kis_image_magick_converter.h"
00046 #include "kis_meta_registry.h"
00047 #include "kis_colorspace_factory_registry.h"
00048 #include "kis_iterators_pixel.h"
00049 #include "kis_colorspace.h"
00050 #include "kis_profile.h"
00051 #include "kis_annotation.h"
00052 #include "kis_paint_layer.h"
00053 #include "kis_group_layer.h"
00054 #include "kis_paint_device.h"
00055
00056 #include "../../../config.h"
00057
00058 namespace {
00059
00060 const Q_UINT8 PIXEL_BLUE = 0;
00061 const Q_UINT8 PIXEL_GREEN = 1;
00062 const Q_UINT8 PIXEL_RED = 2;
00063 const Q_UINT8 PIXEL_ALPHA = 3;
00064
00065 static const Q_UINT8 PIXEL_CYAN = 0;
00066 static const Q_UINT8 PIXEL_MAGENTA = 1;
00067 static const Q_UINT8 PIXEL_YELLOW = 2;
00068 static const Q_UINT8 PIXEL_BLACK = 3;
00069 static const Q_UINT8 PIXEL_CMYK_ALPHA = 4;
00070
00071 static const Q_UINT8 PIXEL_GRAY = 0;
00072 static const Q_UINT8 PIXEL_GRAY_ALPHA = 1;
00073
00078 QString getColorSpaceName(ColorspaceType type, unsigned long imageDepth = 8)
00079 {
00080
00081 if (type == GRAYColorspace) {
00082 if (imageDepth == 8)
00083 return "GRAYA";
00084 else if ( imageDepth == 16 )
00085 return "GRAYA16" ;
00086 }
00087 else if (type == CMYKColorspace) {
00088 if (imageDepth == 8)
00089 return "CMYK";
00090 else if ( imageDepth == 16 ) {
00091 return "CMYK16";
00092 }
00093 }
00094 else if (type == LABColorspace) {
00095 kdDebug(41008) << "Lab!\n";
00096 return "LABA";
00097 }
00098 else if (type == RGBColorspace || type == sRGBColorspace || type == TransparentColorspace) {
00099 if (imageDepth == 8)
00100 return "RGBA";
00101 else if (imageDepth == 16)
00102 return "RGBA16";
00103 }
00104 return "";
00105
00106 }
00107
00108 ColorspaceType getColorTypeforColorSpace( KisColorSpace * cs )
00109 {
00110 if ( cs->id() == KisID("GRAYA") || cs->id() == KisID("GRAYA16") ) return GRAYColorspace;
00111 if ( cs->id() == KisID("RGBA") || cs->id() == KisID("RGBA16") ) return RGBColorspace;
00112 if ( cs->id() == KisID("CMYK") || cs->id() == KisID("CMYK16") ) return CMYKColorspace;
00113 if ( cs->id() == KisID("LABA") ) return LABColorspace;
00114
00115 kdDebug(41008) << "Cannot export images in " + cs->id().name() + " yet.\n";
00116 return RGBColorspace;
00117
00118 }
00119
00120 KisProfile * getProfileForProfileInfo(const Image * image)
00121 {
00122 #ifndef HAVE_MAGICK6
00123 return 0;
00124 #else
00125
00126 if (image->profiles == NULL)
00127 return 0;
00128
00129 const char *name;
00130 const StringInfo *profile;
00131
00132 KisProfile * p = 0;
00133
00134 ResetImageProfileIterator(image);
00135 for (name = GetNextImageProfile(image); name != (char *) NULL; )
00136 {
00137 profile = GetImageProfile(image, name);
00138 if (profile == (StringInfo *) NULL)
00139 continue;
00140
00141
00142 if (QString::compare(name, "icc") == 0) {
00143 QByteArray rawdata;
00144 rawdata.resize(profile->length);
00145 memcpy(rawdata.data(), profile->datum, profile->length);
00146
00147 p = new KisProfile(rawdata);
00148 if (p == 0)
00149 return 0;
00150 }
00151 name = GetNextImageProfile(image);
00152 }
00153 return p;
00154 #endif
00155 }
00156
00157 void setAnnotationsForImage(const Image * src, KisImageSP image)
00158 {
00159 #ifndef HAVE_MAGICK6
00160 return;
00161 #else
00162 if (src->profiles == NULL)
00163 return;
00164
00165 const char *name = 0;
00166 const StringInfo *profile;
00167 KisAnnotation* annotation = 0;
00168
00169
00170 ResetImageProfileIterator(src);
00171 while((name = GetNextImageProfile(src))) {
00172 profile = GetImageProfile(src, name);
00173 if (profile == (StringInfo *) NULL)
00174 continue;
00175
00176
00177 if (QString::compare(name, "icc") == 0)
00178 continue;
00179
00180 QByteArray rawdata;
00181 rawdata.resize(profile->length);
00182 memcpy(rawdata.data(), profile->datum, profile->length);
00183
00184 annotation = new KisAnnotation(QString(name), "", rawdata);
00185 Q_CHECK_PTR(annotation);
00186
00187 image -> addAnnotation(annotation);
00188 }
00189
00190
00191
00192
00193
00194
00195 #if MagickLibVersion >= 0x621
00196 const ImageAttribute * attr;
00197 ResetImageAttributeIterator(src);
00198 while ( (attr = GetNextImageAttribute(src)) ) {
00199 #else
00200 ImageAttribute * attr = src -> attributes;
00201 while (attr) {
00202 #endif
00203 QByteArray rawdata;
00204 int len = strlen(attr -> value) + 1;
00205 rawdata.resize(len);
00206 memcpy(rawdata.data(), attr -> value, len);
00207
00208 annotation = new KisAnnotation(
00209 QString("krita_attribute:%1").arg(QString(attr -> key)), "", rawdata);
00210 Q_CHECK_PTR(annotation);
00211
00212 image -> addAnnotation(annotation);
00213 #if MagickLibVersion < 0x620
00214 attr = attr -> next;
00215 #endif
00216 }
00217
00218 #endif
00219 }
00220 }
00221
00222 void exportAnnotationsForImage(Image * dst, vKisAnnotationSP_it& it, vKisAnnotationSP_it& annotationsEnd)
00223 {
00224 #ifndef HAVE_MAGICK6
00225 return;
00226 #else
00227 while(it != annotationsEnd) {
00228 if (!(*it) || (*it) -> type() == QString()) {
00229 kdDebug(41008) << "Warning: empty annotation" << endl;
00230 ++it;
00231 continue;
00232 }
00233
00234 kdDebug(41008) << "Trying to store annotation of type " << (*it) -> type() << " of size " << (*it) -> annotation() . size() << endl;
00235
00236 if ((*it) -> type().startsWith("krita_attribute:")) {
00237 if (!SetImageAttribute(dst,
00238 (*it) -> type().mid(strlen("krita_attribute:")).ascii(),
00239 (*it) -> annotation() . data()) ) {
00240 kdDebug(41008) << "Storing of attribute " << (*it) -> type() << "failed!\n";
00241 }
00242 } else {
00243 if (!ProfileImage(dst, (*it) -> type().ascii(),
00244 (unsigned char*)(*it) -> annotation() . data(),
00245 (*it) -> annotation() . size(), MagickFalse)) {
00246 kdDebug(41008) << "Storing failed!" << endl;
00247 }
00248 }
00249 ++it;
00250 }
00251 #endif
00252 }
00253
00254
00255 void InitGlobalMagick()
00256 {
00257 static bool init = false;
00258
00259 if (!init) {
00260 KApplication *app = KApplication::kApplication();
00261
00262 InitializeMagick(*app -> argv());
00263 atexit(DestroyMagick);
00264 init = true;
00265 }
00266 }
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278 #ifdef HAVE_MAGICK6
00279 MagickBooleanType monitor(const char *text, const ExtendedSignedIntegralType, const ExtendedUnsignedIntegralType, ExceptionInfo *)
00280 {
00281 KApplication *app = KApplication::kApplication();
00282
00283 Q_ASSERT(app);
00284
00285 if (app -> hasPendingEvents())
00286 app -> processEvents();
00287
00288 printf("%s\n", text);
00289 return MagickTrue;
00290 }
00291 #else
00292 unsigned int monitor(const char *text, const ExtendedSignedIntegralType, const ExtendedUnsignedIntegralType, ExceptionInfo *)
00293 {
00294 KApplication *app = KApplication::kApplication();
00295
00296 Q_ASSERT(app);
00297
00298 if (app -> hasPendingEvents())
00299 app -> processEvents();
00300
00301 printf("%s\n", text);
00302 return true;
00303 }
00304 #endif
00305
00306
00307
00308 KisImageMagickConverter::KisImageMagickConverter(KisDoc *doc, KisUndoAdapter *adapter)
00309 {
00310 InitGlobalMagick();
00311 init(doc, adapter);
00312 SetMonitorHandler(monitor);
00313 m_stop = false;
00314 }
00315
00316 KisImageMagickConverter::~KisImageMagickConverter()
00317 {
00318 }
00319
00320 KisImageBuilder_Result KisImageMagickConverter::decode(const KURL& uri, bool isBlob)
00321 {
00322 Image *image;
00323 Image *images;
00324 ExceptionInfo ei;
00325 ImageInfo *ii;
00326
00327 if (m_stop) {
00328 m_img = 0;
00329 return KisImageBuilder_RESULT_INTR;
00330 }
00331
00332 GetExceptionInfo(&ei);
00333 ii = CloneImageInfo(0);
00334
00335 if (isBlob) {
00336
00337
00338 Q_ASSERT(uri.isEmpty());
00339 images = BlobToImage(ii, &m_data[0], m_data.size(), &ei);
00340 } else {
00341
00342 qstrncpy(ii -> filename, QFile::encodeName(uri.path()), MaxTextExtent - 1);
00343
00344 if (ii -> filename[MaxTextExtent - 1]) {
00345 emit notifyProgressError();
00346 return KisImageBuilder_RESULT_PATH;
00347 }
00348
00349 images = ReadImage(ii, &ei);
00350
00351 }
00352
00353 if (ei.severity != UndefinedException)
00354 CatchException(&ei);
00355
00356 if (images == 0) {
00357 DestroyImageInfo(ii);
00358 DestroyExceptionInfo(&ei);
00359 emit notifyProgressError();
00360 return KisImageBuilder_RESULT_FAILURE;
00361 }
00362
00363 emit notifyProgressStage(i18n("Importing..."), 0);
00364
00365 m_img = 0;
00366
00367 while ((image = RemoveFirstImageFromList(&images))) {
00368 ViewInfo *vi = OpenCacheView(image);
00369
00370
00371 unsigned long imageDepth = image->depth;
00372 kdDebug(41008) << "Image depth: " << imageDepth << "\n";
00373
00374 QString csName;
00375 KisColorSpace * cs = 0;
00376 ColorspaceType colorspaceType;
00377
00378
00379 if (GetImageType(image, &ei) == GrayscaleType || GetImageType(image, &ei) == GrayscaleMatteType) {
00380 if (imageDepth == 8)
00381 csName = "GRAYA";
00382 else if ( imageDepth == 16 )
00383 csName = "GRAYA16" ;
00384 colorspaceType = GRAYColorspace;
00385 }
00386 else {
00387 colorspaceType = image->colorspace;
00388 csName = getColorSpaceName(image -> colorspace, imageDepth);
00389 }
00390
00391 kdDebug(41008) << "image has " << csName << " colorspace\n";
00392
00393 KisProfile * profile = getProfileForProfileInfo(image);
00394 if (profile)
00395 {
00396 kdDebug(41008) << "image has embedded profile: " << profile -> productName() << "\n";
00397 cs = KisMetaRegistry::instance()->csRegistry()->getColorSpace(csName, profile);
00398 }
00399 else
00400 cs = KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID(csName,""),"");
00401
00402 if (!cs) {
00403 kdDebug(41008) << "Krita does not support colorspace " << image -> colorspace << "\n";
00404 CloseCacheView(vi);
00405 DestroyImage(image);
00406 DestroyExceptionInfo(&ei);
00407 DestroyImageList(images);
00408 DestroyImageInfo(ii);
00409 emit notifyProgressError();
00410 return KisImageBuilder_RESULT_UNSUPPORTED_COLORSPACE;
00411 }
00412
00413 if( ! m_img) {
00414 m_img = new KisImage(m_doc->undoAdapter(), image -> columns, image -> rows, cs, "built image");
00415 Q_CHECK_PTR(m_img);
00416 m_img->blockSignals(true);
00417
00418
00419 setAnnotationsForImage(image, m_img);
00420 }
00421
00422 if (image -> columns && image -> rows) {
00423
00424
00425 Q_UINT8 opacity = OPACITY_OPAQUE;
00426 const ImageAttribute * attr = GetImageAttribute(image, "[layer-opacity]");
00427 if (attr != 0) {
00428 opacity = Q_UINT8_MAX - Downscale(QString(attr->value).toInt());
00429 }
00430
00431 KisPaintLayerSP layer = 0;
00432
00433 attr = GetImageAttribute(image, "[layer-name]");
00434 if (attr != 0) {
00435 layer = new KisPaintLayer(m_img, attr->value, opacity);
00436 }
00437 else {
00438 layer = new KisPaintLayer(m_img, m_img -> nextLayerName(), opacity);
00439 }
00440
00441 Q_ASSERT(layer);
00442
00443
00444 Q_INT32 x_offset = 0;
00445 Q_INT32 y_offset = 0;
00446
00447 attr = GetImageAttribute(image, "[layer-xpos]");
00448 if (attr != 0) {
00449 x_offset = QString(attr->value).toInt();
00450 }
00451
00452 attr = GetImageAttribute(image, "[layer-ypos]");
00453 if (attr != 0) {
00454 y_offset = QString(attr->value).toInt();
00455 }
00456
00457
00458 for (Q_UINT32 y = 0; y < image->rows; y ++)
00459 {
00460 const PixelPacket *pp = AcquireCacheView(vi, 0, y, image->columns, 1, &ei);
00461
00462 if(!pp)
00463 {
00464 CloseCacheView(vi);
00465 DestroyImageList(images);
00466 DestroyImageInfo(ii);
00467 DestroyExceptionInfo(&ei);
00468 emit notifyProgressError();
00469 return KisImageBuilder_RESULT_FAILURE;
00470 }
00471
00472 IndexPacket * indexes = GetCacheViewIndexes(vi);
00473
00474 KisHLineIteratorPixel hiter = layer->paintDevice()->createHLineIterator(0, y, image->columns, true);
00475
00476 if (colorspaceType== CMYKColorspace) {
00477 if (imageDepth == 8) {
00478 int x = 0;
00479 while (!hiter.isDone())
00480 {
00481 Q_UINT8 *ptr= hiter.rawData();
00482 *(ptr++) = Downscale(pp->red);
00483 *(ptr++) = Downscale(pp->green);
00484 *(ptr++) = Downscale(pp->blue);
00485 *(ptr++) = Downscale(indexes[x]);
00486
00487 #ifdef HAVE_MAGICK6
00488 if (image->matte != MagickFalse) {
00489 #else
00490 if (image->matte == true) {
00491 #endif
00492 *(ptr++) = OPACITY_OPAQUE - Downscale(pp->opacity);
00493 }
00494 else {
00495 *(ptr++) = OPACITY_OPAQUE;
00496 }
00497 ++x;
00498 pp++;
00499 ++hiter;
00500 }
00501 }
00502 }
00503 else if (colorspaceType == LABColorspace) {
00504 while(! hiter.isDone())
00505 {
00506 Q_UINT16 *ptr = reinterpret_cast<Q_UINT16 *>(hiter.rawData());
00507
00508 *(ptr++) = ScaleQuantumToShort(pp->red);
00509 *(ptr++) = ScaleQuantumToShort(pp->green);
00510 *(ptr++) = ScaleQuantumToShort(pp->blue);
00511 *(ptr++) = 65535 - ScaleQuantumToShort(pp->opacity);
00512
00513 pp++;
00514 ++hiter;
00515 }
00516 }
00517 else if (colorspaceType == RGBColorspace ||
00518 colorspaceType == sRGBColorspace ||
00519 colorspaceType == TransparentColorspace)
00520 {
00521 if (imageDepth == 8) {
00522 while(! hiter.isDone())
00523 {
00524 Q_UINT8 *ptr= hiter.rawData();
00525
00526 *(ptr++) = Downscale(pp->blue);
00527 *(ptr++) = Downscale(pp->green);
00528 *(ptr++) = Downscale(pp->red);
00529 *(ptr++) = OPACITY_OPAQUE - Downscale(pp->opacity);
00530
00531 pp++;
00532 ++hiter;
00533 }
00534 }
00535 else if (imageDepth == 16) {
00536 while(! hiter.isDone())
00537 {
00538 Q_UINT16 *ptr = reinterpret_cast<Q_UINT16 *>(hiter.rawData());
00539
00540 *(ptr++) = ScaleQuantumToShort(pp->blue);
00541 *(ptr++) = ScaleQuantumToShort(pp->green);
00542 *(ptr++) = ScaleQuantumToShort(pp->red);
00543 *(ptr++) = 65535 - ScaleQuantumToShort(pp->opacity);
00544
00545 pp++;
00546 ++hiter;
00547 }
00548 }
00549 }
00550 else if ( colorspaceType == GRAYColorspace) {
00551 if (imageDepth == 8) {
00552 while(! hiter.isDone())
00553 {
00554 Q_UINT8 *ptr= hiter.rawData();
00555
00556 *(ptr++) = Downscale(pp->blue);
00557 *(ptr++) = OPACITY_OPAQUE - Downscale(pp->opacity);
00558
00559 pp++;
00560 ++hiter;
00561 }
00562 }
00563 else if (imageDepth == 16) {
00564 while(! hiter.isDone())
00565 {
00566 Q_UINT16 *ptr = reinterpret_cast<Q_UINT16 *>(hiter.rawData());
00567
00568 *(ptr++) = ScaleQuantumToShort(pp->blue);
00569 *(ptr++) = 65535 - ScaleQuantumToShort(pp->opacity);
00570
00571 pp++;
00572 ++hiter;
00573 }
00574 }
00575 }
00576
00577 emit notifyProgress(y * 100 / image->rows);
00578
00579 if (m_stop) {
00580 CloseCacheView(vi);
00581 DestroyImage(image);
00582 DestroyImageList(images);
00583 DestroyImageInfo(ii);
00584 DestroyExceptionInfo(&ei);
00585 m_img = 0;
00586 return KisImageBuilder_RESULT_INTR;
00587 }
00588 }
00589 m_img->addLayer(layer.data(), m_img->rootLayer());
00590 layer->paintDevice()->move(x_offset, y_offset);
00591 }
00592
00593 emit notifyProgressDone();
00594 CloseCacheView(vi);
00595 DestroyImage(image);
00596 }
00597
00598 emit notifyProgressDone();
00599 DestroyImageList(images);
00600 DestroyImageInfo(ii);
00601 DestroyExceptionInfo(&ei);
00602 return KisImageBuilder_RESULT_OK;
00603 }
00604
00605 KisImageBuilder_Result KisImageMagickConverter::buildImage(const KURL& uri)
00606 {
00607 if (uri.isEmpty())
00608 return KisImageBuilder_RESULT_NO_URI;
00609
00610 if (!KIO::NetAccess::exists(uri, false, qApp -> mainWidget())) {
00611 return KisImageBuilder_RESULT_NOT_EXIST;
00612 }
00613
00614 KisImageBuilder_Result result = KisImageBuilder_RESULT_FAILURE;
00615 QString tmpFile;
00616
00617 if (KIO::NetAccess::download(uri, tmpFile, qApp -> mainWidget())) {
00618 KURL uriTF;
00619 uriTF.setPath( tmpFile );
00620 result = decode(uriTF, false);
00621 KIO::NetAccess::removeTempFile(tmpFile);
00622 }
00623
00624 return result;
00625 }
00626
00627
00628 KisImageSP KisImageMagickConverter::image()
00629 {
00630 return m_img;
00631 }
00632
00633 void KisImageMagickConverter::init(KisDoc *doc, KisUndoAdapter *adapter)
00634 {
00635 m_doc = doc;
00636 m_adapter = adapter;
00637 m_job = 0;
00638 }
00639
00640 KisImageBuilder_Result KisImageMagickConverter::buildFile(const KURL& uri, KisPaintLayerSP layer, vKisAnnotationSP_it annotationsStart, vKisAnnotationSP_it annotationsEnd)
00641 {
00642 Image *image;
00643 ExceptionInfo ei;
00644 ImageInfo *ii;
00645
00646 if (!layer)
00647 return KisImageBuilder_RESULT_INVALID_ARG;
00648
00649 KisImageSP img = layer->image();
00650 if (!img)
00651 return KisImageBuilder_RESULT_EMPTY;
00652
00653 if (uri.isEmpty())
00654 return KisImageBuilder_RESULT_NO_URI;
00655
00656 if (!uri.isLocalFile())
00657 return KisImageBuilder_RESULT_NOT_LOCAL;
00658
00659
00660 Q_UINT32 layerBytesPerChannel = layer->paintDevice()->pixelSize() / layer->paintDevice()->nChannels();
00661
00662 GetExceptionInfo(&ei);
00663
00664 ii = CloneImageInfo(0);
00665
00666 qstrncpy(ii -> filename, QFile::encodeName(uri.path()), MaxTextExtent - 1);
00667
00668 if (ii -> filename[MaxTextExtent - 1]) {
00669 emit notifyProgressError();
00670 return KisImageBuilder_RESULT_PATH;
00671 }
00672
00673 if (!img -> width() || !img -> height())
00674 return KisImageBuilder_RESULT_EMPTY;
00675
00676 if (layerBytesPerChannel < 2) {
00677 ii->depth = 8;
00678 }
00679 else {
00680 ii->depth = 16;
00681 }
00682
00683 ii->colorspace = getColorTypeforColorSpace(layer->paintDevice()->colorSpace());
00684
00685 image = AllocateImage(ii);
00686 SetImageColorspace(image, ii->colorspace);
00687 image -> columns = img -> width();
00688 image -> rows = img -> height();
00689
00690 kdDebug(41008) << "Saving with colorspace " << image->colorspace << ", (" << layer->paintDevice()->colorSpace()->id().name() << ")\n";
00691 kdDebug(41008) << "IM Image thinks it has depth: " << image->depth << "\n";
00692
00693 #ifdef HAVE_MAGICK6
00694
00695 image -> matte = MagickTrue;
00696
00697
00698 #else
00699
00700 image -> matte = true;
00701 #endif
00702
00703 Q_INT32 y, height, width;
00704
00705 height = img -> height();
00706 width = img -> width();
00707
00708 bool alpha = true;
00709 QString ext = QFileInfo(QFile::encodeName(uri.path())).extension(false).upper();
00710 if (ext == "BMP") {
00711 alpha = false;
00712 qstrncpy(ii->magick, "BMP2", MaxTextExtent - 1);
00713 }
00714 else if (ext == "RGB") {
00715 qstrncpy(ii->magick, "SGI", MaxTextExtent - 1);
00716 }
00717
00718 for (y = 0; y < height; y++) {
00719
00720
00721 PixelPacket * pp = SetImagePixels(image, 0, y, width, 1);
00722
00723 if (!pp) {
00724 DestroyExceptionInfo(&ei);
00725 DestroyImage(image);
00726 emit notifyProgressError();
00727 return KisImageBuilder_RESULT_FAILURE;
00728
00729 }
00730
00731 KisHLineIterator it = layer->paintDevice()->createHLineIterator(0, y, width, false);
00732 if (alpha)
00733 SetImageType(image, TrueColorMatteType);
00734 else
00735 SetImageType(image, TrueColorType);
00736
00737 if (image->colorspace== CMYKColorspace) {
00738
00739 IndexPacket * indexes = GetIndexes(image);
00740 int x = 0;
00741 if (layerBytesPerChannel == 2) {
00742 while (!it.isDone()) {
00743
00744 const Q_UINT16 *d = reinterpret_cast<const Q_UINT16 *>(it.rawData());
00745 pp -> red = ScaleShortToQuantum(d[PIXEL_CYAN]);
00746 pp -> green = ScaleShortToQuantum(d[PIXEL_MAGENTA]);
00747 pp -> blue = ScaleShortToQuantum(d[PIXEL_YELLOW]);
00748 if (alpha)
00749 pp -> opacity = ScaleShortToQuantum(65535 - d[PIXEL_CMYK_ALPHA]);
00750 indexes[x] = ScaleShortToQuantum(d[PIXEL_BLACK]);
00751 x++;
00752 pp++;
00753 ++it;
00754 }
00755 }
00756 else {
00757 while (!it.isDone()) {
00758
00759 Q_UINT8 * d = it.rawData();
00760 pp -> red = Upscale(d[PIXEL_CYAN]);
00761 pp -> green = Upscale(d[PIXEL_MAGENTA]);
00762 pp -> blue = Upscale(d[PIXEL_YELLOW]);
00763 if (alpha)
00764 pp -> opacity = Upscale(OPACITY_OPAQUE - d[PIXEL_CMYK_ALPHA]);
00765
00766 indexes[x]= Upscale(d[PIXEL_BLACK]);
00767
00768 x++;
00769 pp++;
00770 ++it;
00771 }
00772 }
00773 }
00774 else if (image->colorspace== RGBColorspace ||
00775 image->colorspace == sRGBColorspace ||
00776 image->colorspace == TransparentColorspace)
00777 {
00778 if (layerBytesPerChannel == 2) {
00779 while (!it.isDone()) {
00780
00781 const Q_UINT16 *d = reinterpret_cast<const Q_UINT16 *>(it.rawData());
00782 pp -> red = ScaleShortToQuantum(d[PIXEL_RED]);
00783 pp -> green = ScaleShortToQuantum(d[PIXEL_GREEN]);
00784 pp -> blue = ScaleShortToQuantum(d[PIXEL_BLUE]);
00785 if (alpha)
00786 pp -> opacity = ScaleShortToQuantum(65535 - d[PIXEL_ALPHA]);
00787
00788 pp++;
00789 ++it;
00790 }
00791 }
00792 else {
00793 while (!it.isDone()) {
00794
00795 Q_UINT8 * d = it.rawData();
00796 pp -> red = Upscale(d[PIXEL_RED]);
00797 pp -> green = Upscale(d[PIXEL_GREEN]);
00798 pp -> blue = Upscale(d[PIXEL_BLUE]);
00799 if (alpha)
00800 pp -> opacity = Upscale(OPACITY_OPAQUE - d[PIXEL_ALPHA]);
00801
00802 pp++;
00803 ++it;
00804 }
00805 }
00806 }
00807 else if (image->colorspace == GRAYColorspace)
00808 {
00809 SetImageType(image, GrayscaleMatteType);
00810 if (layerBytesPerChannel == 2) {
00811 while (!it.isDone()) {
00812
00813 const Q_UINT16 *d = reinterpret_cast<const Q_UINT16 *>(it.rawData());
00814 pp -> red = ScaleShortToQuantum(d[PIXEL_GRAY]);
00815 pp -> green = ScaleShortToQuantum(d[PIXEL_GRAY]);
00816 pp -> blue = ScaleShortToQuantum(d[PIXEL_GRAY]);
00817 if (alpha)
00818 pp -> opacity = ScaleShortToQuantum(65535 - d[PIXEL_GRAY_ALPHA]);
00819
00820 pp++;
00821 ++it;
00822 }
00823 }
00824 else {
00825 while (!it.isDone()) {
00826 Q_UINT8 * d = it.rawData();
00827 pp -> red = Upscale(d[PIXEL_GRAY]);
00828 pp -> green = Upscale(d[PIXEL_GRAY]);
00829 pp -> blue = Upscale(d[PIXEL_GRAY]);
00830 if (alpha)
00831 pp -> opacity = Upscale(OPACITY_OPAQUE - d[PIXEL_GRAY_ALPHA]);
00832
00833 pp++;
00834 ++it;
00835 }
00836 }
00837 }
00838 else {
00839 kdDebug(41008) << "Unsupported image format\n";
00840 return KisImageBuilder_RESULT_INVALID_ARG;
00841 }
00842
00843 emit notifyProgressStage(i18n("Saving..."), y * 100 / height);
00844
00845 #ifdef HAVE_MAGICK6
00846 if (SyncImagePixels(image) == MagickFalse)
00847 kdDebug(41008) << "Syncing pixels failed\n";
00848 #else
00849 if (!SyncImagePixels(image))
00850 kdDebug(41008) << "Syncing pixels failed\n";
00851 #endif
00852 }
00853
00854
00855 exportAnnotationsForImage(image, annotationsStart, annotationsEnd);
00856
00857
00858
00859
00860 WriteImage(ii, image);
00861 DestroyExceptionInfo(&ei);
00862 DestroyImage(image);
00863 emit notifyProgressDone();
00864 return KisImageBuilder_RESULT_OK;
00865 }
00866
00867 void KisImageMagickConverter::ioData(KIO::Job *job, const QByteArray& data)
00868 {
00869 if (data.isNull() || data.isEmpty()) {
00870 emit notifyProgressStage(i18n("Loading..."), 0);
00871 return;
00872 }
00873
00874 if (m_data.empty()) {
00875 Image *image;
00876 ImageInfo *ii;
00877 ExceptionInfo ei;
00878
00879 ii = CloneImageInfo(0);
00880 GetExceptionInfo(&ei);
00881 image = PingBlob(ii, data.data(), data.size(), &ei);
00882
00883 if (image == 0 || ei.severity == BlobError) {
00884 DestroyExceptionInfo(&ei);
00885 DestroyImageInfo(ii);
00886 job -> kill();
00887 emit notifyProgressError();
00888 return;
00889 }
00890
00891 DestroyImage(image);
00892 DestroyExceptionInfo(&ei);
00893 DestroyImageInfo(ii);
00894 emit notifyProgressStage(i18n("Loading..."), 0);
00895 }
00896
00897 Q_ASSERT(data.size() + m_data.size() <= m_size);
00898 memcpy(&m_data[m_data.size()], data.data(), data.count());
00899 m_data.resize(m_data.size() + data.count());
00900 emit notifyProgressStage(i18n("Loading..."), m_data.size() * 100 / m_size);
00901
00902 if (m_stop)
00903 job -> kill();
00904 }
00905
00906 void KisImageMagickConverter::ioResult(KIO::Job *job)
00907 {
00908 m_job = 0;
00909
00910 if (job -> error())
00911 emit notifyProgressError();
00912
00913 decode(KURL(), true);
00914 }
00915
00916 void KisImageMagickConverter::ioTotalSize(KIO::Job * , KIO::filesize_t size)
00917 {
00918 m_size = size;
00919 m_data.reserve(size);
00920 emit notifyProgressStage(i18n("Loading..."), 0);
00921 }
00922
00923 void KisImageMagickConverter::cancel()
00924 {
00925 m_stop = true;
00926 }
00927
00932 QString KisImageMagickConverter::readFilters()
00933 {
00934 QString s;
00935 QString all;
00936 QString name;
00937 QString description;
00938 unsigned long matches;
00939
00940 #ifdef HAVE_MAGICK6
00941 #ifdef HAVE_OLD_GETMAGICKINFOLIST
00942 const MagickInfo **mi;
00943 mi = GetMagickInfoList("*", &matches);
00944 #else // HAVE_OLD_GETMAGICKINFOLIST
00945 ExceptionInfo ei;
00946 GetExceptionInfo(&ei);
00947 const MagickInfo **mi;
00948 mi = GetMagickInfoList("*", &matches, &ei);
00949 DestroyExceptionInfo(&ei);
00950 #endif // HAVE_OLD_GETMAGICKINFOLIST
00951 #else // HAVE_MAGICK6
00952 const MagickInfo *mi;
00953 ExceptionInfo ei;
00954 GetExceptionInfo(&ei);
00955 mi = GetMagickInfo("*", &ei);
00956 DestroyExceptionInfo(&ei);
00957 #endif // HAVE_MAGICK6
00958
00959 if (!mi)
00960 return s;
00961
00962 #ifdef HAVE_MAGICK6
00963 for (unsigned long i = 0; i < matches; i++) {
00964 const MagickInfo *info = mi[i];
00965 if (info -> stealth)
00966 continue;
00967
00968 if (info -> decoder) {
00969 name = info -> name;
00970 description = info -> description;
00971 kdDebug(41008) << "Found import filter for: " << name << "\n";
00972
00973 if (!description.isEmpty() && !description.contains('/')) {
00974 all += "*." + name.lower() + " *." + name + " ";
00975 s += "*." + name.lower() + " *." + name + "|";
00976 s += i18n(description.utf8());
00977 s += "\n";
00978 }
00979 }
00980 }
00981 #else
00982 for (; mi; mi = reinterpret_cast<const MagickInfo*>(mi -> next)) {
00983 if (mi -> stealth)
00984 continue;
00985 if (mi -> decoder) {
00986 name = mi -> name;
00987 description = mi -> description;
00988 kdDebug(41008) << "Found import filter for: " << name << "\n";
00989
00990 if (!description.isEmpty() && !description.contains('/')) {
00991 all += "*." + name.lower() + " *." + name + " ";
00992 s += "*." + name.lower() + " *." + name + "|";
00993 s += i18n(description.utf8());
00994 s += "\n";
00995 }
00996 }
00997 }
00998 #endif
00999
01000 all += "|" + i18n("All Images");
01001 all += "\n";
01002
01003 return all + s;
01004 }
01005
01006 QString KisImageMagickConverter::writeFilters()
01007 {
01008 QString s;
01009 QString all;
01010 QString name;
01011 QString description;
01012 unsigned long matches;
01013
01014 #ifdef HAVE_MAGICK6
01015 #ifdef HAVE_OLD_GETMAGICKINFOLIST
01016 const MagickInfo **mi;
01017 mi = GetMagickInfoList("*", &matches);
01018 #else // HAVE_OLD_GETMAGICKINFOLIST
01019 ExceptionInfo ei;
01020 GetExceptionInfo(&ei);
01021 const MagickInfo **mi;
01022 mi = GetMagickInfoList("*", &matches, &ei);
01023 DestroyExceptionInfo(&ei);
01024 #endif // HAVE_OLD_GETMAGICKINFOLIST
01025 #else // HAVE_MAGICK6
01026 const MagickInfo *mi;
01027 ExceptionInfo ei;
01028 GetExceptionInfo(&ei);
01029 mi = GetMagickInfo("*", &ei);
01030 DestroyExceptionInfo(&ei);
01031 #endif // HAVE_MAGICK6
01032
01033 if (!mi) {
01034 kdDebug(41008) << "Eek, no magick info!\n";
01035 return s;
01036 }
01037
01038 #ifdef HAVE_MAGICK6
01039 for (unsigned long i = 0; i < matches; i++) {
01040 const MagickInfo *info = mi[i];
01041 kdDebug(41008) << "Found export filter for: " << info -> name << "\n";
01042 if (info -> stealth)
01043 continue;
01044
01045 if (info -> encoder) {
01046 name = info -> name;
01047
01048 description = info -> description;
01049
01050 if (!description.isEmpty() && !description.contains('/')) {
01051 all += "*." + name.lower() + " *." + name + " ";
01052 s += "*." + name.lower() + " *." + name + "|";
01053 s += i18n(description.utf8());
01054 s += "\n";
01055 }
01056 }
01057 }
01058 #else
01059 for (; mi; mi = reinterpret_cast<const MagickInfo*>(mi -> next)) {
01060 kdDebug(41008) << "Found export filter for: " << mi -> name << "\n";
01061 if (mi -> stealth)
01062 continue;
01063
01064 if (mi -> encoder) {
01065 name = mi -> name;
01066
01067 description = mi -> description;
01068
01069 if (!description.isEmpty() && !description.contains('/')) {
01070 all += "*." + name.lower() + " *." + name + " ";
01071 s += "*." + name.lower() + " *." + name + "|";
01072 s += i18n(description.utf8());
01073 s += "\n";
01074 }
01075 }
01076 }
01077 #endif
01078
01079
01080 all += "|" + i18n("All Images");
01081 all += "\n";
01082
01083 return all + s;
01084 }
01085
01086 #include "kis_image_magick_converter.moc"
01087