filters

kis_tiff_writer_visitor.cpp

00001 /*
00002  *  Copyright (c) 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_writer_visitor.h"
00021 
00022 #include <kmessagebox.h>
00023 #include <klocale.h>
00024 
00025 #include <kis_annotation.h>
00026 #include <kis_colorspace.h>
00027 #include <kis_group_layer.h>
00028 #include <kis_image.h>
00029 #include <kis_paint_layer.h>
00030 #include <kis_types.h>
00031 
00032 #include "kis_tiff_converter.h"
00033 
00034 namespace {
00035     bool writeColorSpaceInformation( TIFF* image, KisColorSpace * cs, uint16& color_type, uint16& sample_format )
00036     {
00037         sample_format = SAMPLEFORMAT_UINT;
00038         if ( cs->id() == KisID("GRAYA") || cs->id() == KisID("GRAYA16") )
00039         {
00040             color_type = PHOTOMETRIC_MINISBLACK;
00041             return true;
00042         }
00043         if ( cs->id() == KisID("RGBA") || cs->id() == KisID("RGBA16") )
00044         {
00045             color_type = PHOTOMETRIC_RGB;
00046             return true;
00047         }
00048         if ( cs->id() == KisID("RGBAF16HALF") || cs->id() == KisID("RGBAF32") )
00049         {
00050             color_type = PHOTOMETRIC_RGB;
00051             sample_format = SAMPLEFORMAT_IEEEFP;
00052             return true;
00053         }
00054         if ( cs->id() == KisID("CMYK") || cs->id() == KisID("CMYKA16") )
00055         {
00056             color_type = PHOTOMETRIC_SEPARATED;
00057             TIFFSetField(image, TIFFTAG_INKSET, INKSET_CMYK);
00058             return true;
00059         }
00060         if ( cs->id() == KisID("LABA") )
00061         {
00062             color_type = PHOTOMETRIC_CIELAB;
00063             return true;
00064         }
00065 
00066         KMessageBox::error(0, i18n("Cannot export images in %1.\n").arg(cs->id().name()) ) ;
00067         return false;
00068 
00069     }
00070 }
00071 
00072 KisTIFFWriterVisitor::KisTIFFWriterVisitor(TIFF*img, KisTIFFOptions* options) : m_image(img), m_options(options)
00073 {
00074 }
00075 
00076 KisTIFFWriterVisitor::~KisTIFFWriterVisitor()
00077 {
00078 }
00079 
00080 bool KisTIFFWriterVisitor::saveAlpha() { return m_options->alpha; }
00081 
00082 bool KisTIFFWriterVisitor::copyDataToStrips( KisHLineIterator it, tdata_t buff, uint8 depth, uint8 nbcolorssamples, Q_UINT8* poses)
00083 {
00084     if(depth == 32)
00085     {
00086         Q_UINT32 *dst = reinterpret_cast<Q_UINT32 *>(buff);
00087         while (!it.isDone()) {
00088             const Q_UINT32 *d = reinterpret_cast<const Q_UINT32 *>(it.rawData());
00089             int i;
00090             for(i = 0; i < nbcolorssamples; i++)
00091             {
00092                 *(dst++) = d[poses[i]];
00093             }
00094             if(saveAlpha()) *(dst++) = d[poses[i]];
00095             ++it;
00096         }
00097         return true;
00098     } else if(depth == 16)
00099     {
00100         Q_UINT16 *dst = reinterpret_cast<Q_UINT16 *>(buff);
00101         while (!it.isDone()) {
00102             const Q_UINT16 *d = reinterpret_cast<const Q_UINT16 *>(it.rawData());
00103             int i;
00104             for(i = 0; i < nbcolorssamples; i++)
00105             {
00106                 *(dst++) = d[poses[i]];
00107             }
00108             if(saveAlpha()) *(dst++) = d[poses[i]];
00109             ++it;
00110         }
00111         return true;
00112     } else if(depth == 8) {
00113         Q_UINT8 *dst = reinterpret_cast<Q_UINT8 *>(buff);
00114         while (!it.isDone()) {
00115             const Q_UINT8 *d = it.rawData();
00116             int i;
00117             for(i = 0; i < nbcolorssamples; i++)
00118             {
00119                 *(dst++) = d[poses[i]];
00120             }
00121             if(saveAlpha()) *(dst++) = d[poses[i]];
00122             ++it;
00123         }
00124         return true;
00125     }
00126     return false;
00127 }
00128 
00129 
00130 bool KisTIFFWriterVisitor::visit(KisPaintLayer *layer)
00131 {
00132     kdDebug(41008) << "visiting on paint layer " << layer->name() << "\n";
00133     KisPaintDeviceSP pd = layer->paintDevice();
00134     // Save depth
00135     int depth = 8 * pd->pixelSize() / pd->nChannels();
00136     TIFFSetField(image(), TIFFTAG_BITSPERSAMPLE, depth);
00137     // Save number of samples
00138     if(saveAlpha())
00139     {
00140         TIFFSetField(image(), TIFFTAG_SAMPLESPERPIXEL, pd->nChannels());
00141         uint16 sampleinfo[1] = { EXTRASAMPLE_UNASSALPHA };
00142         TIFFSetField(image(), TIFFTAG_EXTRASAMPLES, 1, sampleinfo);
00143     } else {
00144         TIFFSetField(image(), TIFFTAG_SAMPLESPERPIXEL, pd->nChannels() - 1);
00145         TIFFSetField(image(), TIFFTAG_EXTRASAMPLES, 0);
00146     }
00147     // Save colorspace information
00148     uint16 color_type;
00149     uint16 sample_format;
00150     if(!writeColorSpaceInformation(image(), pd->colorSpace(), color_type, sample_format))
00151     { // unsupported colorspace
00152         return false;
00153     }
00154     TIFFSetField(image(), TIFFTAG_PHOTOMETRIC, color_type);
00155     TIFFSetField(image(), TIFFTAG_SAMPLEFORMAT, sample_format);
00156     TIFFSetField(image(), TIFFTAG_IMAGEWIDTH, layer->image()->width());
00157     TIFFSetField(image(), TIFFTAG_IMAGELENGTH, layer->image()->height());
00158 
00159     // Set the compression options
00160     TIFFSetField(image(), TIFFTAG_COMPRESSION, m_options->compressionType);
00161     TIFFSetField(image(), TIFFTAG_FAXMODE, m_options->faxMode);
00162     TIFFSetField(image(), TIFFTAG_JPEGQUALITY, m_options->jpegQuality);
00163     TIFFSetField(image(), TIFFTAG_ZIPQUALITY, m_options->deflateCompress);
00164     TIFFSetField(image(), TIFFTAG_PIXARLOGQUALITY, m_options->pixarLogCompress);
00165     
00166     // Set the predictor
00167     TIFFSetField(image(), TIFFTAG_PREDICTOR, m_options->predictor);
00168 
00169     // Use contiguous configuration
00170     TIFFSetField(image(), TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
00171     // Use 8 rows per strip
00172     TIFFSetField(image(), TIFFTAG_ROWSPERSTRIP, 8);
00173 
00174     // Save profile
00175     KisProfile* profile = pd->colorSpace()->getProfile();
00176     if(profile)
00177     {
00178         QByteArray ba = profile->annotation()->annotation();
00179         TIFFSetField(image(), TIFFTAG_ICCPROFILE, ba.size(),ba.data());
00180     }
00181     tsize_t stripsize = TIFFStripSize(image());
00182     tdata_t buff = _TIFFmalloc(stripsize);
00183     Q_INT32 height = layer->image()->height();
00184     Q_INT32 width = layer->image()->width();
00185     bool r = true;
00186     for (int y = 0; y < height; y++) {
00187         KisHLineIterator it = layer->paintDevice()->createHLineIterator(0, y, width, false);
00188         switch(color_type)
00189         {
00190             case PHOTOMETRIC_MINISBLACK:
00191             {
00192                 Q_UINT8 poses[]={ 0,1 };
00193                 r = copyDataToStrips(it, buff, depth, 1, poses);
00194             }
00195                 break;
00196             case PHOTOMETRIC_RGB:
00197             {
00198                 Q_UINT8 poses[]={ 2, 1, 0, 3};
00199                 r = copyDataToStrips(it, buff, depth, 3, poses);
00200             }
00201                 break;
00202             case PHOTOMETRIC_SEPARATED:
00203             {
00204                 Q_UINT8 poses[]={ 0, 1, 2, 3, 4 };
00205                 r = copyDataToStrips(it, buff, depth, 4, poses);
00206             }
00207                 break;
00208             case PHOTOMETRIC_CIELAB:
00209             {
00210                 Q_UINT8 poses[]={ 0, 1, 2, 3 };
00211                 r = copyDataToStrips(it, buff, depth, 3, poses);
00212             }
00213                 break;
00214             return false;
00215         }
00216         if(!r) return false;
00217         TIFFWriteScanline(image(), buff, y, (tsample_t) -1);
00218     }
00219     _TIFFfree(buff);
00220     TIFFWriteDirectory(image());
00221     return true;
00222 }
00223 bool KisTIFFWriterVisitor::visit(KisGroupLayer *layer)
00224 {
00225     kdDebug(41008) << "Visiting on grouplayer " << layer->name() << "\n";
00226     KisLayerSP child = layer->firstChild();
00227     while (child) {
00228         child->accept(*this);
00229         child = child->nextSibling();
00230     }
00231     return true;
00232 }
00233 
00234 bool KisTIFFWriterVisitor::visit(KisPartLayer *)
00235 {
00236     return true;
00237 }
KDE Home | KDE Accessibility Home | Description of Access Keys