kis_tiff_converter.cpp
1/*
2 * Copyright (c) 2005-2006 Cyrille Berger <cberger@cberger.net>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20#include "kis_tiff_converter.h"
21
22#include <stdio.h>
23
24#include <config.h>
25#include LCMS_HEADER
26
27#include <tqfile.h>
28
29#include <tdeapplication.h>
30#include <KoDocumentInfo.h>
31
32#include <tdeio/netaccess.h>
33
34#include <kis_abstract_colorspace.h>
35#include <kis_colorspace_factory_registry.h>
36#include <kis_doc.h>
37#include <kis_image.h>
38#include <kis_iterators_pixel.h>
39#include <kis_layer.h>
40#include <kis_meta_registry.h>
41#include <kis_profile.h>
42#include <kis_group_layer.h>
43#include <kis_paint_layer.h>
44
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"
49
50namespace {
51
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)
54 {
55 if(nbchannels == 0) nbchannels = 1;
56 extrasamplescount = nbchannels - 1; // FIX the extrasamples count in case of
57 if(color_nb_bits <= 8)
58 {
59 destDepth = 8;
60 return "GRAYA";
61 } else {
62 destDepth = 16;
63 return "GRAYA16";
64 }
65 } else if(color_type == PHOTOMETRIC_RGB /*|| color_type == */ ) {
66 if(nbchannels == 0) nbchannels = 3;
67 extrasamplescount = nbchannels - 3; // FIX the extrasamples count in case of
68 if(sampletype == SAMPLEFORMAT_IEEEFP)
69 {
70 if(color_nb_bits == 16)
71 {
72 destDepth = 16;
73 return "RGBAF16HALF";
74 } else if( color_nb_bits == 32) {
75 destDepth = 32;
76 return "RGBAF32";
77 }
78 return "";
79 } else {
80 if(color_nb_bits <= 8)
81 {
82 destDepth = 8;
83 return "RGBA";
84 } else {
85 destDepth = 16;
86 return "RGBA16";
87 }
88 }
89 } else if(color_type == PHOTOMETRIC_YCBCR ) {
90 if(nbchannels == 0) nbchannels = 3;
91 extrasamplescount = nbchannels - 3; // FIX the extrasamples count in case of
92 if(color_nb_bits <= 8)
93 {
94 destDepth = 8;
95 return "YCbCrAU8";
96 } else {
97 destDepth = 16;
98 return "YCbCrAU16";
99 }
100 } else if(color_type == PHOTOMETRIC_SEPARATED ) {
101 if(nbchannels == 0) nbchannels = 4;
102 // SEPARATED is in general CMYK but not allways, so we check
103 uint16 inkset;
104 if((TIFFGetField(image, TIFFTAG_INKSET, &inkset) == 0)){
105 kdDebug(41008) << "Image does not define the inkset." << endl;
106 inkset = 2;
107 }
108 if(inkset != INKSET_CMYK)
109 {
110 kdDebug(41008) << "Unsupported inkset (right now, only CMYK is supported)" << endl;
111 char** ink_names;
112 uint16 numberofinks;
113 if( TIFFGetField(image, TIFFTAG_INKNAMES, &ink_names) && TIFFGetField(image, TIFFTAG_NUMBEROFINKS, &numberofinks) )
114 {
115 kdDebug(41008) << "Inks are : " << endl;
116 for(uint i = 0; i < numberofinks; i++)
117 {
118 kdDebug(41008) << ink_names[i] << endl;
119 }
120 } else {
121 kdDebug(41008) << "inknames aren't defined !" << endl;
122 // To be able to read stupid adobe files, if there are no information about inks and four channels, then it's a CMYK file :
123 if( nbchannels - extrasamplescount != 4)
124 {
125 return "";
126 }
127 }
128 }
129 if(color_nb_bits <= 8)
130 {
131 destDepth = 8;
132 return "CMYK";
133 } else {
134 destDepth = 16;
135 return "CMYKA16";
136 }
137 } else if(color_type == PHOTOMETRIC_CIELAB
138#ifdef PHOTOMETRIC_ICCLAB
139 || color_type == PHOTOMETRIC_ICCLAB
140#endif
141 ) {
142 destDepth = 16;
143 if(nbchannels == 0) nbchannels = 3;
144 extrasamplescount = nbchannels - 3; // FIX the extrasamples count in case of
145 return "LABA"; // TODO add support for a 8bit LAB colorspace when it is written
146 } else if(color_type == PHOTOMETRIC_PALETTE) {
147 destDepth = 16;
148 if(nbchannels == 0) nbchannels = 2;
149 extrasamplescount = nbchannels - 2; // FIX the extrasamples count in case of
150 // <-- we will convert the index image to RGBA16 as the palette is allways on 16bits colors
151 return "RGBA16";
152 }
153 return "";
154 }
155}
156
157KisTIFFConverter::KisTIFFConverter(KisDoc *doc, KisUndoAdapter *adapter)
158{
159 m_doc = doc;
160 m_adapter = adapter;
161 m_job = 0;
162 m_stop = false;
163}
164
165KisTIFFConverter::~KisTIFFConverter()
166{
167}
168
169KisImageBuilder_Result KisTIFFConverter::decode(const KURL& uri)
170{
171 kdDebug(41008) << "Start decoding TIFF File" << endl;
172 // Opent the TIFF file
173 TIFF *image = 0;
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;
176
177 return (KisImageBuilder_RESULT_BAD_FETCH);
178 }
179 do {
180 kdDebug(41008) << "Read new sub-image" << endl;
181 KisImageBuilder_Result result = readTIFFDirectory(image);
182 if(result != KisImageBuilder_RESULT_OK){
183 return result;
184 }
185 } while (TIFFReadDirectory(image));
186 // Freeing memory
187 TIFFClose(image);
188 return KisImageBuilder_RESULT_OK;
189}
190
191KisImageBuilder_Result KisTIFFConverter::readTIFFDirectory( TIFF* image)
192{
193 // Read information about the tiff
194 uint32 width, height;
195 if(TIFFGetField(image, TIFFTAG_IMAGEWIDTH, &width) == 0){
196 kdDebug(41008) << "Image does not define its width" << endl;
197 TIFFClose(image);
198 return KisImageBuilder_RESULT_INVALID_ARG;
199 }
200 if(TIFFGetField(image, TIFFTAG_IMAGELENGTH, &height) == 0){
201 kdDebug(41008) << "Image does not define its height" << endl;
202 TIFFClose(image);
203 return KisImageBuilder_RESULT_INVALID_ARG;
204 }
205 uint16 depth;
206 if((TIFFGetField(image, TIFFTAG_BITSPERSAMPLE, &depth) == 0)){
207 kdDebug(41008) << "Image does not define its depth" << endl;
208 depth = 1;
209 }
210 uint16 sampletype;
211 if((TIFFGetField(image, TIFFTAG_SAMPLEFORMAT, &sampletype) == 0)){
212 kdDebug(41008) << "Image does not define its sample type" << endl;
213 sampletype = SAMPLEFORMAT_UINT;
214 }
215 // Determine the number of channels (usefull to know if a file has an alpha or not
216 uint16 nbchannels;
217 if(TIFFGetField(image, TIFFTAG_SAMPLESPERPIXEL, &nbchannels) == 0){
218 kdDebug(41008) << "Image has an undefined number of samples per pixel" << endl;
219 nbchannels = 0;
220 }
221 // Get the number of extrasamples and information about them
222 uint16 *sampleinfo, extrasamplescount;
223 if(TIFFGetField(image, TIFFTAG_EXTRASAMPLES, &extrasamplescount, &sampleinfo) == 0)
224 {
225 extrasamplescount = 0;
226 }
227 // Determine the colorspace
228 uint16 color_type;
229 if(TIFFGetField(image, TIFFTAG_PHOTOMETRIC, &color_type) == 0){
230 kdDebug(41008) << "Image has an undefined photometric interpretation" << endl;
231 color_type = PHOTOMETRIC_MINISWHITE;
232 }
233 uint8 dstDepth;
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;
237 TIFFClose(image);
238 return KisImageBuilder_RESULT_UNSUPPORTED_COLORSPACE;
239 }
240 kdDebug(41008) << "Colorspace is : " << csName << " with a depth of " << depth << " and with a nb of channels of " << nbchannels << endl;
241
242 // Read image profile
243 kdDebug() << "Reading profile" << endl;
244 KisProfile* profile = 0;
245 DWORD EmbedLen;
246 LPBYTE EmbedBuffer;
247
248 if (TIFFGetField(image, TIFFTAG_ICCPROFILE, &EmbedLen, &EmbedBuffer)) {
249 kdDebug(41008) << "Profile found" << endl;
250 TQByteArray rawdata;
251 rawdata.resize(EmbedLen);
252 memcpy(rawdata.data(), EmbedBuffer, EmbedLen);
253 profile = new KisProfile(rawdata);
254 } else {
255 kdDebug(41008) << "No Profile found" << endl;
256 }
257
258 // Retrieve a pointer to the colorspace
259 KisColorSpace* cs = 0;
260 if (profile && profile->isSuitableForOutput())
261 {
262 kdDebug(41008) << "image has embedded profile: " << profile -> productName() << "\n";
263 cs = KisMetaRegistry::instance()->csRegistry()->getColorSpace(csName, profile);
264 }
265 else
266 cs = KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID(csName,""),"");
267
268 if(cs == 0) {
269 kdDebug(41008) << "Colorspace " << csName << " is not available, please check your installation." << endl;
270 TIFFClose(image);
271 return KisImageBuilder_RESULT_UNSUPPORTED_COLORSPACE;
272 }
273
274 // Create the cmsTransform if needed
275 cmsHTRANSFORM transform = 0;
276 if(profile && !profile->isSuitableForOutput())
277 {
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);
282 }
283
284
285 // Check if there is an alpha channel
286 int8 alphapos = -1; // <- no alpha
287 // Check which extra is alpha if any
288 kdDebug(41008) << "There are " << nbchannels << " channels and " << extrasamplescount << " extra channels" << endl;
289 if(sampleinfo) // index images don't have any sampleinfo, and therefor sampleinfo == 0
290 {
291 for(int i = 0; i < extrasamplescount; i ++)
292 {
293 kdDebug(41008) << i << " " << extrasamplescount << " " << (cs->nColorChannels()) << nbchannels << " " << sampleinfo[i] << endl;
294 if(sampleinfo[i] == EXTRASAMPLE_ASSOCALPHA)
295 {
296 // XXX: dangelo: the color values are already multiplied with
297 // the alpha value. This needs to be reversed later (postprocessor?)
298 alphapos = i;
299 }
300
301 if (sampleinfo[i] == EXTRASAMPLE_UNASSALPHA)
302 {
303 // color values are not premultiplied with alpha, and can be used as they are.
304 alphapos = i;
305 }
306 }
307 }
308
309 // Read META Information
310 KoDocumentInfo * info = m_doc->documentInfo();
311 KoDocumentInfoAbout * aboutPage = static_cast<KoDocumentInfoAbout *>(info->page( "about" ));
312 KoDocumentInfoAuthor * authorPage = static_cast<KoDocumentInfoAuthor *>(info->page( "author"));
313 char* text;
314 if (TIFFGetField(image, TIFFTAG_ARTIST, &text)) {
315 authorPage->setFullName(text);
316 }
317 if (TIFFGetField(image, TIFFTAG_DOCUMENTNAME, &text)) {
318 aboutPage->setTitle(text);
319 }
320 if (TIFFGetField(image,TIFFTAG_IMAGEDESCRIPTION,&text) ) {
321 aboutPage->setAbstract( text );
322 }
323
324
325 // Get the planar configuration
326 uint16 planarconfig;
327 if(TIFFGetField(image, TIFFTAG_PLANARCONFIG, &planarconfig) == 0)
328 {
329 kdDebug(41008) << "Plannar configuration is not define" << endl;
330 TIFFClose(image);
331 return KisImageBuilder_RESULT_INVALID_ARG;
332 }
333 // Creating the KisImageSP
334 if( ! m_img ) {
335 m_img = new KisImage(m_doc->undoAdapter(), width, height, cs, "built image");
336 TQ_CHECK_PTR(m_img);
337 m_img->blockSignals(true); // Don't send out signals while we're building the image
338 if(profile)
339 {
340 m_img -> addAnnotation( profile->annotation() );
341 }
342 } else {
343 if( m_img->width() < (TQ_INT32)width || m_img->height() < (TQ_INT32)height)
344 {
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);
348 }
349 }
350 KisPaintLayer* layer = new KisPaintLayer(m_img, m_img -> nextLayerName(), TQ_UINT8_MAX);
351 tdata_t buf = 0;
352 tdata_t* ps_buf = 0; // used only for planar configuration seperated
353 TIFFStreamBase* tiffstream;
354
355 KisTIFFReaderBase* tiffReader = 0;
356
357 TQ_UINT8 poses[5];
358 KisTIFFPostProcessor* postprocessor = 0;
359
360 // Configure poses
361 uint8 nbcolorsamples = nbchannels - extrasamplescount;
362 switch(color_type)
363 {
364 case PHOTOMETRIC_MINISWHITE:
365 {
366 poses[0] = 0; poses[1] = 1;
367 postprocessor = new KisTIFFPostProcessorInvert(nbcolorsamples);
368 }
369 break;
370 case PHOTOMETRIC_MINISBLACK:
371 {
372 poses[0] = 0; poses[1] = 1;
373 postprocessor = new KisTIFFPostProcessor(nbcolorsamples);
374 }
375 break;
376 case PHOTOMETRIC_CIELAB:
377 {
378 poses[0] = 0; poses[1] = 1; poses[2] = 2; poses[3] = 3;
379 postprocessor = new KisTIFFPostProcessorICCLABtoCIELAB(nbcolorsamples);
380 }
381 break;
382#ifdef PHOTOMETRIC_ICCLAB
383 case PHOTOMETRIC_ICCLAB:
384 {
385 poses[0] = 0; poses[1] = 1; poses[2] = 2; poses[3] = 3;
386 postprocessor = new KisTIFFPostProcessor(nbcolorsamples);
387 }
388 break;
389#endif
390 case PHOTOMETRIC_RGB:
391 {
392 poses[0] = 2; poses[1] = 1; poses[2] = 0; poses[3] = 3;
393 postprocessor = new KisTIFFPostProcessor(nbcolorsamples);
394 }
395 break;
396 case PHOTOMETRIC_SEPARATED:
397 {
398 poses[0] = 0; poses[1] = 1; poses[2] = 2; poses[3] = 3; poses[4] = 4;
399 postprocessor = new KisTIFFPostProcessor(nbcolorsamples);
400 }
401 break;
402 default:
403 break;
404 }
405
406
407 // Initisalize tiffReader
408 uint16 * lineSizeCoeffs = new uint16[nbchannels];
409 uint16 vsubsampling = 1;
410 uint16 hsubsampling = 1;
411 for(uint i = 0; i < nbchannels; i++)
412 {
413 lineSizeCoeffs[i] = 1;
414 }
415 if( color_type == PHOTOMETRIC_PALETTE)
416 {
417 uint16 *red; // No need to free them they are free by libtiff
418 uint16 *green;
419 uint16 *blue;
420 if ((TIFFGetField(image, TIFFTAG_COLORMAP, &red, &green, &blue)) == 0)
421 {
422 kdDebug(41008) << "Indexed image does not define a palette" << endl;
423 TIFFClose(image);
424 return KisImageBuilder_RESULT_INVALID_ARG;
425 }
426
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;
432 uint16 position;
433 TIFFGetFieldDefaulted( image, TIFFTAG_YCBCRPOSITIONING, &position );
434 if( dstDepth == 8 )
435 {
436 tiffReader = new KisTIFFYCbCrReaderTarget8Bit(layer->paintDevice(), poses, alphapos, depth, nbcolorsamples, extrasamplescount, transform, postprocessor, hsubsampling, vsubsampling, (KisTIFFYCbCr::Position)position);
437 } else if( dstDepth == 16 )
438 {
439 tiffReader = new KisTIFFYCbCrReaderTarget16Bit( layer->paintDevice(), poses, alphapos, depth, nbcolorsamples, extrasamplescount, transform, postprocessor, hsubsampling, vsubsampling, (KisTIFFYCbCr::Position)position);
440 }
441 } else if(dstDepth == 8)
442 {
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);
448 }
449
450 if(TIFFIsTiled(image))
451 {
452 kdDebug(41008) << "tiled image" << endl;
453 uint32 tileWidth, tileHeight;
454 uint32 x, y;
455 TIFFGetField(image, TIFFTAG_TILEWIDTH, &tileWidth);
456 TIFFGetField(image, TIFFTAG_TILELENGTH, &tileHeight);
457 uint32 linewidth = (tileWidth * depth * nbchannels) / 8;
458 if(planarconfig == PLANARCONFIG_CONTIG)
459 {
460 buf = _TIFFmalloc(TIFFTileSize(image));
461 if(depth < 16)
462 {
463 tiffstream = new TIFFStreamContigBelow16((uint8*)buf, depth, linewidth);
464 } else if(depth < 32)
465 {
466 tiffstream = new TIFFStreamContigBelow32((uint8*)buf, depth, linewidth);
467 } else {
468 tiffstream = new TIFFStreamContigAbove32((uint8*)buf, depth, linewidth);
469 }
470 } else {
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++)
475 {
476 ps_buf[i] = _TIFFmalloc(baseSize);
477 lineSizes[i] = baseSize / lineSizeCoeffs[i];
478 }
479 tiffstream = new TIFFStreamSeperate( (uint8**) ps_buf, nbchannels, depth, lineSizes);
480 delete [] lineSizes;
481 }
482 kdDebug(41008) << linewidth << " " << nbchannels << " " << layer->paintDevice()->colorSpace()->nColorChannels() << endl;
483 for (y = 0; y < height; y+= tileHeight)
484 {
485 for (x = 0; x < width; x += tileWidth)
486 {
487 kdDebug(41008) << "Reading tile x = " << x << " y = " << y << endl;
488 if( planarconfig == PLANARCONFIG_CONTIG )
489 {
490 TIFFReadTile(image, buf, x, y, 0, (tsample_t) -1);
491 } else {
492 for(uint i = 0; i < nbchannels; i++)
493 {
494 TIFFReadTile(image, ps_buf[i], x, y, 0, i);
495 }
496 }
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);
500 yintile += 1;
501 tiffstream->moveToLine( yintile );
502 }
503 tiffstream->restart();
504 }
505 }
506 } else {
507 kdDebug(41008) << "striped image" << endl;
508 tsize_t stripsize = TIFFStripSize(image);
509 uint32 rowsPerStrip;
510 TIFFGetFieldDefaulted(image, TIFFTAG_ROWSPERSTRIP, &rowsPerStrip);
511 kdDebug() << rowsPerStrip << " " << height << endl;
512 rowsPerStrip = TQMIN(rowsPerStrip, height); // when TIFFNumberOfStrips(image) == 1 it might happen that rowsPerStrip is incorrectly set
513 if(planarconfig == PLANARCONFIG_CONTIG)
514 {
515 buf = _TIFFmalloc(stripsize);
516 if(depth < 16)
517 {
518 tiffstream = new TIFFStreamContigBelow16((uint8*)buf, depth, stripsize/rowsPerStrip);
519 } else if(depth < 32)
520 {
521 tiffstream = new TIFFStreamContigBelow32((uint8*)buf, depth, stripsize/rowsPerStrip);
522 } else {
523 tiffstream = new TIFFStreamContigAbove32((uint8*)buf, depth, stripsize/rowsPerStrip);
524 }
525 } else {
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++)
531 {
532 ps_buf[i] = _TIFFmalloc(stripsize);
533 lineSizes[i] = scanLineSize / lineSizeCoeffs[i];
534 }
535 tiffstream = new TIFFStreamSeperate( (uint8**) ps_buf, nbchannels, depth, lineSizes);
536 delete [] lineSizes;
537 }
538
539 kdDebug(41008) << "Scanline size = " << TIFFRasterScanlineSize(image) << " / strip size = " << TIFFStripSize(image) << " / rowsPerStrip = " << rowsPerStrip << " stripsize/rowsPerStrip = " << stripsize/rowsPerStrip << endl;
540 uint32 y = 0;
541 kdDebug(41008) << " NbOfStrips = " << TIFFNumberOfStrips(image) << " rowsPerStrip = " << rowsPerStrip << " stripsize = " << stripsize << endl;
542 for (uint32 strip = 0; y < height; strip++)
543 {
544 if( planarconfig == PLANARCONFIG_CONTIG )
545 {
546 TIFFReadEncodedStrip(image, TIFFComputeStrip( image, y, 0 ) , buf, (tsize_t) -1);
547 } else {
548 for(uint i = 0; i < nbchannels; i++)
549 {
550 TIFFReadEncodedStrip(image, TIFFComputeStrip( image, y, i ), ps_buf[i], (tsize_t) -1);
551 }
552 }
553 for( uint32 yinstrip = 0 ; yinstrip < rowsPerStrip && y < height ; )
554 {
555 uint linesread = tiffReader->copyDataToChannels( 0, y, width, tiffstream);
556 y += linesread;
557 yinstrip += linesread;
558 tiffstream->moveToLine( yinstrip );
559 }
560 tiffstream->restart();
561 }
562 }
563 tiffReader->finalize();
564 delete lineSizeCoeffs;
565 delete tiffReader;
566 delete tiffstream;
567 if( planarconfig == PLANARCONFIG_CONTIG )
568 {
569 _TIFFfree(buf);
570 } else {
571 for(uint i = 0; i < nbchannels; i++)
572 {
573 _TIFFfree(ps_buf[i]);
574 }
575 delete[] ps_buf;
576 }
577
578 m_img->addLayer(layer, m_img->rootLayer(), 0);
579 return KisImageBuilder_RESULT_OK;
580}
581
582KisImageBuilder_Result KisTIFFConverter::buildImage(const KURL& uri)
583{
584 if (uri.isEmpty())
585 return KisImageBuilder_RESULT_NO_URI;
586
587 if (!TDEIO::NetAccess::exists(uri, false, tqApp -> mainWidget())) {
588 return KisImageBuilder_RESULT_NOT_EXIST;
589 }
590
591 // We're not set up to handle asynchronous loading at the moment.
592 KisImageBuilder_Result result = KisImageBuilder_RESULT_FAILURE;
593 TQString tmpFile;
594
595 if (TDEIO::NetAccess::download(uri, tmpFile, tqApp -> mainWidget())) {
596 KURL uriTF;
597 uriTF.setPath( tmpFile );
598 result = decode(uriTF);
599 TDEIO::NetAccess::removeTempFile(tmpFile);
600 }
601
602 return result;
603}
604
605
606KisImageSP KisTIFFConverter::image()
607{
608 return m_img;
609}
610
611
612KisImageBuilder_Result KisTIFFConverter::buildFile(const KURL& uri, KisImageSP img, KisTIFFOptions options)
613{
614 kdDebug(41008) << "Start writing TIFF File" << endl;
615 if (!img)
616 return KisImageBuilder_RESULT_EMPTY;
617
618 if (uri.isEmpty())
619 return KisImageBuilder_RESULT_NO_URI;
620
621 if (!uri.isLocalFile())
622 return KisImageBuilder_RESULT_NOT_LOCAL;
623
624 // Open file for writing
625 TIFF *image;
626 if((image = TIFFOpen(TQFile::encodeName(uri.path()), "w")) == NULL){
627 kdDebug(41008) << "Could not open the file for writting " << uri.path() << endl;
628 TIFFClose(image);
629 return (KisImageBuilder_RESULT_FAILURE);
630 }
631
632 // Set the document informations
633 KoDocumentInfo * info = m_doc->documentInfo();
634 KoDocumentInfoAbout * aboutPage = static_cast<KoDocumentInfoAbout *>(info->page( "about" ));
635 TQString title = aboutPage->title();
636 if(!title.isEmpty())
637 {
638 TIFFSetField(image, TIFFTAG_DOCUMENTNAME, title.ascii());
639 }
640 TQString abstract = aboutPage->abstract();
641 if(!abstract.isEmpty())
642 {
643 TIFFSetField(image, TIFFTAG_IMAGEDESCRIPTION, abstract.ascii());
644 }
645 KoDocumentInfoAuthor * authorPage = static_cast<KoDocumentInfoAuthor *>(info->page( "author" ));
646 TQString author = authorPage->fullName();
647 if(!author.isEmpty())
648 {
649 TIFFSetField(image, TIFFTAG_ARTIST, author.ascii());
650 }
651
652 KisTIFFWriterVisitor* visitor = new KisTIFFWriterVisitor(image, &options);
653 KisGroupLayer* root = dynamic_cast<KisGroupLayer*>(img->rootLayer().data());
654 if(root == 0)
655 {
656 TDEIO::del(uri);
657 TIFFClose(image);
658 return KisImageBuilder_RESULT_FAILURE;
659 }
660 if(!visitor->visit( root ))
661 {
662 TDEIO::del(uri);
663 TIFFClose(image);
664 return KisImageBuilder_RESULT_FAILURE;
665 }
666
667 TIFFClose(image);
668 return KisImageBuilder_RESULT_OK;
669}
670
671
672void KisTIFFConverter::cancel()
673{
674 m_stop = true;
675}
676
677#include "kis_tiff_converter.moc"