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