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