20#include "kis_tiff_converter.h"
29#include <tdeapplication.h>
30#include <KoDocumentInfo.h>
32#include <tdeio/netaccess.h>
34#include <kis_abstract_colorspace.h>
35#include <kis_colorspace_factory_registry.h>
38#include <kis_iterators_pixel.h>
40#include <kis_meta_registry.h>
41#include <kis_profile.h>
42#include <kis_group_layer.h>
43#include <kis_paint_layer.h>
45#include "kis_tiff_reader.h"
46#include "kis_tiff_ycbcr_reader.h"
47#include "kis_tiff_stream.h"
48#include "kis_tiff_writer_visitor.h"
52 TQString getColorSpaceForColorType(uint16 color_type, uint16 color_nb_bits, TIFF *image, uint16 &nbchannels, uint16 &extrasamplescount, uint8 &destDepth, uint16 sampletype) {
53 if(color_type == PHOTOMETRIC_MINISWHITE || color_type == PHOTOMETRIC_MINISBLACK)
55 if(nbchannels == 0) nbchannels = 1;
56 extrasamplescount = nbchannels - 1;
57 if(color_nb_bits <= 8)
65 }
else if(color_type == PHOTOMETRIC_RGB ) {
66 if(nbchannels == 0) nbchannels = 3;
67 extrasamplescount = nbchannels - 3;
68 if(sampletype == SAMPLEFORMAT_IEEEFP)
70 if(color_nb_bits == 16)
74 }
else if( color_nb_bits == 32) {
80 if(color_nb_bits <= 8)
89 }
else if(color_type == PHOTOMETRIC_YCBCR ) {
90 if(nbchannels == 0) nbchannels = 3;
91 extrasamplescount = nbchannels - 3;
92 if(color_nb_bits <= 8)
100 }
else if(color_type == PHOTOMETRIC_SEPARATED ) {
101 if(nbchannels == 0) nbchannels = 4;
104 if((TIFFGetField(image, TIFFTAG_INKSET, &inkset) == 0)){
105 kdDebug(41008) <<
"Image does not define the inkset." << endl;
108 if(inkset != INKSET_CMYK)
110 kdDebug(41008) <<
"Unsupported inkset (right now, only CMYK is supported)" << endl;
113 if( TIFFGetField(image, TIFFTAG_INKNAMES, &ink_names) && TIFFGetField(image, TIFFTAG_NUMBEROFINKS, &numberofinks) )
115 kdDebug(41008) <<
"Inks are : " << endl;
116 for(uint i = 0; i < numberofinks; i++)
118 kdDebug(41008) << ink_names[i] << endl;
121 kdDebug(41008) <<
"inknames aren't defined !" << endl;
123 if( nbchannels - extrasamplescount != 4)
129 if(color_nb_bits <= 8)
137 }
else if(color_type == PHOTOMETRIC_CIELAB
138#ifdef PHOTOMETRIC_ICCLAB
139 || color_type == PHOTOMETRIC_ICCLAB
143 if(nbchannels == 0) nbchannels = 3;
144 extrasamplescount = nbchannels - 3;
146 }
else if(color_type == PHOTOMETRIC_PALETTE) {
148 if(nbchannels == 0) nbchannels = 2;
149 extrasamplescount = nbchannels - 2;
157KisTIFFConverter::KisTIFFConverter(KisDoc *doc, KisUndoAdapter *adapter)
165KisTIFFConverter::~KisTIFFConverter()
169KisImageBuilder_Result KisTIFFConverter::decode(
const KURL& uri)
171 kdDebug(41008) <<
"Start decoding TIFF File" << endl;
174 if((image = TIFFOpen(TQFile::encodeName(uri.path()),
"r")) == NULL){
175 kdDebug(41008) <<
"Could not open the file, either it doesn't exist, either it is not a TIFF : " << uri.path() << endl;
177 return (KisImageBuilder_RESULT_BAD_FETCH);
180 kdDebug(41008) <<
"Read new sub-image" << endl;
181 KisImageBuilder_Result result = readTIFFDirectory(image);
182 if(result != KisImageBuilder_RESULT_OK){
185 }
while (TIFFReadDirectory(image));
188 return KisImageBuilder_RESULT_OK;
191KisImageBuilder_Result KisTIFFConverter::readTIFFDirectory( TIFF* image)
194 uint32 width, height;
195 if(TIFFGetField(image, TIFFTAG_IMAGEWIDTH, &width) == 0){
196 kdDebug(41008) <<
"Image does not define its width" << endl;
198 return KisImageBuilder_RESULT_INVALID_ARG;
200 if(TIFFGetField(image, TIFFTAG_IMAGELENGTH, &height) == 0){
201 kdDebug(41008) <<
"Image does not define its height" << endl;
203 return KisImageBuilder_RESULT_INVALID_ARG;
206 if((TIFFGetField(image, TIFFTAG_BITSPERSAMPLE, &depth) == 0)){
207 kdDebug(41008) <<
"Image does not define its depth" << endl;
211 if((TIFFGetField(image, TIFFTAG_SAMPLEFORMAT, &sampletype) == 0)){
212 kdDebug(41008) <<
"Image does not define its sample type" << endl;
213 sampletype = SAMPLEFORMAT_UINT;
217 if(TIFFGetField(image, TIFFTAG_SAMPLESPERPIXEL, &nbchannels) == 0){
218 kdDebug(41008) <<
"Image has an undefined number of samples per pixel" << endl;
222 uint16 *sampleinfo, extrasamplescount;
223 if(TIFFGetField(image, TIFFTAG_EXTRASAMPLES, &extrasamplescount, &sampleinfo) == 0)
225 extrasamplescount = 0;
229 if(TIFFGetField(image, TIFFTAG_PHOTOMETRIC, &color_type) == 0){
230 kdDebug(41008) <<
"Image has an undefined photometric interpretation" << endl;
231 color_type = PHOTOMETRIC_MINISWHITE;
234 TQString csName = getColorSpaceForColorType(color_type, depth, image, nbchannels, extrasamplescount, dstDepth,sampletype);
235 if(csName.isEmpty()) {
236 kdDebug(41008) <<
"Image has an unsupported colorspace : " << color_type <<
" for this depth : "<< depth << endl;
238 return KisImageBuilder_RESULT_UNSUPPORTED_COLORSPACE;
240 kdDebug(41008) <<
"Colorspace is : " << csName <<
" with a depth of " << depth <<
" and with a nb of channels of " << nbchannels << endl;
243 kdDebug() <<
"Reading profile" << endl;
244 KisProfile* profile = 0;
248 if (TIFFGetField(image, TIFFTAG_ICCPROFILE, &EmbedLen, &EmbedBuffer)) {
249 kdDebug(41008) <<
"Profile found" << endl;
251 rawdata.resize(EmbedLen);
252 memcpy(rawdata.data(), EmbedBuffer, EmbedLen);
253 profile =
new KisProfile(rawdata);
255 kdDebug(41008) <<
"No Profile found" << endl;
259 KisColorSpace* cs = 0;
260 if (profile && profile->isSuitableForOutput())
262 kdDebug(41008) <<
"image has embedded profile: " << profile -> productName() <<
"\n";
263 cs = KisMetaRegistry::instance()->csRegistry()->getColorSpace(csName, profile);
266 cs = KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID(csName,
""),
"");
269 kdDebug(41008) <<
"Colorspace " << csName <<
" is not available, please check your installation." << endl;
271 return KisImageBuilder_RESULT_UNSUPPORTED_COLORSPACE;
275 cmsHTRANSFORM transform = 0;
276 if(profile && !profile->isSuitableForOutput())
278 kdDebug(41008) <<
"The profile can't be used in chalk, need conversion" << endl;
279 transform = cmsCreateTransform(profile->profile(), cs->colorSpaceType(),
280 cs->getProfile()->profile() , cs->colorSpaceType(),
281 INTENT_PERCEPTUAL, 0);
288 kdDebug(41008) <<
"There are " << nbchannels <<
" channels and " << extrasamplescount <<
" extra channels" << endl;
291 for(
int i = 0; i < extrasamplescount; i ++)
293 kdDebug(41008) << i <<
" " << extrasamplescount <<
" " << (cs->nColorChannels()) << nbchannels <<
" " << sampleinfo[i] << endl;
294 if(sampleinfo[i] == EXTRASAMPLE_ASSOCALPHA)
301 if (sampleinfo[i] == EXTRASAMPLE_UNASSALPHA)
310 KoDocumentInfo * info = m_doc->documentInfo();
311 KoDocumentInfoAbout * aboutPage =
static_cast<KoDocumentInfoAbout *
>(info->page(
"about" ));
312 KoDocumentInfoAuthor * authorPage =
static_cast<KoDocumentInfoAuthor *
>(info->page(
"author"));
314 if (TIFFGetField(image, TIFFTAG_ARTIST, &text)) {
315 authorPage->setFullName(text);
317 if (TIFFGetField(image, TIFFTAG_DOCUMENTNAME, &text)) {
318 aboutPage->setTitle(text);
320 if (TIFFGetField(image,TIFFTAG_IMAGEDESCRIPTION,&text) ) {
321 aboutPage->setAbstract( text );
327 if(TIFFGetField(image, TIFFTAG_PLANARCONFIG, &planarconfig) == 0)
329 kdDebug(41008) <<
"Plannar configuration is not define" << endl;
331 return KisImageBuilder_RESULT_INVALID_ARG;
335 m_img =
new KisImage(m_doc->undoAdapter(), width, height, cs,
"built image");
337 m_img->blockSignals(
true);
340 m_img -> addAnnotation( profile->annotation() );
343 if( m_img->width() < (TQ_INT32)width || m_img->height() < (TQ_INT32)height)
345 TQ_UINT32 newwidth = (m_img->width() < (TQ_INT32)width) ? width : m_img->width();
346 TQ_UINT32 newheight = (m_img->height() < (TQ_INT32)height) ? height : m_img->height();
347 m_img->resize(newwidth, newheight,
false);
350 KisPaintLayer* layer =
new KisPaintLayer(m_img, m_img -> nextLayerName(), TQ_UINT8_MAX);
353 TIFFStreamBase* tiffstream;
355 KisTIFFReaderBase* tiffReader = 0;
358 KisTIFFPostProcessor* postprocessor = 0;
361 uint8 nbcolorsamples = nbchannels - extrasamplescount;
364 case PHOTOMETRIC_MINISWHITE:
366 poses[0] = 0; poses[1] = 1;
367 postprocessor =
new KisTIFFPostProcessorInvert(nbcolorsamples);
370 case PHOTOMETRIC_MINISBLACK:
372 poses[0] = 0; poses[1] = 1;
373 postprocessor =
new KisTIFFPostProcessor(nbcolorsamples);
376 case PHOTOMETRIC_CIELAB:
378 poses[0] = 0; poses[1] = 1; poses[2] = 2; poses[3] = 3;
379 postprocessor =
new KisTIFFPostProcessorICCLABtoCIELAB(nbcolorsamples);
382#ifdef PHOTOMETRIC_ICCLAB
383 case PHOTOMETRIC_ICCLAB:
385 poses[0] = 0; poses[1] = 1; poses[2] = 2; poses[3] = 3;
386 postprocessor =
new KisTIFFPostProcessor(nbcolorsamples);
390 case PHOTOMETRIC_RGB:
392 poses[0] = 2; poses[1] = 1; poses[2] = 0; poses[3] = 3;
393 postprocessor =
new KisTIFFPostProcessor(nbcolorsamples);
396 case PHOTOMETRIC_SEPARATED:
398 poses[0] = 0; poses[1] = 1; poses[2] = 2; poses[3] = 3; poses[4] = 4;
399 postprocessor =
new KisTIFFPostProcessor(nbcolorsamples);
408 uint16 * lineSizeCoeffs =
new uint16[nbchannels];
409 uint16 vsubsampling = 1;
410 uint16 hsubsampling = 1;
411 for(uint i = 0; i < nbchannels; i++)
413 lineSizeCoeffs[i] = 1;
415 if( color_type == PHOTOMETRIC_PALETTE)
420 if ((TIFFGetField(image, TIFFTAG_COLORMAP, &red, &green, &blue)) == 0)
422 kdDebug(41008) <<
"Indexed image does not define a palette" << endl;
424 return KisImageBuilder_RESULT_INVALID_ARG;
427 tiffReader =
new KisTIFFReaderFromPalette( layer->paintDevice(), red, green, blue, poses, alphapos, depth, nbcolorsamples, extrasamplescount, transform, postprocessor);
428 }
else if(color_type == PHOTOMETRIC_YCBCR ) {
429 TIFFGetFieldDefaulted( image, TIFFTAG_YCBCRSUBSAMPLING, &hsubsampling, &vsubsampling );
430 lineSizeCoeffs[1] = hsubsampling;
431 lineSizeCoeffs[2] = hsubsampling;
433 TIFFGetFieldDefaulted( image, TIFFTAG_YCBCRPOSITIONING, &position );
436 tiffReader =
new KisTIFFYCbCrReaderTarget8Bit(layer->paintDevice(), poses, alphapos, depth, nbcolorsamples, extrasamplescount, transform, postprocessor, hsubsampling, vsubsampling, (KisTIFFYCbCr::Position)position);
437 }
else if( dstDepth == 16 )
439 tiffReader =
new KisTIFFYCbCrReaderTarget16Bit( layer->paintDevice(), poses, alphapos, depth, nbcolorsamples, extrasamplescount, transform, postprocessor, hsubsampling, vsubsampling, (KisTIFFYCbCr::Position)position);
441 }
else if(dstDepth == 8)
443 tiffReader =
new KisTIFFReaderTarget8bit( layer->paintDevice(), poses, alphapos, depth, nbcolorsamples, extrasamplescount, transform, postprocessor);
444 }
else if(dstDepth == 16) {
445 tiffReader =
new KisTIFFReaderTarget16bit( layer->paintDevice(), poses, alphapos, depth, nbcolorsamples, extrasamplescount, transform, postprocessor);
446 }
else if(dstDepth == 32) {
447 tiffReader =
new KisTIFFReaderTarget32bit( layer->paintDevice(), poses, alphapos, depth, nbcolorsamples, extrasamplescount, transform, postprocessor);
450 if(TIFFIsTiled(image))
452 kdDebug(41008) <<
"tiled image" << endl;
453 uint32 tileWidth, tileHeight;
455 TIFFGetField(image, TIFFTAG_TILEWIDTH, &tileWidth);
456 TIFFGetField(image, TIFFTAG_TILELENGTH, &tileHeight);
457 uint32 linewidth = (tileWidth * depth * nbchannels) / 8;
458 if(planarconfig == PLANARCONFIG_CONTIG)
460 buf = _TIFFmalloc(TIFFTileSize(image));
463 tiffstream =
new TIFFStreamContigBelow16((uint8*)buf, depth, linewidth);
464 }
else if(depth < 32)
466 tiffstream =
new TIFFStreamContigBelow32((uint8*)buf, depth, linewidth);
468 tiffstream =
new TIFFStreamContigAbove32((uint8*)buf, depth, linewidth);
471 ps_buf =
new tdata_t[nbchannels];
472 uint32 * lineSizes =
new uint32[nbchannels];
473 uint16 baseSize = TIFFTileSize(image)/nbchannels;
474 for(uint i = 0; i < nbchannels; i++)
476 ps_buf[i] = _TIFFmalloc(baseSize);
477 lineSizes[i] = baseSize / lineSizeCoeffs[i];
479 tiffstream =
new TIFFStreamSeperate( (uint8**) ps_buf, nbchannels, depth, lineSizes);
482 kdDebug(41008) << linewidth <<
" " << nbchannels <<
" " << layer->paintDevice()->colorSpace()->nColorChannels() << endl;
483 for (y = 0; y < height; y+= tileHeight)
485 for (x = 0; x < width; x += tileWidth)
487 kdDebug(41008) <<
"Reading tile x = " << x <<
" y = " << y << endl;
488 if( planarconfig == PLANARCONFIG_CONTIG )
490 TIFFReadTile(image, buf, x, y, 0, (tsample_t) -1);
492 for(uint i = 0; i < nbchannels; i++)
494 TIFFReadTile(image, ps_buf[i], x, y, 0, i);
497 uint32 realTileWidth = (x + tileWidth) < width ? tileWidth : width - x;
498 for (uint yintile = 0; y + yintile < height && yintile < tileHeight/vsubsampling; ) {
499 tiffReader->copyDataToChannels( x, y + yintile , realTileWidth, tiffstream);
501 tiffstream->moveToLine( yintile );
503 tiffstream->restart();
507 kdDebug(41008) <<
"striped image" << endl;
508 tsize_t stripsize = TIFFStripSize(image);
510 TIFFGetFieldDefaulted(image, TIFFTAG_ROWSPERSTRIP, &rowsPerStrip);
511 kdDebug() << rowsPerStrip <<
" " << height << endl;
512 rowsPerStrip = TQMIN(rowsPerStrip, height);
513 if(planarconfig == PLANARCONFIG_CONTIG)
515 buf = _TIFFmalloc(stripsize);
518 tiffstream =
new TIFFStreamContigBelow16((uint8*)buf, depth, stripsize/rowsPerStrip);
519 }
else if(depth < 32)
521 tiffstream =
new TIFFStreamContigBelow32((uint8*)buf, depth, stripsize/rowsPerStrip);
523 tiffstream =
new TIFFStreamContigAbove32((uint8*)buf, depth, stripsize/rowsPerStrip);
526 ps_buf =
new tdata_t[nbchannels];
527 uint32 scanLineSize = stripsize/rowsPerStrip;
528 kdDebug(41008) <<
" scanLineSize for each plan = " << scanLineSize << endl;
529 uint32 * lineSizes =
new uint32[nbchannels];
530 for(uint i = 0; i < nbchannels; i++)
532 ps_buf[i] = _TIFFmalloc(stripsize);
533 lineSizes[i] = scanLineSize / lineSizeCoeffs[i];
535 tiffstream =
new TIFFStreamSeperate( (uint8**) ps_buf, nbchannels, depth, lineSizes);
539 kdDebug(41008) <<
"Scanline size = " << TIFFRasterScanlineSize(image) <<
" / strip size = " << TIFFStripSize(image) <<
" / rowsPerStrip = " << rowsPerStrip <<
" stripsize/rowsPerStrip = " << stripsize/rowsPerStrip << endl;
541 kdDebug(41008) <<
" NbOfStrips = " << TIFFNumberOfStrips(image) <<
" rowsPerStrip = " << rowsPerStrip <<
" stripsize = " << stripsize << endl;
542 for (uint32 strip = 0; y < height; strip++)
544 if( planarconfig == PLANARCONFIG_CONTIG )
546 TIFFReadEncodedStrip(image, TIFFComputeStrip( image, y, 0 ) , buf, (tsize_t) -1);
548 for(uint i = 0; i < nbchannels; i++)
550 TIFFReadEncodedStrip(image, TIFFComputeStrip( image, y, i ), ps_buf[i], (tsize_t) -1);
553 for( uint32 yinstrip = 0 ; yinstrip < rowsPerStrip && y < height ; )
555 uint linesread = tiffReader->copyDataToChannels( 0, y, width, tiffstream);
557 yinstrip += linesread;
558 tiffstream->moveToLine( yinstrip );
560 tiffstream->restart();
563 tiffReader->finalize();
564 delete lineSizeCoeffs;
567 if( planarconfig == PLANARCONFIG_CONTIG )
571 for(uint i = 0; i < nbchannels; i++)
573 _TIFFfree(ps_buf[i]);
578 m_img->addLayer(layer, m_img->rootLayer(), 0);
579 return KisImageBuilder_RESULT_OK;
582KisImageBuilder_Result KisTIFFConverter::buildImage(
const KURL& uri)
585 return KisImageBuilder_RESULT_NO_URI;
587 if (!TDEIO::NetAccess::exists(uri,
false, tqApp -> mainWidget())) {
588 return KisImageBuilder_RESULT_NOT_EXIST;
592 KisImageBuilder_Result result = KisImageBuilder_RESULT_FAILURE;
595 if (TDEIO::NetAccess::download(uri, tmpFile, tqApp -> mainWidget())) {
597 uriTF.setPath( tmpFile );
598 result = decode(uriTF);
599 TDEIO::NetAccess::removeTempFile(tmpFile);
606KisImageSP KisTIFFConverter::image()
612KisImageBuilder_Result KisTIFFConverter::buildFile(
const KURL& uri, KisImageSP img, KisTIFFOptions options)
614 kdDebug(41008) <<
"Start writing TIFF File" << endl;
616 return KisImageBuilder_RESULT_EMPTY;
619 return KisImageBuilder_RESULT_NO_URI;
621 if (!uri.isLocalFile())
622 return KisImageBuilder_RESULT_NOT_LOCAL;
626 if((image = TIFFOpen(TQFile::encodeName(uri.path()),
"w")) == NULL){
627 kdDebug(41008) <<
"Could not open the file for writting " << uri.path() << endl;
629 return (KisImageBuilder_RESULT_FAILURE);
633 KoDocumentInfo * info = m_doc->documentInfo();
634 KoDocumentInfoAbout * aboutPage =
static_cast<KoDocumentInfoAbout *
>(info->page(
"about" ));
635 TQString title = aboutPage->title();
638 TIFFSetField(image, TIFFTAG_DOCUMENTNAME, title.ascii());
640 TQString abstract = aboutPage->abstract();
641 if(!abstract.isEmpty())
643 TIFFSetField(image, TIFFTAG_IMAGEDESCRIPTION, abstract.ascii());
645 KoDocumentInfoAuthor * authorPage =
static_cast<KoDocumentInfoAuthor *
>(info->page(
"author" ));
646 TQString author = authorPage->fullName();
647 if(!author.isEmpty())
649 TIFFSetField(image, TIFFTAG_ARTIST, author.ascii());
652 KisTIFFWriterVisitor* visitor =
new KisTIFFWriterVisitor(image, &options);
653 KisGroupLayer* root =
dynamic_cast<KisGroupLayer*
>(img->rootLayer().data());
658 return KisImageBuilder_RESULT_FAILURE;
660 if(!visitor->visit( root ))
664 return KisImageBuilder_RESULT_FAILURE;
668 return KisImageBuilder_RESULT_OK;
672void KisTIFFConverter::cancel()
677#include "kis_tiff_converter.moc"