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