190 || !TIFFGetField(tiff, TIFFTAG_PHOTOMETRIC, &photometric)) { |
190 || !TIFFGetField(tiff, TIFFTAG_PHOTOMETRIC, &photometric)) { |
191 TIFFClose(tiff); |
191 TIFFClose(tiff); |
192 return false; |
192 return false; |
193 } |
193 } |
194 |
194 |
195 if (photometric == PHOTOMETRIC_MINISBLACK || photometric == PHOTOMETRIC_MINISWHITE) { |
195 uint16 bitPerSample; |
|
196 if (!TIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE, &bitPerSample)) { |
|
197 TIFFClose(tiff); |
|
198 return false; |
|
199 } |
|
200 |
|
201 bool grayscale = photometric == PHOTOMETRIC_MINISBLACK || photometric == PHOTOMETRIC_MINISWHITE; |
|
202 if (grayscale && bitPerSample == 1) { |
196 if (image->size() != QSize(width, height) || image->format() != QImage::Format_Mono) |
203 if (image->size() != QSize(width, height) || image->format() != QImage::Format_Mono) |
197 *image = QImage(width, height, QImage::Format_Mono); |
204 *image = QImage(width, height, QImage::Format_Mono); |
198 QVector<QRgb> colortable(2); |
205 QVector<QRgb> colortable(2); |
199 if (photometric == PHOTOMETRIC_MINISBLACK) { |
206 if (photometric == PHOTOMETRIC_MINISBLACK) { |
200 colortable[0] = 0xff000000; |
207 colortable[0] = 0xff000000; |
206 image->setColorTable(colortable); |
213 image->setColorTable(colortable); |
207 |
214 |
208 if (!image->isNull()) { |
215 if (!image->isNull()) { |
209 for (uint32 y=0; y<height; ++y) { |
216 for (uint32 y=0; y<height; ++y) { |
210 if (TIFFReadScanline(tiff, image->scanLine(y), y, 0) < 0) { |
217 if (TIFFReadScanline(tiff, image->scanLine(y), y, 0) < 0) { |
211 TIFFClose(tiff); |
218 TIFFClose(tiff); |
212 return false; |
219 return false; |
213 } |
220 } |
214 } |
221 } |
215 } |
222 } |
216 } else { |
223 } else { |
217 uint16 bitPerSample; |
224 if ((grayscale || photometric == PHOTOMETRIC_PALETTE) && bitPerSample == 8) { |
218 if (!TIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE, &bitPerSample)) { |
|
219 TIFFClose(tiff); |
|
220 return false; |
|
221 } |
|
222 if (photometric == PHOTOMETRIC_PALETTE && bitPerSample == 8) { |
|
223 if (image->size() != QSize(width, height) || image->format() != QImage::Format_Indexed8) |
225 if (image->size() != QSize(width, height) || image->format() != QImage::Format_Indexed8) |
224 *image = QImage(width, height, QImage::Format_Indexed8); |
226 *image = QImage(width, height, QImage::Format_Indexed8); |
225 if (!image->isNull()) { |
227 if (!image->isNull()) { |
226 // create the color table |
|
227 const uint16 tableSize = 256; |
228 const uint16 tableSize = 256; |
228 uint16 *redTable = static_cast<uint16 *>(qMalloc(tableSize * sizeof(uint16))); |
|
229 uint16 *greenTable = static_cast<uint16 *>(qMalloc(tableSize * sizeof(uint16))); |
|
230 uint16 *blueTable = static_cast<uint16 *>(qMalloc(tableSize * sizeof(uint16))); |
|
231 if (!redTable || !greenTable || !blueTable) { |
|
232 TIFFClose(tiff); |
|
233 return false; |
|
234 } |
|
235 if (!TIFFGetField(tiff, TIFFTAG_COLORMAP, &redTable, &greenTable, &blueTable)) { |
|
236 TIFFClose(tiff); |
|
237 return false; |
|
238 } |
|
239 |
|
240 QVector<QRgb> qtColorTable(tableSize); |
229 QVector<QRgb> qtColorTable(tableSize); |
241 for (int i = 0; i<tableSize ;++i) { |
230 if (grayscale) { |
242 const int red = redTable[i] / 257; |
231 for (int i = 0; i<tableSize; ++i) { |
243 const int green = greenTable[i] / 257; |
232 const int c = (photometric == PHOTOMETRIC_MINISBLACK) ? i : (255 - i); |
244 const int blue = blueTable[i] / 257; |
233 qtColorTable[i] = qRgb(c, c, c); |
245 qtColorTable[i] = qRgb(red, green, blue); |
234 } |
246 |
235 } else { |
|
236 // create the color table |
|
237 uint16 *redTable = static_cast<uint16 *>(qMalloc(tableSize * sizeof(uint16))); |
|
238 uint16 *greenTable = static_cast<uint16 *>(qMalloc(tableSize * sizeof(uint16))); |
|
239 uint16 *blueTable = static_cast<uint16 *>(qMalloc(tableSize * sizeof(uint16))); |
|
240 if (!redTable || !greenTable || !blueTable) { |
|
241 TIFFClose(tiff); |
|
242 return false; |
|
243 } |
|
244 if (!TIFFGetField(tiff, TIFFTAG_COLORMAP, &redTable, &greenTable, &blueTable)) { |
|
245 TIFFClose(tiff); |
|
246 return false; |
|
247 } |
|
248 |
|
249 for (int i = 0; i<tableSize ;++i) { |
|
250 const int red = redTable[i] / 257; |
|
251 const int green = greenTable[i] / 257; |
|
252 const int blue = blueTable[i] / 257; |
|
253 qtColorTable[i] = qRgb(red, green, blue); |
|
254 } |
247 } |
255 } |
248 |
256 |
249 image->setColorTable(qtColorTable); |
257 image->setColorTable(qtColorTable); |
250 for (uint32 y=0; y<height; ++y) { |
258 for (uint32 y=0; y<height; ++y) { |
251 if (TIFFReadScanline(tiff, image->scanLine(y), y, 0) < 0) { |
259 if (TIFFReadScanline(tiff, image->scanLine(y), y, 0) < 0) { |
423 if (format == QImage::Format_Mono || format == QImage::Format_MonoLSB) { |
445 if (format == QImage::Format_Mono || format == QImage::Format_MonoLSB) { |
424 uint16 photometric = PHOTOMETRIC_MINISBLACK; |
446 uint16 photometric = PHOTOMETRIC_MINISBLACK; |
425 if (image.colorTable().at(0) == 0xffffffff) |
447 if (image.colorTable().at(0) == 0xffffffff) |
426 photometric = PHOTOMETRIC_MINISWHITE; |
448 photometric = PHOTOMETRIC_MINISWHITE; |
427 if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, photometric) |
449 if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, photometric) |
428 || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_CCITTRLE)) { |
450 || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_CCITTRLE) |
|
451 || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 1)) { |
429 TIFFClose(tiff); |
452 TIFFClose(tiff); |
430 return false; |
453 return false; |
431 } |
454 } |
432 |
455 |
433 // try to do the conversion in chunks no greater than 16 MB |
456 // try to do the conversion in chunks no greater than 16 MB |
448 ++y; |
471 ++y; |
449 } |
472 } |
450 } |
473 } |
451 TIFFClose(tiff); |
474 TIFFClose(tiff); |
452 } else if (format == QImage::Format_Indexed8) { |
475 } else if (format == QImage::Format_Indexed8) { |
453 if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE) |
|
454 || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_PACKBITS) |
|
455 || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8)) { |
|
456 TIFFClose(tiff); |
|
457 return false; |
|
458 } |
|
459 //// write the color table |
|
460 // allocate the color tables |
|
461 uint16 *redTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16))); |
|
462 uint16 *greenTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16))); |
|
463 uint16 *blueTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16))); |
|
464 if (!redTable || !greenTable || !blueTable) { |
|
465 TIFFClose(tiff); |
|
466 return false; |
|
467 } |
|
468 |
|
469 // set the color table |
|
470 const QVector<QRgb> colorTable = image.colorTable(); |
476 const QVector<QRgb> colorTable = image.colorTable(); |
471 |
477 bool isGrayscale = checkGrayscale(colorTable); |
472 const int tableSize = colorTable.size(); |
478 if (isGrayscale) { |
473 Q_ASSERT(tableSize <= 256); |
479 uint16 photometric = PHOTOMETRIC_MINISBLACK; |
474 for (int i = 0; i<tableSize; ++i) { |
480 if (image.colorTable().at(0) == 0xffffffff) |
475 const QRgb color = colorTable.at(i); |
481 photometric = PHOTOMETRIC_MINISWHITE; |
476 redTable[i] = qRed(color) * 257; |
482 if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, photometric) |
477 greenTable[i] = qGreen(color) * 257; |
483 || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_PACKBITS) |
478 blueTable[i] = qBlue(color) * 257; |
484 || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8)) { |
479 } |
485 TIFFClose(tiff); |
480 |
486 return false; |
481 const bool setColorTableSuccess = TIFFSetField(tiff, TIFFTAG_COLORMAP, redTable, greenTable, blueTable); |
487 } |
482 |
488 } else { |
483 qFree(redTable); |
489 if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE) |
484 qFree(greenTable); |
490 || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_PACKBITS) |
485 qFree(blueTable); |
491 || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8)) { |
486 |
492 TIFFClose(tiff); |
487 if (!setColorTableSuccess) { |
493 return false; |
488 TIFFClose(tiff); |
494 } |
489 return false; |
495 //// write the color table |
|
496 // allocate the color tables |
|
497 uint16 *redTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16))); |
|
498 uint16 *greenTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16))); |
|
499 uint16 *blueTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16))); |
|
500 if (!redTable || !greenTable || !blueTable) { |
|
501 TIFFClose(tiff); |
|
502 return false; |
|
503 } |
|
504 |
|
505 // set the color table |
|
506 const int tableSize = colorTable.size(); |
|
507 Q_ASSERT(tableSize <= 256); |
|
508 for (int i = 0; i<tableSize; ++i) { |
|
509 const QRgb color = colorTable.at(i); |
|
510 redTable[i] = qRed(color) * 257; |
|
511 greenTable[i] = qGreen(color) * 257; |
|
512 blueTable[i] = qBlue(color) * 257; |
|
513 } |
|
514 |
|
515 const bool setColorTableSuccess = TIFFSetField(tiff, TIFFTAG_COLORMAP, redTable, greenTable, blueTable); |
|
516 |
|
517 qFree(redTable); |
|
518 qFree(greenTable); |
|
519 qFree(blueTable); |
|
520 |
|
521 if (!setColorTableSuccess) { |
|
522 TIFFClose(tiff); |
|
523 return false; |
|
524 } |
490 } |
525 } |
491 |
526 |
492 //// write the data |
527 //// write the data |
493 // try to do the conversion in chunks no greater than 16 MB |
528 // try to do the conversion in chunks no greater than 16 MB |
494 int chunks = (width * height/ (1024 * 1024 * 16)) + 1; |
529 int chunks = (width * height/ (1024 * 1024 * 16)) + 1; |