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