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