diff options
Diffstat (limited to 'filters/chalk/tiff/kis_tiff_converter.cpp')
-rw-r--r-- | filters/chalk/tiff/kis_tiff_converter.cpp | 677 |
1 files changed, 677 insertions, 0 deletions
diff --git a/filters/chalk/tiff/kis_tiff_converter.cpp b/filters/chalk/tiff/kis_tiff_converter.cpp new file mode 100644 index 000000000..ea39dec28 --- /dev/null +++ b/filters/chalk/tiff/kis_tiff_converter.cpp @@ -0,0 +1,677 @@ +/* + * Copyright (c) 2005-2006 Cyrille Berger <cberger@cberger.net> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "kis_tiff_converter.h" + +#include <stdio.h> + +#include <config.h> +#include LCMS_HEADER + +#include <tqfile.h> + +#include <tdeapplication.h> +#include <KoDocumentInfo.h> + +#include <tdeio/netaccess.h> + +#include <kis_abstract_colorspace.h> +#include <kis_colorspace_factory_registry.h> +#include <kis_doc.h> +#include <kis_image.h> +#include <kis_iterators_pixel.h> +#include <kis_layer.h> +#include <kis_meta_registry.h> +#include <kis_profile.h> +#include <kis_group_layer.h> +#include <kis_paint_layer.h> + +#include "kis_tiff_reader.h" +#include "kis_tiff_ycbcr_reader.h" +#include "kis_tiff_stream.h" +#include "kis_tiff_writer_visitor.h" + +namespace { + + TQString getColorSpaceForColorType(uint16 color_type, uint16 color_nb_bits, TIFF *image, uint16 &nbchannels, uint16 &extrasamplescount, uint8 &destDepth, uint16 sampletype) { + if(color_type == PHOTOMETRIC_MINISWHITE || color_type == PHOTOMETRIC_MINISBLACK) + { + if(nbchannels == 0) nbchannels = 1; + extrasamplescount = nbchannels - 1; // FIX the extrasamples count in case of + if(color_nb_bits <= 8) + { + destDepth = 8; + return "GRAYA"; + } else { + destDepth = 16; + return "GRAYA16"; + } + } else if(color_type == PHOTOMETRIC_RGB /*|| color_type == */ ) { + if(nbchannels == 0) nbchannels = 3; + extrasamplescount = nbchannels - 3; // FIX the extrasamples count in case of + if(sampletype == SAMPLEFORMAT_IEEEFP) + { + if(color_nb_bits == 16) + { + destDepth = 16; + return "RGBAF16HALF"; + } else if( color_nb_bits == 32) { + destDepth = 32; + return "RGBAF32"; + } + return ""; + } else { + if(color_nb_bits <= 8) + { + destDepth = 8; + return "RGBA"; + } else { + destDepth = 16; + return "RGBA16"; + } + } + } else if(color_type == PHOTOMETRIC_YCBCR ) { + if(nbchannels == 0) nbchannels = 3; + extrasamplescount = nbchannels - 3; // FIX the extrasamples count in case of + if(color_nb_bits <= 8) + { + destDepth = 8; + return "YCbCrAU8"; + } else { + destDepth = 16; + return "YCbCrAU16"; + } + } else if(color_type == PHOTOMETRIC_SEPARATED ) { + if(nbchannels == 0) nbchannels = 4; + // SEPARATED is in general CMYK but not allways, so we check + uint16 inkset; + if((TIFFGetField(image, TIFFTAG_INKSET, &inkset) == 0)){ + kdDebug(41008) << "Image does not define the inkset." << endl; + inkset = 2; + } + if(inkset != INKSET_CMYK) + { + kdDebug(41008) << "Unsupported inkset (right now, only CMYK is supported)" << endl; + char** ink_names; + uint16 numberofinks; + if( TIFFGetField(image, TIFFTAG_INKNAMES, &ink_names) && TIFFGetField(image, TIFFTAG_NUMBEROFINKS, &numberofinks) ) + { + kdDebug(41008) << "Inks are : " << endl; + for(uint i = 0; i < numberofinks; i++) + { + kdDebug(41008) << ink_names[i] << endl; + } + } else { + kdDebug(41008) << "inknames aren't defined !" << endl; + // To be able to read stupid adobe files, if there are no information about inks and four channels, then it's a CMYK file : + if( nbchannels - extrasamplescount != 4) + { + return ""; + } + } + } + if(color_nb_bits <= 8) + { + destDepth = 8; + return "CMYK"; + } else { + destDepth = 16; + return "CMYKA16"; + } + } else if(color_type == PHOTOMETRIC_CIELAB +#ifdef PHOTOMETRIC_ICCLAB + || color_type == PHOTOMETRIC_ICCLAB +#endif + ) { + destDepth = 16; + if(nbchannels == 0) nbchannels = 3; + extrasamplescount = nbchannels - 3; // FIX the extrasamples count in case of + return "LABA"; // TODO add support for a 8bit LAB colorspace when it is written + } else if(color_type == PHOTOMETRIC_PALETTE) { + destDepth = 16; + if(nbchannels == 0) nbchannels = 2; + extrasamplescount = nbchannels - 2; // FIX the extrasamples count in case of + // <-- we will convert the index image to RGBA16 as the palette is allways on 16bits colors + return "RGBA16"; + } + return ""; + } +} + +KisTIFFConverter::KisTIFFConverter(KisDoc *doc, KisUndoAdapter *adapter) +{ + m_doc = doc; + m_adapter = adapter; + m_job = 0; + m_stop = false; +} + +KisTIFFConverter::~KisTIFFConverter() +{ +} + +KisImageBuilder_Result KisTIFFConverter::decode(const KURL& uri) +{ + kdDebug(41008) << "Start decoding TIFF File" << endl; + // Opent the TIFF file + TIFF *image = 0; + if((image = TIFFOpen(TQFile::encodeName(uri.path()), "r")) == NULL){ + kdDebug(41008) << "Could not open the file, either it doesn't exist, either it is not a TIFF : " << uri.path() << endl; + + return (KisImageBuilder_RESULT_BAD_FETCH); + } + do { + kdDebug(41008) << "Read new sub-image" << endl; + KisImageBuilder_Result result = readTIFFDirectory(image); + if(result != KisImageBuilder_RESULT_OK){ + return result; + } + } while (TIFFReadDirectory(image)); + // Freeing memory + TIFFClose(image); + return KisImageBuilder_RESULT_OK; +} + +KisImageBuilder_Result KisTIFFConverter::readTIFFDirectory( TIFF* image) +{ + // Read information about the tiff + uint32 width, height; + if(TIFFGetField(image, TIFFTAG_IMAGEWIDTH, &width) == 0){ + kdDebug(41008) << "Image does not define its width" << endl; + TIFFClose(image); + return KisImageBuilder_RESULT_INVALID_ARG; + } + if(TIFFGetField(image, TIFFTAG_IMAGELENGTH, &height) == 0){ + kdDebug(41008) << "Image does not define its height" << endl; + TIFFClose(image); + return KisImageBuilder_RESULT_INVALID_ARG; + } + uint16 depth; + if((TIFFGetField(image, TIFFTAG_BITSPERSAMPLE, &depth) == 0)){ + kdDebug(41008) << "Image does not define its depth" << endl; + depth = 1; + } + uint16 sampletype; + if((TIFFGetField(image, TIFFTAG_SAMPLEFORMAT, &sampletype) == 0)){ + kdDebug(41008) << "Image does not define its sample type" << endl; + sampletype = SAMPLEFORMAT_UINT; + } + // Determine the number of channels (usefull to know if a file has an alpha or not + uint16 nbchannels; + if(TIFFGetField(image, TIFFTAG_SAMPLESPERPIXEL, &nbchannels) == 0){ + kdDebug(41008) << "Image has an undefined number of samples per pixel" << endl; + nbchannels = 0; + } + // Get the number of extrasamples and information about them + uint16 *sampleinfo, extrasamplescount; + if(TIFFGetField(image, TIFFTAG_EXTRASAMPLES, &extrasamplescount, &sampleinfo) == 0) + { + extrasamplescount = 0; + } + // Determine the colorspace + uint16 color_type; + if(TIFFGetField(image, TIFFTAG_PHOTOMETRIC, &color_type) == 0){ + kdDebug(41008) << "Image has an undefined photometric interpretation" << endl; + color_type = PHOTOMETRIC_MINISWHITE; + } + uint8 dstDepth; + TQString csName = getColorSpaceForColorType(color_type, depth, image, nbchannels, extrasamplescount, dstDepth,sampletype); + if(csName.isEmpty()) { + kdDebug(41008) << "Image has an unsupported colorspace : " << color_type << " for this depth : "<< depth << endl; + TIFFClose(image); + return KisImageBuilder_RESULT_UNSUPPORTED_COLORSPACE; + } + kdDebug(41008) << "Colorspace is : " << csName << " with a depth of " << depth << " and with a nb of channels of " << nbchannels << endl; + + // Read image profile + kdDebug() << "Reading profile" << endl; + KisProfile* profile = 0; + DWORD EmbedLen; + LPBYTE EmbedBuffer; + + if (TIFFGetField(image, TIFFTAG_ICCPROFILE, &EmbedLen, &EmbedBuffer)) { + kdDebug(41008) << "Profile found" << endl; + TQByteArray rawdata; + rawdata.resize(EmbedLen); + memcpy(rawdata.data(), EmbedBuffer, EmbedLen); + profile = new KisProfile(rawdata); + } else { + kdDebug(41008) << "No Profile found" << endl; + } + + // Retrieve a pointer to the colorspace + KisColorSpace* cs = 0; + if (profile && profile->isSuitableForOutput()) + { + kdDebug(41008) << "image has embedded profile: " << profile -> productName() << "\n"; + cs = KisMetaRegistry::instance()->csRegistry()->getColorSpace(csName, profile); + } + else + cs = KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID(csName,""),""); + + if(cs == 0) { + kdDebug(41008) << "Colorspace " << csName << " is not available, please check your installation." << endl; + TIFFClose(image); + return KisImageBuilder_RESULT_UNSUPPORTED_COLORSPACE; + } + + // Create the cmsTransform if needed + cmsHTRANSFORM transform = 0; + if(profile && !profile->isSuitableForOutput()) + { + kdDebug(41008) << "The profile can't be used in chalk, need conversion" << endl; + transform = cmsCreateTransform(profile->profile(), cs->colorSpaceType(), + cs->getProfile()->profile() , cs->colorSpaceType(), + INTENT_PERCEPTUAL, 0); + } + + + // Check if there is an alpha channel + int8 alphapos = -1; // <- no alpha + // Check which extra is alpha if any + kdDebug(41008) << "There are " << nbchannels << " channels and " << extrasamplescount << " extra channels" << endl; + if(sampleinfo) // index images don't have any sampleinfo, and therefor sampleinfo == 0 + { + for(int i = 0; i < extrasamplescount; i ++) + { + kdDebug(41008) << i << " " << extrasamplescount << " " << (cs->nColorChannels()) << nbchannels << " " << sampleinfo[i] << endl; + if(sampleinfo[i] == EXTRASAMPLE_ASSOCALPHA) + { + // XXX: dangelo: the color values are already multiplied with + // the alpha value. This needs to be reversed later (postprocessor?) + alphapos = i; + } + + if (sampleinfo[i] == EXTRASAMPLE_UNASSALPHA) + { + // color values are not premultiplied with alpha, and can be used as they are. + alphapos = i; + } + } + } + + // Read META Information + KoDocumentInfo * info = m_doc->documentInfo(); + KoDocumentInfoAbout * aboutPage = static_cast<KoDocumentInfoAbout *>(info->page( "about" )); + KoDocumentInfoAuthor * authorPage = static_cast<KoDocumentInfoAuthor *>(info->page( "author")); + char* text; + if (TIFFGetField(image, TIFFTAG_ARTIST, &text)) { + authorPage->setFullName(text); + } + if (TIFFGetField(image, TIFFTAG_DOCUMENTNAME, &text)) { + aboutPage->setTitle(text); + } + if (TIFFGetField(image,TIFFTAG_IMAGEDESCRIPTION,&text) ) { + aboutPage->setAbstract( text ); + } + + + // Get the planar configuration + uint16 planarconfig; + if(TIFFGetField(image, TIFFTAG_PLANARCONFIG, &planarconfig) == 0) + { + kdDebug(41008) << "Plannar configuration is not define" << endl; + TIFFClose(image); + return KisImageBuilder_RESULT_INVALID_ARG; + } + // Creating the KisImageSP + if( ! m_img ) { + m_img = new KisImage(m_doc->undoAdapter(), width, height, cs, "built image"); + TQ_CHECK_PTR(m_img); + m_img->blockSignals(true); // Don't send out signals while we're building the image + if(profile) + { + m_img -> addAnnotation( profile->annotation() ); + } + } else { + if( m_img->width() < (TQ_INT32)width || m_img->height() < (TQ_INT32)height) + { + TQ_UINT32 newwidth = (m_img->width() < (TQ_INT32)width) ? width : m_img->width(); + TQ_UINT32 newheight = (m_img->height() < (TQ_INT32)height) ? height : m_img->height(); + m_img->resize(newwidth, newheight, false); + } + } + KisPaintLayer* layer = new KisPaintLayer(m_img, m_img -> nextLayerName(), TQ_UINT8_MAX); + tdata_t buf = 0; + tdata_t* ps_buf = 0; // used only for planar configuration seperated + TIFFStreamBase* tiffstream; + + KisTIFFReaderBase* tiffReader = 0; + + TQ_UINT8 poses[5]; + KisTIFFPostProcessor* postprocessor = 0; + + // Configure poses + uint8 nbcolorsamples = nbchannels - extrasamplescount; + switch(color_type) + { + case PHOTOMETRIC_MINISWHITE: + { + poses[0] = 0; poses[1] = 1; + postprocessor = new KisTIFFPostProcessorInvert(nbcolorsamples); + } + break; + case PHOTOMETRIC_MINISBLACK: + { + poses[0] = 0; poses[1] = 1; + postprocessor = new KisTIFFPostProcessor(nbcolorsamples); + } + break; + case PHOTOMETRIC_CIELAB: + { + poses[0] = 0; poses[1] = 1; poses[2] = 2; poses[3] = 3; + postprocessor = new KisTIFFPostProcessorICCLABtoCIELAB(nbcolorsamples); + } + break; +#ifdef PHOTOMETRIC_ICCLAB + case PHOTOMETRIC_ICCLAB: + { + poses[0] = 0; poses[1] = 1; poses[2] = 2; poses[3] = 3; + postprocessor = new KisTIFFPostProcessor(nbcolorsamples); + } + break; +#endif + case PHOTOMETRIC_RGB: + { + poses[0] = 2; poses[1] = 1; poses[2] = 0; poses[3] = 3; + postprocessor = new KisTIFFPostProcessor(nbcolorsamples); + } + break; + case PHOTOMETRIC_SEPARATED: + { + poses[0] = 0; poses[1] = 1; poses[2] = 2; poses[3] = 3; poses[4] = 4; + postprocessor = new KisTIFFPostProcessor(nbcolorsamples); + } + break; + default: + break; + } + + + // Initisalize tiffReader + uint16 * lineSizeCoeffs = new uint16[nbchannels]; + uint16 vsubsampling = 1; + uint16 hsubsampling = 1; + for(uint i = 0; i < nbchannels; i++) + { + lineSizeCoeffs[i] = 1; + } + if( color_type == PHOTOMETRIC_PALETTE) + { + uint16 *red; // No need to free them they are free by libtiff + uint16 *green; + uint16 *blue; + if ((TIFFGetField(image, TIFFTAG_COLORMAP, &red, &green, &blue)) == 0) + { + kdDebug(41008) << "Indexed image does not define a palette" << endl; + TIFFClose(image); + return KisImageBuilder_RESULT_INVALID_ARG; + } + + tiffReader = new KisTIFFReaderFromPalette( layer->paintDevice(), red, green, blue, poses, alphapos, depth, nbcolorsamples, extrasamplescount, transform, postprocessor); + } else if(color_type == PHOTOMETRIC_YCBCR ) { + TIFFGetFieldDefaulted( image, TIFFTAG_YCBCRSUBSAMPLING, &hsubsampling, &vsubsampling ); + lineSizeCoeffs[1] = hsubsampling; + lineSizeCoeffs[2] = hsubsampling; + uint16 position; + TIFFGetFieldDefaulted( image, TIFFTAG_YCBCRPOSITIONING, &position ); + if( dstDepth == 8 ) + { + tiffReader = new KisTIFFYCbCrReaderTarget8Bit(layer->paintDevice(), poses, alphapos, depth, nbcolorsamples, extrasamplescount, transform, postprocessor, hsubsampling, vsubsampling, (KisTIFFYCbCr::Position)position); + } else if( dstDepth == 16 ) + { + tiffReader = new KisTIFFYCbCrReaderTarget16Bit( layer->paintDevice(), poses, alphapos, depth, nbcolorsamples, extrasamplescount, transform, postprocessor, hsubsampling, vsubsampling, (KisTIFFYCbCr::Position)position); + } + } else if(dstDepth == 8) + { + tiffReader = new KisTIFFReaderTarget8bit( layer->paintDevice(), poses, alphapos, depth, nbcolorsamples, extrasamplescount, transform, postprocessor); + } else if(dstDepth == 16) { + tiffReader = new KisTIFFReaderTarget16bit( layer->paintDevice(), poses, alphapos, depth, nbcolorsamples, extrasamplescount, transform, postprocessor); + } else if(dstDepth == 32) { + tiffReader = new KisTIFFReaderTarget32bit( layer->paintDevice(), poses, alphapos, depth, nbcolorsamples, extrasamplescount, transform, postprocessor); + } + + if(TIFFIsTiled(image)) + { + kdDebug(41008) << "tiled image" << endl; + uint32 tileWidth, tileHeight; + uint32 x, y; + TIFFGetField(image, TIFFTAG_TILEWIDTH, &tileWidth); + TIFFGetField(image, TIFFTAG_TILELENGTH, &tileHeight); + uint32 linewidth = (tileWidth * depth * nbchannels) / 8; + if(planarconfig == PLANARCONFIG_CONTIG) + { + buf = _TIFFmalloc(TIFFTileSize(image)); + if(depth < 16) + { + tiffstream = new TIFFStreamContigBelow16((uint8*)buf, depth, linewidth); + } else if(depth < 32) + { + tiffstream = new TIFFStreamContigBelow32((uint8*)buf, depth, linewidth); + } else { + tiffstream = new TIFFStreamContigAbove32((uint8*)buf, depth, linewidth); + } + } else { + ps_buf = new tdata_t[nbchannels]; + uint32 * lineSizes = new uint32[nbchannels]; + uint16 baseSize = TIFFTileSize(image)/nbchannels; + for(uint i = 0; i < nbchannels; i++) + { + ps_buf[i] = _TIFFmalloc(baseSize); + lineSizes[i] = baseSize / lineSizeCoeffs[i]; + } + tiffstream = new TIFFStreamSeperate( (uint8**) ps_buf, nbchannels, depth, lineSizes); + delete [] lineSizes; + } + kdDebug(41008) << linewidth << " " << nbchannels << " " << layer->paintDevice()->colorSpace()->nColorChannels() << endl; + for (y = 0; y < height; y+= tileHeight) + { + for (x = 0; x < width; x += tileWidth) + { + kdDebug(41008) << "Reading tile x = " << x << " y = " << y << endl; + if( planarconfig == PLANARCONFIG_CONTIG ) + { + TIFFReadTile(image, buf, x, y, 0, (tsample_t) -1); + } else { + for(uint i = 0; i < nbchannels; i++) + { + TIFFReadTile(image, ps_buf[i], x, y, 0, i); + } + } + uint32 realTileWidth = (x + tileWidth) < width ? tileWidth : width - x; + for (uint yintile = 0; y + yintile < height && yintile < tileHeight/vsubsampling; ) { + tiffReader->copyDataToChannels( x, y + yintile , realTileWidth, tiffstream); + yintile += 1; + tiffstream->moveToLine( yintile ); + } + tiffstream->restart(); + } + } + } else { + kdDebug(41008) << "striped image" << endl; + tsize_t stripsize = TIFFStripSize(image); + uint32 rowsPerStrip; + TIFFGetFieldDefaulted(image, TIFFTAG_ROWSPERSTRIP, &rowsPerStrip); + kdDebug() << rowsPerStrip << " " << height << endl; + rowsPerStrip = TQMIN(rowsPerStrip, height); // when TIFFNumberOfStrips(image) == 1 it might happen that rowsPerStrip is incorrectly set + if(planarconfig == PLANARCONFIG_CONTIG) + { + buf = _TIFFmalloc(stripsize); + if(depth < 16) + { + tiffstream = new TIFFStreamContigBelow16((uint8*)buf, depth, stripsize/rowsPerStrip); + } else if(depth < 32) + { + tiffstream = new TIFFStreamContigBelow32((uint8*)buf, depth, stripsize/rowsPerStrip); + } else { + tiffstream = new TIFFStreamContigAbove32((uint8*)buf, depth, stripsize/rowsPerStrip); + } + } else { + ps_buf = new tdata_t[nbchannels]; + uint32 scanLineSize = stripsize/rowsPerStrip; + kdDebug(41008) << " scanLineSize for each plan = " << scanLineSize << endl; + uint32 * lineSizes = new uint32[nbchannels]; + for(uint i = 0; i < nbchannels; i++) + { + ps_buf[i] = _TIFFmalloc(stripsize); + lineSizes[i] = scanLineSize / lineSizeCoeffs[i]; + } + tiffstream = new TIFFStreamSeperate( (uint8**) ps_buf, nbchannels, depth, lineSizes); + delete [] lineSizes; + } + + kdDebug(41008) << "Scanline size = " << TIFFRasterScanlineSize(image) << " / strip size = " << TIFFStripSize(image) << " / rowsPerStrip = " << rowsPerStrip << " stripsize/rowsPerStrip = " << stripsize/rowsPerStrip << endl; + uint32 y = 0; + kdDebug(41008) << " NbOfStrips = " << TIFFNumberOfStrips(image) << " rowsPerStrip = " << rowsPerStrip << " stripsize = " << stripsize << endl; + for (uint32 strip = 0; y < height; strip++) + { + if( planarconfig == PLANARCONFIG_CONTIG ) + { + TIFFReadEncodedStrip(image, TIFFComputeStrip( image, y, 0 ) , buf, (tsize_t) -1); + } else { + for(uint i = 0; i < nbchannels; i++) + { + TIFFReadEncodedStrip(image, TIFFComputeStrip( image, y, i ), ps_buf[i], (tsize_t) -1); + } + } + for( uint32 yinstrip = 0 ; yinstrip < rowsPerStrip && y < height ; ) + { + uint linesread = tiffReader->copyDataToChannels( 0, y, width, tiffstream); + y += linesread; + yinstrip += linesread; + tiffstream->moveToLine( yinstrip ); + } + tiffstream->restart(); + } + } + tiffReader->finalize(); + delete lineSizeCoeffs; + delete tiffReader; + delete tiffstream; + if( planarconfig == PLANARCONFIG_CONTIG ) + { + _TIFFfree(buf); + } else { + for(uint i = 0; i < nbchannels; i++) + { + _TIFFfree(ps_buf[i]); + } + delete[] ps_buf; + } + + m_img->addLayer(layer, m_img->rootLayer(), 0); + return KisImageBuilder_RESULT_OK; +} + +KisImageBuilder_Result KisTIFFConverter::buildImage(const KURL& uri) +{ + if (uri.isEmpty()) + return KisImageBuilder_RESULT_NO_URI; + + if (!TDEIO::NetAccess::exists(uri, false, tqApp -> mainWidget())) { + return KisImageBuilder_RESULT_NOT_EXIST; + } + + // We're not set up to handle asynchronous loading at the moment. + KisImageBuilder_Result result = KisImageBuilder_RESULT_FAILURE; + TQString tmpFile; + + if (TDEIO::NetAccess::download(uri, tmpFile, tqApp -> mainWidget())) { + KURL uriTF; + uriTF.setPath( tmpFile ); + result = decode(uriTF); + TDEIO::NetAccess::removeTempFile(tmpFile); + } + + return result; +} + + +KisImageSP KisTIFFConverter::image() +{ + return m_img; +} + + +KisImageBuilder_Result KisTIFFConverter::buildFile(const KURL& uri, KisImageSP img, KisTIFFOptions options) +{ + kdDebug(41008) << "Start writing TIFF File" << endl; + if (!img) + return KisImageBuilder_RESULT_EMPTY; + + if (uri.isEmpty()) + return KisImageBuilder_RESULT_NO_URI; + + if (!uri.isLocalFile()) + return KisImageBuilder_RESULT_NOT_LOCAL; + + // Open file for writing + TIFF *image; + if((image = TIFFOpen(TQFile::encodeName(uri.path()), "w")) == NULL){ + kdDebug(41008) << "Could not open the file for writting " << uri.path() << endl; + TIFFClose(image); + return (KisImageBuilder_RESULT_FAILURE); + } + + // Set the document informations + KoDocumentInfo * info = m_doc->documentInfo(); + KoDocumentInfoAbout * aboutPage = static_cast<KoDocumentInfoAbout *>(info->page( "about" )); + TQString title = aboutPage->title(); + if(!title.isEmpty()) + { + TIFFSetField(image, TIFFTAG_DOCUMENTNAME, title.ascii()); + } + TQString abstract = aboutPage->abstract(); + if(!abstract.isEmpty()) + { + TIFFSetField(image, TIFFTAG_IMAGEDESCRIPTION, abstract.ascii()); + } + KoDocumentInfoAuthor * authorPage = static_cast<KoDocumentInfoAuthor *>(info->page( "author" )); + TQString author = authorPage->fullName(); + if(!author.isEmpty()) + { + TIFFSetField(image, TIFFTAG_ARTIST, author.ascii()); + } + + KisTIFFWriterVisitor* visitor = new KisTIFFWriterVisitor(image, &options); + KisGroupLayer* root = dynamic_cast<KisGroupLayer*>(img->rootLayer().data()); + if(root == 0) + { + TDEIO::del(uri); + TIFFClose(image); + return KisImageBuilder_RESULT_FAILURE; + } + if(!visitor->visit( root )) + { + TDEIO::del(uri); + TIFFClose(image); + return KisImageBuilder_RESULT_FAILURE; + } + + TIFFClose(image); + return KisImageBuilder_RESULT_OK; +} + + +void KisTIFFConverter::cancel() +{ + m_stop = true; +} + +#include "kis_tiff_converter.moc" |