filters

kis_tiff_converter.cc

00001 /*
00002  *  Copyright (c) 2005-2006 Cyrille Berger <cberger@cberger.net>
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  * Boston, MA 02110-1301, USA.
00018  */
00019  
00020 #include "kis_tiff_converter.h"
00021 
00022 #include <stdio.h>
00023 
00024 #include <config.h>
00025 #include LCMS_HEADER
00026 
00027 #include <qfile.h>
00028 
00029 #include <kapplication.h>
00030 #include <KoDocumentInfo.h>
00031 
00032 #include <kio/netaccess.h>
00033 
00034 #include <kis_abstract_colorspace.h>
00035 #include <kis_colorspace_factory_registry.h>
00036 #include <kis_doc.h>
00037 #include <kis_image.h>
00038 #include <kis_iterators_pixel.h>
00039 #include <kis_layer.h>
00040 #include <kis_meta_registry.h>
00041 #include <kis_profile.h>
00042 #include <kis_group_layer.h>
00043 #include <kis_paint_layer.h>
00044 
00045 #include "kis_tiff_reader.h"
00046 #include "kis_tiff_ycbcr_reader.h"
00047 #include "kis_tiff_stream.h"
00048 #include "kis_tiff_writer_visitor.h"
00049 
00050 namespace {
00051 
00052     QString getColorSpaceForColorType(uint16 color_type, uint16 color_nb_bits, TIFF *image, uint16 &nbchannels, uint16 &extrasamplescount, uint8 &destDepth, uint16 sampletype) {
00053         if(color_type == PHOTOMETRIC_MINISWHITE || color_type == PHOTOMETRIC_MINISBLACK)
00054         {
00055             if(nbchannels == 0) nbchannels = 1;
00056             extrasamplescount = nbchannels - 1; // FIX the extrasamples count in case of
00057             if(color_nb_bits <= 8)
00058             {
00059                 destDepth = 8;
00060                 return "GRAYA";
00061             } else {
00062                 destDepth = 16;
00063                 return "GRAYA16";
00064             }
00065         } else if(color_type == PHOTOMETRIC_RGB  /*|| color_type == */ ) {
00066             if(nbchannels == 0) nbchannels = 3;
00067             extrasamplescount = nbchannels - 3; // FIX the extrasamples count in case of
00068             if(sampletype == SAMPLEFORMAT_IEEEFP)
00069             {
00070               if(color_nb_bits == 16)
00071               {
00072                 destDepth = 16;
00073                 return "RGBAF16HALF";
00074               } else if( color_nb_bits == 32) {
00075                 destDepth = 32;
00076                 return "RGBAF32";
00077               }
00078               return "";
00079             } else {
00080               if(color_nb_bits <= 8)
00081               {
00082                   destDepth = 8;
00083                   return "RGBA";
00084               } else {
00085                   destDepth = 16;
00086                   return "RGBA16";
00087               }
00088             }
00089         } else if(color_type == PHOTOMETRIC_YCBCR ) {
00090             if(nbchannels == 0) nbchannels = 3;
00091             extrasamplescount = nbchannels - 3; // FIX the extrasamples count in case of
00092             if(color_nb_bits <= 8)
00093             {
00094                 destDepth = 8;
00095                 return "YCbCrAU8";
00096             } else {
00097                 destDepth = 16;
00098                 return "YCbCrAU16";
00099             }
00100         } else if(color_type == PHOTOMETRIC_SEPARATED ) {
00101             if(nbchannels == 0) nbchannels = 4;
00102             // SEPARATED is in general CMYK but not allways, so we check
00103             uint16 inkset;
00104             if((TIFFGetField(image, TIFFTAG_INKSET, &inkset) == 0)){
00105                 kdDebug(41008) <<  "Image does not define the inkset." << endl;
00106                 inkset = 2;
00107             }
00108             if(inkset !=  INKSET_CMYK)
00109             {
00110                 kdDebug(41008) << "Unsupported inkset (right now, only CMYK is supported)" << endl;
00111                 char** ink_names;
00112                 uint16 numberofinks;
00113                 if( TIFFGetField(image, TIFFTAG_INKNAMES, &ink_names) && TIFFGetField(image, TIFFTAG_NUMBEROFINKS, &numberofinks) )
00114                 {
00115                     kdDebug(41008) << "Inks are : " << endl;
00116                     for(uint i = 0; i < numberofinks; i++)
00117                     {
00118                         kdDebug(41008) << ink_names[i] << endl;
00119                     }
00120                 } else {
00121                     kdDebug(41008) << "inknames aren't defined !" << endl;
00122                     // To be able to read stupid adobe files, if there are no information about inks and four channels, then it's a CMYK file :
00123                     if( nbchannels - extrasamplescount != 4)
00124                     {
00125                         return "";
00126                     }
00127                 }
00128             }
00129             if(color_nb_bits <= 8)
00130             {
00131                 destDepth = 8;
00132                 return "CMYK";
00133             } else {
00134                 destDepth = 16;
00135                 return "CMYKA16";
00136             }
00137         } else if(color_type == PHOTOMETRIC_CIELAB
00138 #ifdef PHOTOMETRIC_ICCLAB
00139      || color_type == PHOTOMETRIC_ICCLAB
00140 #endif
00141      ) {
00142             destDepth = 16;
00143             if(nbchannels == 0) nbchannels = 3;
00144             extrasamplescount = nbchannels - 3; // FIX the extrasamples count in case of
00145             return "LABA"; // TODO add support for a 8bit LAB colorspace when it is written
00146         } else if(color_type ==  PHOTOMETRIC_PALETTE) {
00147             destDepth = 16;
00148             if(nbchannels == 0) nbchannels = 2;
00149             extrasamplescount = nbchannels - 2; // FIX the extrasamples count in case of
00150             // <-- we will convert the index image to RGBA16 as the palette is allways on 16bits colors
00151             return "RGBA16";
00152         }
00153         return "";
00154     }
00155 }
00156 
00157 KisTIFFConverter::KisTIFFConverter(KisDoc *doc, KisUndoAdapter *adapter)
00158 {
00159     m_doc = doc;
00160     m_adapter = adapter;
00161     m_job = 0;
00162     m_stop = false;
00163 }
00164 
00165 KisTIFFConverter::~KisTIFFConverter()
00166 {
00167 }
00168 
00169 KisImageBuilder_Result KisTIFFConverter::decode(const KURL& uri)
00170 {
00171     kdDebug(41008) << "Start decoding TIFF File" << endl;
00172     // Opent the TIFF file
00173     TIFF *image = 0;
00174     if((image = TIFFOpen(QFile::encodeName(uri.path()), "r")) == NULL){
00175         kdDebug(41008) << "Could not open the file, either it doesn't exist, either it is not a TIFF : " << uri.path() << endl;
00176 
00177         return (KisImageBuilder_RESULT_BAD_FETCH);
00178     }
00179     do {
00180         kdDebug(41008) << "Read new sub-image" << endl;
00181         KisImageBuilder_Result result = readTIFFDirectory(image);
00182         if(result != KisImageBuilder_RESULT_OK){
00183             return result;
00184         }
00185     } while (TIFFReadDirectory(image));
00186     // Freeing memory
00187     TIFFClose(image);
00188     return KisImageBuilder_RESULT_OK;
00189 }
00190 
00191 KisImageBuilder_Result KisTIFFConverter::readTIFFDirectory( TIFF* image)
00192 {
00193     // Read information about the tiff
00194     uint32 width, height;
00195     if(TIFFGetField(image, TIFFTAG_IMAGEWIDTH, &width) == 0){
00196         kdDebug(41008) <<  "Image does not define its width" << endl;
00197         TIFFClose(image);
00198         return KisImageBuilder_RESULT_INVALID_ARG;
00199     }
00200     if(TIFFGetField(image, TIFFTAG_IMAGELENGTH, &height) == 0){
00201         kdDebug(41008) <<  "Image does not define its height" << endl;
00202         TIFFClose(image);
00203         return KisImageBuilder_RESULT_INVALID_ARG;
00204     }
00205     uint16 depth;
00206     if((TIFFGetField(image, TIFFTAG_BITSPERSAMPLE, &depth) == 0)){
00207         kdDebug(41008) <<  "Image does not define its depth" << endl;
00208         depth = 1;
00209     }
00210     uint16 sampletype;
00211     if((TIFFGetField(image, TIFFTAG_SAMPLEFORMAT, &sampletype) == 0)){
00212         kdDebug(41008) <<  "Image does not define its sample type" << endl;
00213         sampletype =  SAMPLEFORMAT_UINT;
00214     }
00215     // Determine the number of channels (usefull to know if a file has an alpha or not
00216     uint16 nbchannels;
00217     if(TIFFGetField(image, TIFFTAG_SAMPLESPERPIXEL, &nbchannels) == 0){
00218         kdDebug(41008) << "Image has an undefined number of samples per pixel" << endl;
00219         nbchannels = 0;
00220     }
00221     // Get the number of extrasamples and information about them
00222     uint16 *sampleinfo, extrasamplescount;
00223     if(TIFFGetField(image, TIFFTAG_EXTRASAMPLES, &extrasamplescount, &sampleinfo) == 0)
00224     {
00225         extrasamplescount = 0;
00226     }
00227     // Determine the colorspace
00228     uint16 color_type;
00229     if(TIFFGetField(image, TIFFTAG_PHOTOMETRIC, &color_type) == 0){
00230         kdDebug(41008) << "Image has an undefined photometric interpretation" << endl;
00231         color_type = PHOTOMETRIC_MINISWHITE;
00232     }
00233     uint8 dstDepth;
00234     QString csName = getColorSpaceForColorType(color_type, depth, image, nbchannels, extrasamplescount, dstDepth,sampletype);
00235     if(csName.isEmpty()) {
00236         kdDebug(41008) << "Image has an unsupported colorspace : " << color_type << " for this depth : "<< depth << endl;
00237         TIFFClose(image);
00238         return KisImageBuilder_RESULT_UNSUPPORTED_COLORSPACE;
00239     }
00240     kdDebug(41008) << "Colorspace is : " << csName << " with a depth of " << depth << " and with a nb of channels of " << nbchannels << endl;
00241     
00242     // Read image profile
00243     kdDebug() << "Reading profile" << endl;
00244     KisProfile* profile = 0;
00245     DWORD EmbedLen;
00246     LPBYTE EmbedBuffer;
00247 
00248     if (TIFFGetField(image, TIFFTAG_ICCPROFILE, &EmbedLen, &EmbedBuffer)) {
00249         kdDebug(41008) << "Profile found" << endl;
00250         QByteArray rawdata;
00251         rawdata.resize(EmbedLen);
00252         memcpy(rawdata.data(), EmbedBuffer, EmbedLen);
00253         profile = new KisProfile(rawdata);
00254     } else {
00255         kdDebug(41008) << "No Profile found" << endl;
00256     }
00257     
00258     // Retrieve a pointer to the colorspace
00259     KisColorSpace* cs = 0;
00260     if (profile && profile->isSuitableForOutput())
00261     {
00262         kdDebug(41008) << "image has embedded profile: " << profile -> productName() << "\n";
00263         cs = KisMetaRegistry::instance()->csRegistry()->getColorSpace(csName, profile);
00264     }
00265     else
00266         cs = KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID(csName,""),"");
00267 
00268     if(cs == 0) {
00269         kdDebug(41008) << "Colorspace " << csName << " is not available, please check your installation." << endl;
00270         TIFFClose(image);
00271         return KisImageBuilder_RESULT_UNSUPPORTED_COLORSPACE;
00272     }
00273     
00274     // Create the cmsTransform if needed 
00275     cmsHTRANSFORM transform = 0;
00276     if(profile && !profile->isSuitableForOutput())
00277     {
00278         kdDebug(41008) << "The profile can't be used in krita, need conversion" << endl;
00279         transform = cmsCreateTransform(profile->profile(), cs->colorSpaceType(),
00280                                        cs->getProfile()->profile() , cs->colorSpaceType(),
00281                                        INTENT_PERCEPTUAL, 0);
00282     }
00283 
00284     
00285     // Check if there is an alpha channel
00286     int8 alphapos = -1; // <- no alpha
00287     // Check which extra is alpha if any
00288     kdDebug(41008) << "There are " << nbchannels << " channels and " << extrasamplescount << " extra channels" << endl;
00289     if(sampleinfo) // index images don't have any sampleinfo, and therefor sampleinfo == 0
00290     {
00291         for(int i = 0; i < extrasamplescount; i ++)
00292         {
00293             kdDebug(41008) << i << " " << extrasamplescount << " "  << (cs->nColorChannels()) <<  nbchannels << " " << sampleinfo[i] << endl;
00294             if(sampleinfo[i] == EXTRASAMPLE_ASSOCALPHA)
00295             {
00296                 // XXX: dangelo: the color values are already multiplied with
00297                 // the alpha value.  This needs to be reversed later (postprocessor?)
00298                 alphapos = i;
00299             }
00300     
00301             if (sampleinfo[i] == EXTRASAMPLE_UNASSALPHA)
00302             {
00303                 // color values are not premultiplied with alpha, and can be used as they are.
00304                 alphapos = i;
00305             }
00306         }
00307     }
00308     
00309     // Read META Information
00310     KoDocumentInfo * info = m_doc->documentInfo();
00311     KoDocumentInfoAbout * aboutPage = static_cast<KoDocumentInfoAbout *>(info->page( "about" ));
00312     KoDocumentInfoAuthor * authorPage = static_cast<KoDocumentInfoAuthor *>(info->page( "author"));
00313     char* text;
00314     if (TIFFGetField(image, TIFFTAG_ARTIST, &text)) {
00315         authorPage->setFullName(text);
00316     }
00317     if (TIFFGetField(image, TIFFTAG_DOCUMENTNAME, &text)) {
00318         aboutPage->setTitle(text);
00319     }
00320     if (TIFFGetField(image,TIFFTAG_IMAGEDESCRIPTION,&text) ) {
00321         aboutPage->setAbstract( text );
00322     }
00323     
00324     
00325     // Get the planar configuration
00326     uint16 planarconfig;
00327     if(TIFFGetField(image, TIFFTAG_PLANARCONFIG, &planarconfig) == 0)
00328     {
00329         kdDebug(41008) <<  "Plannar configuration is not define" << endl;
00330         TIFFClose(image);
00331         return KisImageBuilder_RESULT_INVALID_ARG;
00332     }
00333     // Creating the KisImageSP
00334     if( ! m_img ) {
00335         m_img = new KisImage(m_doc->undoAdapter(), width, height, cs, "built image");
00336         Q_CHECK_PTR(m_img);
00337         m_img->blockSignals(true); // Don't send out signals while we're building the image
00338         if(profile)
00339         {
00340             m_img -> addAnnotation( profile->annotation() );
00341         }
00342     } else {
00343         if( m_img->width() < (Q_INT32)width || m_img->height() < (Q_INT32)height)
00344         {
00345             Q_UINT32 newwidth = (m_img->width() < (Q_INT32)width) ? width : m_img->width();
00346             Q_UINT32 newheight = (m_img->height() < (Q_INT32)height) ? height : m_img->height();
00347             m_img->resize(newwidth, newheight, false);
00348         }
00349     }
00350     KisPaintLayer* layer = new KisPaintLayer(m_img, m_img -> nextLayerName(), Q_UINT8_MAX);
00351     tdata_t buf = 0;
00352     tdata_t* ps_buf = 0; // used only for planar configuration seperated
00353     TIFFStreamBase* tiffstream;
00354     
00355     KisTIFFReaderBase* tiffReader = 0;
00356     
00357     Q_UINT8 poses[5];
00358     KisTIFFPostProcessor* postprocessor = 0;
00359     
00360     // Configure poses
00361     uint8 nbcolorsamples = nbchannels - extrasamplescount;
00362     switch(color_type)
00363     {
00364         case PHOTOMETRIC_MINISWHITE:
00365         {
00366             poses[0] = 0; poses[1] = 1;
00367             postprocessor = new KisTIFFPostProcessorInvert(nbcolorsamples);
00368         }
00369         break;
00370         case PHOTOMETRIC_MINISBLACK:
00371         {
00372             poses[0] = 0; poses[1] = 1;
00373             postprocessor = new KisTIFFPostProcessor(nbcolorsamples);
00374         }
00375         break;
00376         case PHOTOMETRIC_CIELAB:
00377         {
00378             poses[0] = 0; poses[1] = 1; poses[2] = 2; poses[3] = 3;
00379             postprocessor = new KisTIFFPostProcessorICCLABtoCIELAB(nbcolorsamples);
00380         }
00381         break;
00382 #ifdef PHOTOMETRIC_ICCLAB
00383         case PHOTOMETRIC_ICCLAB:
00384         {
00385             poses[0] = 0; poses[1] = 1; poses[2] = 2; poses[3] = 3;
00386             postprocessor = new KisTIFFPostProcessor(nbcolorsamples);
00387         }
00388         break;
00389 #endif
00390         case PHOTOMETRIC_RGB:
00391         {
00392             poses[0] = 2; poses[1] = 1; poses[2] = 0; poses[3] = 3;
00393             postprocessor = new KisTIFFPostProcessor(nbcolorsamples);
00394         }
00395         break;
00396         case PHOTOMETRIC_SEPARATED:
00397         {
00398             poses[0] = 0; poses[1] = 1; poses[2] = 2; poses[3] = 3; poses[4] = 4;
00399             postprocessor = new KisTIFFPostProcessor(nbcolorsamples);
00400         }
00401         break;
00402         default:
00403         break;
00404     }
00405     
00406     
00407     // Initisalize tiffReader
00408     uint16 * lineSizeCoeffs = new uint16[nbchannels];
00409     uint16 vsubsampling = 1;
00410     uint16 hsubsampling = 1;
00411     for(uint i = 0; i < nbchannels; i++)
00412     {
00413         lineSizeCoeffs[i] = 1;
00414     }
00415     if( color_type == PHOTOMETRIC_PALETTE)
00416     {
00417         uint16 *red; // No need to free them they are free by libtiff
00418         uint16 *green;
00419         uint16 *blue;
00420         if ((TIFFGetField(image, TIFFTAG_COLORMAP, &red, &green, &blue)) == 0)
00421         {
00422             kdDebug(41008) <<  "Indexed image does not define a palette" << endl;
00423             TIFFClose(image);
00424             return KisImageBuilder_RESULT_INVALID_ARG;
00425         }
00426 
00427         tiffReader = new KisTIFFReaderFromPalette( layer->paintDevice(), red, green, blue, poses, alphapos, depth, nbcolorsamples, extrasamplescount, transform, postprocessor);
00428     } else if(color_type == PHOTOMETRIC_YCBCR ) {
00429         TIFFGetFieldDefaulted( image, TIFFTAG_YCBCRSUBSAMPLING, &hsubsampling, &vsubsampling );
00430         lineSizeCoeffs[1] = hsubsampling;
00431         lineSizeCoeffs[2] = hsubsampling;
00432         uint16 position;
00433         TIFFGetFieldDefaulted( image, TIFFTAG_YCBCRPOSITIONING, &position  );
00434         if( dstDepth == 8 )
00435         {
00436             tiffReader = new KisTIFFYCbCrReaderTarget8Bit(layer->paintDevice(), poses, alphapos, depth, nbcolorsamples, extrasamplescount, transform, postprocessor, hsubsampling, vsubsampling, (KisTIFFYCbCr::Position)position);
00437         } else if( dstDepth == 16 )
00438         {
00439             tiffReader = new KisTIFFYCbCrReaderTarget16Bit( layer->paintDevice(), poses, alphapos, depth, nbcolorsamples, extrasamplescount, transform, postprocessor, hsubsampling, vsubsampling, (KisTIFFYCbCr::Position)position);
00440         }
00441     } else if(dstDepth == 8)
00442     {
00443         tiffReader = new KisTIFFReaderTarget8bit( layer->paintDevice(), poses, alphapos, depth, nbcolorsamples, extrasamplescount, transform, postprocessor);
00444     } else if(dstDepth == 16) {
00445         tiffReader = new KisTIFFReaderTarget16bit( layer->paintDevice(), poses, alphapos, depth, nbcolorsamples, extrasamplescount, transform, postprocessor);
00446     } else if(dstDepth == 32) {
00447         tiffReader = new KisTIFFReaderTarget32bit( layer->paintDevice(), poses, alphapos, depth, nbcolorsamples, extrasamplescount, transform, postprocessor);
00448     }
00449     
00450     if(TIFFIsTiled(image))
00451     {
00452         kdDebug(41008) << "tiled image" << endl;
00453         uint32 tileWidth, tileHeight;
00454         uint32 x, y;
00455         TIFFGetField(image, TIFFTAG_TILEWIDTH, &tileWidth);
00456         TIFFGetField(image, TIFFTAG_TILELENGTH, &tileHeight);
00457         uint32 linewidth = (tileWidth * depth * nbchannels) / 8;
00458         if(planarconfig == PLANARCONFIG_CONTIG)
00459         {
00460             buf = _TIFFmalloc(TIFFTileSize(image));
00461             if(depth < 16)
00462             {
00463                 tiffstream = new TIFFStreamContigBelow16((uint8*)buf, depth, linewidth);
00464             } else if(depth < 32)
00465             {
00466                 tiffstream = new TIFFStreamContigBelow32((uint8*)buf, depth, linewidth);
00467             } else {
00468                 tiffstream = new TIFFStreamContigAbove32((uint8*)buf, depth, linewidth);
00469             }
00470         } else {
00471             ps_buf = new tdata_t[nbchannels];
00472             uint32 * lineSizes = new uint32[nbchannels];
00473             uint16 baseSize = TIFFTileSize(image)/nbchannels;
00474             for(uint i = 0; i < nbchannels; i++)
00475             {
00476                 ps_buf[i] = _TIFFmalloc(baseSize);
00477                 lineSizes[i] = baseSize / lineSizeCoeffs[i];
00478             }
00479             tiffstream = new TIFFStreamSeperate( (uint8**) ps_buf, nbchannels, depth, lineSizes);
00480             delete [] lineSizes;
00481         }
00482         kdDebug(41008) << linewidth << " " << nbchannels << " " << layer->paintDevice()->colorSpace()->nColorChannels() << endl;
00483         for (y = 0; y < height; y+= tileHeight)
00484         {
00485             for (x = 0; x < width; x += tileWidth)
00486             {
00487                 kdDebug(41008) << "Reading tile x = " << x << " y = " << y << endl;
00488                 if( planarconfig == PLANARCONFIG_CONTIG )
00489                 {
00490                     TIFFReadTile(image, buf, x, y, 0, (tsample_t) -1);
00491                 } else {
00492                     for(uint i = 0; i < nbchannels; i++)
00493                     {
00494                         TIFFReadTile(image, ps_buf[i], x, y, 0, i);
00495                     }
00496                 }
00497                 uint32 realTileWidth =  (x + tileWidth) < width ? tileWidth : width - x;
00498                 for (uint yintile = 0; y + yintile < height && yintile < tileHeight/vsubsampling; ) {
00499                     tiffReader->copyDataToChannels( x, y + yintile , realTileWidth, tiffstream);
00500                     yintile += 1;
00501                     tiffstream->moveToLine( yintile );
00502                 }
00503                 tiffstream->restart();
00504             }
00505         }
00506     } else {
00507         kdDebug(41008) << "striped image" << endl;
00508         tsize_t stripsize = TIFFStripSize(image);
00509         uint32 rowsPerStrip;
00510         TIFFGetFieldDefaulted(image, TIFFTAG_ROWSPERSTRIP, &rowsPerStrip);
00511         kdDebug() << rowsPerStrip << " " << height << endl;
00512         rowsPerStrip = QMIN(rowsPerStrip, height); // when TIFFNumberOfStrips(image) == 1 it might happen that rowsPerStrip is incorrectly set
00513         if(planarconfig == PLANARCONFIG_CONTIG)
00514         {
00515             buf = _TIFFmalloc(stripsize);
00516             if(depth < 16)
00517             {
00518                 tiffstream = new TIFFStreamContigBelow16((uint8*)buf, depth, stripsize/rowsPerStrip);
00519             } else if(depth < 32)
00520             {
00521                 tiffstream = new TIFFStreamContigBelow32((uint8*)buf, depth, stripsize/rowsPerStrip);
00522             } else {
00523                 tiffstream = new TIFFStreamContigAbove32((uint8*)buf, depth, stripsize/rowsPerStrip);
00524             }
00525         } else {
00526             ps_buf = new tdata_t[nbchannels];
00527             uint32 scanLineSize = stripsize/rowsPerStrip;
00528             kdDebug(41008) << " scanLineSize for each plan = " << scanLineSize << endl;
00529             uint32 * lineSizes = new uint32[nbchannels];
00530             for(uint i = 0; i < nbchannels; i++)
00531             {
00532                 ps_buf[i] = _TIFFmalloc(stripsize);
00533                 lineSizes[i] = scanLineSize / lineSizeCoeffs[i];
00534             }
00535             tiffstream = new TIFFStreamSeperate( (uint8**) ps_buf, nbchannels, depth, lineSizes);
00536             delete [] lineSizes;
00537         }
00538 
00539         kdDebug(41008) << "Scanline size = " << TIFFRasterScanlineSize(image) << " / strip size = " << TIFFStripSize(image) << " / rowsPerStrip = " << rowsPerStrip << " stripsize/rowsPerStrip = " << stripsize/rowsPerStrip << endl;
00540         uint32 y = 0;
00541         kdDebug(41008) << " NbOfStrips = " << TIFFNumberOfStrips(image) << " rowsPerStrip = " << rowsPerStrip << " stripsize = " << stripsize << endl;
00542         for (uint32 strip = 0; y < height; strip++)
00543         {
00544             if( planarconfig == PLANARCONFIG_CONTIG )
00545             {
00546                 TIFFReadEncodedStrip(image, TIFFComputeStrip( image, y, 0 ) , buf, (tsize_t) -1);
00547             } else {
00548                 for(uint i = 0; i < nbchannels; i++)
00549                 {
00550                     TIFFReadEncodedStrip(image, TIFFComputeStrip( image, y, i ), ps_buf[i], (tsize_t) -1);
00551                 }
00552             }
00553             for( uint32 yinstrip = 0 ; yinstrip < rowsPerStrip && y < height ; )
00554             {
00555                 uint linesread = tiffReader->copyDataToChannels( 0, y, width, tiffstream);
00556                 y += linesread;
00557                 yinstrip += linesread;
00558                 tiffstream->moveToLine( yinstrip );
00559             }
00560             tiffstream->restart();
00561         }
00562     }
00563     tiffReader->finalize();
00564     delete lineSizeCoeffs;
00565     delete tiffReader;
00566     delete tiffstream;
00567     if( planarconfig == PLANARCONFIG_CONTIG )
00568     {
00569         _TIFFfree(buf);
00570     } else {
00571         for(uint i = 0; i < nbchannels; i++)
00572         {
00573             _TIFFfree(ps_buf[i]);
00574         }
00575         delete[] ps_buf;
00576     }
00577     
00578     m_img->addLayer(layer, m_img->rootLayer(), 0);
00579     return KisImageBuilder_RESULT_OK;
00580 }
00581 
00582 KisImageBuilder_Result KisTIFFConverter::buildImage(const KURL& uri)
00583 {
00584     if (uri.isEmpty())
00585         return KisImageBuilder_RESULT_NO_URI;
00586 
00587     if (!KIO::NetAccess::exists(uri, false, qApp -> mainWidget())) {
00588         return KisImageBuilder_RESULT_NOT_EXIST;
00589     }
00590 
00591     // We're not set up to handle asynchronous loading at the moment.
00592     KisImageBuilder_Result result = KisImageBuilder_RESULT_FAILURE;
00593     QString tmpFile;
00594 
00595     if (KIO::NetAccess::download(uri, tmpFile, qApp -> mainWidget())) {
00596         KURL uriTF;
00597         uriTF.setPath( tmpFile );
00598         result = decode(uriTF);
00599         KIO::NetAccess::removeTempFile(tmpFile);
00600     }
00601 
00602     return result;
00603 }
00604 
00605 
00606 KisImageSP KisTIFFConverter::image()
00607 {
00608     return m_img;
00609 }
00610 
00611 
00612 KisImageBuilder_Result KisTIFFConverter::buildFile(const KURL& uri, KisImageSP img, KisTIFFOptions options)
00613 {
00614     kdDebug(41008) << "Start writing TIFF File" << endl;
00615     if (!img)
00616         return KisImageBuilder_RESULT_EMPTY;
00617 
00618     if (uri.isEmpty())
00619         return KisImageBuilder_RESULT_NO_URI;
00620 
00621     if (!uri.isLocalFile())
00622         return KisImageBuilder_RESULT_NOT_LOCAL;
00623     
00624     // Open file for writing
00625     TIFF *image;
00626     if((image = TIFFOpen(QFile::encodeName(uri.path()), "w")) == NULL){
00627         kdDebug(41008) << "Could not open the file for writting " << uri.path() << endl;
00628         TIFFClose(image);
00629         return (KisImageBuilder_RESULT_FAILURE);
00630     }
00631 
00632     // Set the document informations
00633     KoDocumentInfo * info = m_doc->documentInfo();
00634     KoDocumentInfoAbout * aboutPage = static_cast<KoDocumentInfoAbout *>(info->page( "about" ));
00635     QString title = aboutPage->title();
00636     if(!title.isEmpty())
00637     {
00638         TIFFSetField(image, TIFFTAG_DOCUMENTNAME, title.ascii());
00639     }
00640     QString abstract = aboutPage->abstract();
00641     if(!abstract.isEmpty())
00642     {
00643         TIFFSetField(image, TIFFTAG_IMAGEDESCRIPTION, abstract.ascii());
00644     }
00645     KoDocumentInfoAuthor * authorPage = static_cast<KoDocumentInfoAuthor *>(info->page( "author" ));
00646     QString author = authorPage->fullName();
00647     if(!author.isEmpty())
00648     {
00649         TIFFSetField(image, TIFFTAG_ARTIST, author.ascii());
00650     }
00651     
00652     KisTIFFWriterVisitor* visitor = new KisTIFFWriterVisitor(image, &options);
00653     KisGroupLayer* root = dynamic_cast<KisGroupLayer*>(img->rootLayer().data());
00654     if(root == 0)
00655     {
00656         KIO::del(uri);
00657         TIFFClose(image);
00658         return KisImageBuilder_RESULT_FAILURE;
00659     }
00660     if(!visitor->visit( root ))
00661     {
00662         KIO::del(uri);
00663         TIFFClose(image);
00664         return KisImageBuilder_RESULT_FAILURE;
00665     }
00666     
00667     TIFFClose(image);
00668     return KisImageBuilder_RESULT_OK;
00669 }
00670 
00671 
00672 void KisTIFFConverter::cancel()
00673 {
00674     m_stop = true;
00675 }
00676 
00677 #include "kis_tiff_converter.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys