1
2
3 // TnzCore includes
4 #include "tsystem.h"
5 #include "timage_io.h"
6 #include "trop.h"
7 #include "tconvert.h"
8 #include "tvectorimage.h"
9 #include "ttoonzimage.h"
10 #include "tproperty.h"
11 #include "trasterimage.h"
12 #include "tiio.h"
13 #include "tfilepath_io.h"
14 #include "tpixelutils.h"
15
16 // boost includes
17 #include <boost/range.hpp>
18
19 #ifdef _MSC_VER
20 #pragma warning(disable : 4996)
21 #endif
22
23 // OS-specific includes
24 #ifdef _WIN32
25 #include <io.h>
26 #endif
27 #if defined(LINUX) || defined(FREEBSD)
28 #include <unistd.h>
29 #endif
30
31 // System V includes
32 #include <fcntl.h> // didn't even know Windows had them :D
33 #include <sys/stat.h> // btw, why are they here?
34
35 DEFINE_CLASS_CODE(TImageReader, 5)
36 DEFINE_CLASS_CODE(TImageWriter, 6)
37
38 //-----------------------------------------------------------
39
40 std::map<QString, TImageReaderCreateProc *> ImageReaderTable;
41 std::map<QString, std::pair<TImageWriterCreateProc *, bool>> ImageWriterTable;
42
43 //-----------------------------------------------------------
44
45 bool TImageReader::m_safeMode = false;
46
47 //-----------------------------------------------------------
48
TImageReader(const TFilePath & path)49 TImageReader::TImageReader(const TFilePath &path)
50 : TSmartObject(m_classCode)
51 , m_path(path)
52 , m_reader(0)
53 , m_vectorReader(0)
54 , m_readGreytones(true)
55 , m_file(NULL)
56 , m_is64BitEnabled(false)
57 , m_shrink(1)
58 , m_region(TRect()) {}
59
60 //-----------------------------------------------------------
61
doReadGraytones(bool readThem)62 void TImageReader::doReadGraytones(bool readThem) {
63 m_readGreytones = readThem;
64 }
65
66 //-----------------------------------------------------------
67
~TImageReader()68 TImageReader::~TImageReader() { close(); }
69
70 //-----------------------------------------------------------
71
isOpen() const72 bool TImageReader::isOpen() const { return m_file != NULL; }
73
74 //-----------------------------------------------------------
75
close()76 void TImageReader::close() {
77 delete m_reader;
78 delete m_vectorReader;
79
80 if (m_file != NULL) {
81 int err = 0;
82 err = fclose(m_file);
83
84 assert(err == 0); // il file e' stato chiuso senza errori
85 }
86
87 m_file = NULL;
88 m_reader = 0;
89 m_vectorReader = 0;
90 }
91
92 //-----------------------------------------------------------
93
94 /*!
95 Opens for reading using \b fopen().
96 */
getTzpPaletteColorNames(std::map<int,std::pair<std::string,std::string>> & pltColorNames)97 void TImageReader::getTzpPaletteColorNames(
98 std::map<int, std::pair<std::string, std::string>> &pltColorNames) {
99 if (!m_file) open();
100
101 if (!m_file) return;
102
103 assert(m_reader);
104 m_reader->getTzpPaletteColorNames(pltColorNames);
105 }
106
107 //-----------------------------------------------------------
108
open()109 void TImageReader::open() {
110 assert(m_file == NULL);
111
112 std::string type = toLower(m_path.getType());
113 m_file = fopen(m_path, "rb"); // Opens for reading. If the file does not
114 // exist or cannot be found, the fopen_s call
115 // fails
116
117 if (m_file == NULL) // Non dovrebbe mai andarci!
118 close(); // close() chiude il file se e' aperto e setta m_file a NULL.
119 else {
120 try {
121 m_reader = Tiio::makeReader(type);
122 if (m_reader)
123 m_reader->open(m_file);
124 else {
125 m_vectorReader = Tiio::makeVectorReader(type);
126 if (m_vectorReader)
127 m_vectorReader->open(m_file);
128 else
129 throw TImageException(m_path, "Image format not supported");
130 }
131 } catch (TException &e) {
132 close(); // close() chiude il file e setta m_file a NULL.
133 QString msg = QString::fromStdWString(e.getMessage());
134 if (msg == QString("Old 4.1 Palette")) throw e;
135 } catch (std::string str) {
136 if (str == "Tiff file closed") m_file = NULL;
137 }
138 }
139 }
140
141 //===========================================================
142
setShrink(int shrink)143 void TImageReader::setShrink(int shrink) { m_shrink = shrink; }
144
145 //-----------------------------------------------------------
146
TImageReaderP(const TFilePath & path)147 TImageReaderP::TImageReaderP(const TFilePath &path) {
148 m_pointer = new TImageReader(path);
149 m_pointer->addRef();
150 m_pointer->open();
151 }
152
153 //-----------------------------------------------------------
154
load()155 TImageP TImageReader::load() {
156 TImageP image = load0();
157 if (!image) return TImageP();
158
159 TImageInfo info = m_reader->getImageInfo();
160 if (info.m_lx <= 0 || info.m_ly <= 0) return TImageP();
161
162 return image;
163 }
164
165 //============================================================
166
167 template <typename Pix>
168 struct pixel_traits {};
169
170 template <>
171 struct pixel_traits<TPixel32> {
172 typedef TPixel32 rgbm_pixel_type;
173 typedef char buffer_type;
174 };
175
176 template <>
177 struct pixel_traits<TPixel64> {
178 typedef TPixel64 rgbm_pixel_type;
179 typedef short buffer_type;
180 };
181
182 template <>
183 struct pixel_traits<TPixelGR8> {
184 typedef TPixel32 rgbm_pixel_type;
185 typedef char buffer_type;
186 };
187
188 template <>
189 struct pixel_traits<TPixelGR16> {
190 typedef TPixel64 rgbm_pixel_type;
191 typedef short buffer_type;
192 };
193
194 template <>
195 struct pixel_traits<TPixelCM32> {
196 typedef TPixel32 rgbm_pixel_type;
197 typedef char buffer_type;
198 };
199
200 //------------------------------------------------------------------------------------
201
202 template <typename Pix>
copyLine(typename pixel_traits<Pix>::rgbm_pixel_type * lineIn,Pix * lineOut,int x0,int length,int shrink)203 void copyLine(typename pixel_traits<Pix>::rgbm_pixel_type *lineIn, Pix *lineOut,
204 int x0, int length, int shrink) {
205 lineIn += x0;
206
207 for (int i = 0; i < length; ++i, lineIn += shrink, ++lineOut)
208 memcpy(lineOut, lineIn, sizeof(Pix));
209 }
210
211 template <>
copyLine(TPixel32 * lineIn,TPixelGR8 * lineOut,int x0,int length,int shrink)212 void copyLine<TPixelGR8>(TPixel32 *lineIn, TPixelGR8 *lineOut, int x0,
213 int length, int shrink) {
214 lineIn += x0;
215
216 for (int i = 0; i < length; ++i, lineIn += shrink, ++lineOut)
217 lineOut->value = lineIn->r;
218 }
219
220 template <>
copyLine(TPixel64 * lineIn,TPixelGR16 * lineOut,int x0,int length,int shrink)221 void copyLine<TPixelGR16>(TPixel64 *lineIn, TPixelGR16 *lineOut, int x0,
222 int length, int shrink) {
223 lineIn += x0;
224
225 for (int i = 0; i < length; ++i, lineIn += shrink, ++lineOut)
226 lineOut->value = lineIn->r;
227 }
228
229 //------------------------------------------------------------------------------------
230
231 template <typename Pix>
readRaster_copyLines(const TRasterPT<Pix> & ras,Tiio::Reader * reader,int x0,int y0,int x1,int y1,int inLx,int inLy,int shrink)232 void readRaster_copyLines(const TRasterPT<Pix> &ras, Tiio::Reader *reader,
233 int x0, int y0, int x1, int y1, int inLx, int inLy,
234 int shrink) {
235 typedef typename pixel_traits<Pix>::buffer_type buffer_type;
236 typedef typename pixel_traits<Pix>::rgbm_pixel_type rgbm_pixel_type;
237
238 int linesToSkip = shrink - 1;
239
240 buffer_type *lineBuffer =
241 (buffer_type *)malloc(inLx * sizeof(rgbm_pixel_type));
242 if (!lineBuffer) return;
243
244 rgbm_pixel_type *lineIn = (rgbm_pixel_type *)lineBuffer;
245
246 if (reader->getRowOrder() == Tiio::BOTTOM2TOP) {
247 int start = reader->skipLines(y0);
248 int stop = y1 + 1;
249
250 for (int y = start; y < stop; ++y) {
251 reader->readLine(lineBuffer, x0, x1, shrink);
252
253 if (y >= y0 && y <= y1 && (y - y0) % shrink == 0) {
254 Pix *line = (Pix *)ras->getRawData(0, (y - y0) / shrink);
255 copyLine<Pix>(lineIn, line, x0, ras->getLx(), shrink);
256 }
257
258 if (linesToSkip > 0 && y + linesToSkip < inLy)
259 y += reader->skipLines(linesToSkip);
260 }
261 } else // TOP2BOTTOM
262 {
263 reader->skipLines(inLy - y1 - 1);
264
265 for (int y = y1; y >= y0; --y) {
266 reader->readLine(lineBuffer, x0, x1, shrink);
267
268 if ((y - y0) % shrink == 0) {
269 Pix *line = (Pix *)ras->getRawData(0, (y - y0) / shrink);
270 copyLine<Pix>(lineIn, line, x0, ras->getLx(), shrink);
271 }
272
273 if (linesToSkip > 0 && y - linesToSkip > 0)
274 y -= reader->skipLines(linesToSkip);
275 }
276 }
277
278 free(lineBuffer);
279 }
280
281 //------------------------------------------------------------------------------------
282
283 template <typename Pix>
readRaster(const TRasterPT<Pix> & ras,Tiio::Reader * reader,int x0,int y0,int x1,int y1,int inLx,int inLy,int shrink)284 void readRaster(const TRasterPT<Pix> &ras, Tiio::Reader *reader, int x0, int y0,
285 int x1, int y1, int inLx, int inLy, int shrink) {
286 typedef typename pixel_traits<Pix>::buffer_type buffer_type;
287
288 if (shrink == 1) {
289 // Direct read
290 ras->lock();
291
292 ptrdiff_t linePad = -x0 * ras->getPixelSize();
293
294 if (reader->getRowOrder() == Tiio::BOTTOM2TOP) {
295 int start = reader->skipLines(y0);
296 int stop = y1 + 1;
297
298 for (int y = start; y < stop; ++y)
299 if (y >= y0 && y <= y1) {
300 buffer_type *line =
301 (buffer_type *)(ras->getRawData(0, y - y0) + linePad);
302 reader->readLine(line, x0, x1, 1);
303 }
304 } else // TOP2BOTTOM
305 {
306 reader->skipLines(inLy - y1 - 1);
307
308 for (int y = y1; y >= y0; --y) {
309 buffer_type *line =
310 (buffer_type *)(ras->getRawData(0, y - y0) + linePad);
311 reader->readLine(line, x0, x1, 1);
312 }
313 }
314
315 ras->unlock();
316 } else
317 readRaster_copyLines(ras, reader, x0, y0, x1, y1, inLx, inLy, shrink);
318 }
319
320 //------------------------------------------------------------------------------------
321
load0()322 TImageP TImageReader::load0() {
323 if (!m_reader && !m_vectorReader) open();
324
325 if (m_reader) {
326 TImageInfo info = m_reader->getImageInfo();
327 if (info.m_lx <= 0 || info.m_ly <= 0) return TImageP();
328
329 // Initialize raster info
330 assert(m_shrink > 0);
331
332 // Build loading rect
333 int x0 = 0;
334 int x1 = info.m_lx - 1;
335 int y0 = 0;
336 int y1 = info.m_ly - 1;
337
338 if (!m_region.isEmpty()) {
339 // Intersect with the externally specified loading region
340
341 x0 = std::max(x0, m_region.x0);
342 y0 = std::max(y0, m_region.y0);
343 x1 = std::min(x1, m_region.x1);
344 y1 = std::min(y1, m_region.y1);
345
346 if (x0 >= x1 || y0 >= y1) return TImageP();
347 }
348
349 if (m_shrink > 1) {
350 // Crop to shrink multiples
351 x1 -= (x1 - x0) % m_shrink;
352 y1 -= (y1 - y0) % m_shrink;
353 }
354
355 assert(x0 <= x1 && y0 <= y1);
356
357 TDimension imageDimension =
358 TDimension((x1 - x0) / m_shrink + 1, (y1 - y0) / m_shrink + 1);
359
360 if (m_path.getType() == "tzp" || m_path.getType() == "tzu") {
361 // Colormap case
362
363 TRasterCM32P ras(imageDimension);
364 readRaster(ras, m_reader, x0, y0, x1, y1, info.m_lx, info.m_ly, m_shrink);
365
366 // Build the savebox
367 TRect saveBox(info.m_x0, info.m_y0, info.m_x1, info.m_y1);
368 if (!m_region.isEmpty()) {
369 // Intersect with the loading rect
370 if (m_region.overlaps(saveBox)) {
371 saveBox *= m_region;
372
373 int sbx0 = saveBox.x0 - m_region.x0;
374 int sby0 = saveBox.y0 - m_region.y0;
375 int sbx1 = sbx0 + saveBox.getLx() - 1;
376 int sby1 = sby0 + saveBox.getLy() - 1;
377 assert(sbx0 >= 0);
378 assert(sby0 >= 0);
379 assert(sbx1 >= 0);
380 assert(sby1 >= 0);
381
382 saveBox = TRect(sbx0, sby0, sbx1, sby1);
383 } else
384 saveBox = TRect(0, 0, 1, 1);
385 }
386
387 if (m_shrink > 1) {
388 saveBox.x0 = saveBox.x0 / m_shrink;
389 saveBox.y0 = saveBox.y0 / m_shrink;
390 saveBox.x1 = saveBox.x1 / m_shrink;
391 saveBox.y1 = saveBox.y1 / m_shrink;
392 }
393
394 TToonzImageP ti(ras, ras->getBounds() * saveBox);
395 ti->setDpi(info.m_dpix, info.m_dpiy);
396
397 return ti;
398 } else if (info.m_bitsPerSample >= 8) {
399 // Common byte-based rasters (see below, we have black-and-white bit-based
400 // images too)
401
402 if (info.m_samplePerPixel == 1 && m_readGreytones) {
403 // Greymap case
404 // NOTE: Uses a full 32-bit raster first, and then copies down to the
405 // GR8
406
407 // Observe that GR16 file images get immediately down-cast to GR8...
408 // Should we implement that too?
409
410 TRasterGR8P ras(imageDimension);
411 readRaster_copyLines(ras, m_reader, x0, y0, x1, y1, info.m_lx,
412 info.m_ly, m_shrink);
413
414 TRasterImageP ri(ras);
415 ri->setDpi(info.m_dpix, info.m_dpiy);
416
417 return ri;
418 }
419
420 // assert(info.m_samplePerPixel == 3 || info.m_samplePerPixel == 4);
421
422 TRasterP _ras;
423 if (info.m_bitsPerSample == 16) {
424 if (m_is64BitEnabled || m_path.getType() != "tif") {
425 // Standard 64-bit case.
426
427 // Also covers down-casting to 32-bit from a 64-bit image file
428 // whenever
429 // not a tif file (see below).
430
431 TRaster64P ras(imageDimension);
432 readRaster(ras, m_reader, x0, y0, x1, y1, info.m_lx, info.m_ly,
433 m_shrink);
434
435 _ras = ras;
436 } else {
437 // The Tif reader has got an automatically down-casting
438 // readLine(char*, ...)
439 // in case the input file is 64-bit. The advantage is that no
440 // intermediate
441 // 64-bit raster is required in this case.
442
443 TRaster32P ras(imageDimension);
444 readRaster(ras, m_reader, x0, y0, x1, y1, info.m_lx, info.m_ly,
445 m_shrink);
446
447 _ras = ras;
448 }
449 } else if (info.m_bitsPerSample == 8) {
450 // Standard 32-bit case
451 TRaster32P ras(imageDimension);
452 readRaster(ras, m_reader, x0, y0, x1, y1, info.m_lx, info.m_ly,
453 m_shrink);
454
455 _ras = ras;
456 } else
457 throw TImageException(m_path, "Image format not supported");
458
459 // 64-bit to 32-bit conversions if necessary (64 bit images not allowed)
460 if (!m_is64BitEnabled && (TRaster64P)_ras) {
461 TRaster32P raux(_ras->getLx(), _ras->getLy());
462 TRop::convert(raux, _ras);
463 _ras = raux;
464 }
465
466 // Return the image
467 TRasterImageP ri(_ras);
468 ri->setDpi(info.m_dpix, info.m_dpiy);
469
470 return ri;
471 } else if (info.m_samplePerPixel == 1 && info.m_valid == true) {
472 // Previously dubbed as 'Palette cases'. No clue about what is this... :|
473
474 TRaster32P ras(imageDimension);
475 readRaster(ras, m_reader, x0, y0, x1, y1, info.m_lx, info.m_ly, m_shrink);
476
477 TRasterImageP ri(ras);
478 ri->setDpi(info.m_dpix, info.m_dpiy);
479
480 return ri;
481 } else if (info.m_samplePerPixel == 1 && m_readGreytones) {
482 // Black-and-White case, I guess. Standard greymaps were considered
483 // above...
484
485 TRasterGR8P ras(imageDimension);
486 readRaster_copyLines(ras, m_reader, x0, y0, x1, y1, info.m_lx, info.m_ly,
487 m_shrink);
488
489 TRasterImageP ri(ras);
490 ri->setDpi(info.m_dpix, info.m_dpiy);
491
492 if (info.m_bitsPerSample == 1) // I suspect this always evaluates true...
493 ri->setScanBWFlag(true);
494
495 return ri;
496 } else
497 return TImageP();
498 } else if (m_vectorReader) {
499 TVectorImage *vi = m_vectorReader->read();
500 return TVectorImageP(vi);
501 } else
502 return TImageP();
503 }
504
505 //-----------------------------------------------------------
506
TImageWriter(const TFilePath & path)507 TImageWriter::TImageWriter(const TFilePath &path)
508 : TSmartObject(m_classCode)
509 , m_path(path)
510 , m_writer(0)
511 , m_vectorWriter(0)
512 , m_properties(0) {}
513
514 //-----------------------------------------------------------
515
~TImageWriter()516 TImageWriter::~TImageWriter() {
517 delete m_writer;
518 delete m_vectorWriter;
519 delete m_properties;
520 }
521
522 //-----------------------------------------------------------
523
setProperties(const TPropertyGroup * g)524 void TImageWriter::setProperties(const TPropertyGroup *g) {
525 if (m_properties) {
526 assert(m_properties != g);
527 delete m_properties;
528 }
529 m_properties = g ? g->clone() : 0;
530 }
531
532 //-----------------------------------------------------------
533
convertForWriting(TRasterP & ras,const TRasterP & rin,int bpp)534 static void convertForWriting(TRasterP &ras, const TRasterP &rin, int bpp) {
535 switch (bpp) {
536 case 1:
537 case 8:
538 ras = TRasterGR8P(rin->getSize());
539 TRop::convert(ras, rin);
540 break;
541 case 24:
542 case 32:
543 ras = TRaster32P(rin->getSize());
544 TRop::convert(ras, rin);
545 break;
546 case 48:
547 case 64:
548 ras = TRaster64P(rin->getSize());
549 TRop::convert(ras, rin);
550 break;
551 default:
552 assert(false);
553 }
554 }
555
556 //-----------------------------------------------------------
557
save(const TImageP & img)558 void TImageWriter::save(const TImageP &img) {
559 const std::string &type = toLower(m_path.getType());
560
561 Tiio::Writer *writer = Tiio::makeWriter(type);
562 if (!writer)
563 throw TImageException(m_path, "unsupported format for raster images");
564
565 writer->setProperties(m_properties);
566
567 FILE *file = fopen(m_path, "wb");
568 if (file == NULL) throw TImageException(m_path, "Can't write file");
569
570 if (TRasterImageP ri = img) {
571 TImageInfo info;
572 TRasterP ras;
573
574 TRasterGR8P rasGr = ri->getRaster();
575 TRaster32P ras32 = ri->getRaster();
576 TRaster64P ras64 = ri->getRaster();
577
578 TEnumProperty *p =
579 m_properties
580 ? (TEnumProperty *)m_properties->getProperty("Bits Per Pixel")
581 : 0;
582
583 if (p && ri->isScanBW()) {
584 const std::vector<std::wstring> &range = p->getRange();
585 p->setValue(range[2]); // Horrible. See tiio_tif.cpp (732 or near) -.-'
586 }
587
588 int bpp = p ? std::stoi(p->getValue()) : 32;
589
590 // bpp 1 8 16 24 32 40 48 56 64
591 int spp[] = {
592 1, 1, 1, 4, 4,
593 0, 4, 0, 4}; // 0s are for pixel sizes which are normally unsupported
594 int bps[] = {
595 1, 8, 16, 8, 8,
596 0, 16, 0, 16}; // by image formats, let alone by Toonz raster ones.
597 // The 24 and 48 cases get automatically promoted to 32 and 64.
598 int bypp = bpp / 8;
599 assert(bypp < boost::size(spp) && spp[bypp] && bps[bypp]);
600
601 info.m_samplePerPixel = spp[bypp];
602 info.m_bitsPerSample = bps[bypp];
603
604 if (rasGr) {
605 if (bypp < 2) // Seems 16 bit greymaps are not handled... why?
606 ras = rasGr; // we do have a Toonz raster for those... >:|
607 else
608 convertForWriting(ras, rasGr, bpp);
609 } else if (ras32) {
610 if (bpp == 32 || bpp == 24)
611 ras = ras32;
612 else
613 convertForWriting(ras, ras32, bpp);
614 } else if (ras64) {
615 if (bpp == 64 || bpp == 48)
616 ras = ras64;
617 else
618 convertForWriting(ras, ras64, bpp);
619 } else {
620 fclose(file);
621 throw TImageException(m_path, "unsupported raster type");
622 }
623
624 info.m_lx = ras->getLx();
625 info.m_ly = ras->getLy();
626
627 ri->getDpi(info.m_dpix, info.m_dpiy);
628
629 if (writer->getProperties() && m_properties)
630 writer->getProperties()->setProperties(m_properties);
631
632 writer->open(file, info);
633
634 // add background colors for non alpha-enabled image types
635 if ((ras32 || ras64) && !writer->writeAlphaSupported() &&
636 TImageWriter::getBackgroundColor() != TPixel::Black) {
637 if (bpp == 32 || bpp == 24)
638 TRop::addBackground(ras, TImageWriter::getBackgroundColor());
639 else if (bpp == 64 || bpp == 48) {
640 TRaster64P bgRas(ras->getSize());
641 bgRas->fill(toPixel64(TImageWriter::getBackgroundColor()));
642 TRop::over(bgRas, ras);
643 ras = bgRas;
644 } // for other bpp values, do nothing for now
645 }
646
647 ras->lock();
648
649 if (writer->getRowOrder() == Tiio::BOTTOM2TOP) {
650 if (bpp == 1 || bpp == 8 || bpp == 24 || bpp == 32 || bpp == 16)
651 for (int i = 0; i < ras->getLy(); i++)
652 writer->writeLine((char *)ras->getRawData(0, i));
653 else
654 for (int i = 0; i < ras->getLy(); i++)
655 writer->writeLine((short *)ras->getRawData(0, i));
656 } else {
657 if (bpp == 1 || bpp == 8 || bpp == 24 || bpp == 32 || bpp == 16)
658 for (int i = ras->getLy() - 1; i >= 0; i--)
659 writer->writeLine((char *)ras->getRawData(0, i));
660 else
661 for (int i = ras->getLy() - 1; i >= 0; i--)
662 writer->writeLine((short *)ras->getRawData(0, i));
663 }
664
665 ras->unlock();
666
667 writer->flush();
668 delete writer;
669 } else if (TVectorImageP vi = img) {
670 Tiio::VectorWriter *writer = Tiio::makeVectorWriter(type);
671 if (!writer) {
672 fclose(file);
673 throw TImageException(m_path, "unsupported format for vector images");
674 }
675
676 writer->open(file);
677 writer->write(vi.getPointer());
678
679 delete writer;
680 } else {
681 fclose(file);
682 throw TImageException(m_path, "Can't write file");
683 }
684
685 fclose(file);
686 }
687
688 //-----------------------------------------------------------
689
TImageWriterP(const TFilePath & path)690 TImageWriterP::TImageWriterP(const TFilePath &path) {
691 m_pointer = new TImageWriter(path);
692 m_pointer->addRef();
693 }
694
695 //============================================================
696 //
697 // Helper functions statiche
698 //
699 //============================================================
700
load(const TFilePath & path,TRasterP & raster)701 bool TImageReader::load(const TFilePath &path, TRasterP &raster) {
702 raster = TRasterP();
703 TImageReaderP ir(path);
704 if (!ir) return false;
705 TImageP img = ir->load();
706 if (!img) return false;
707
708 TRasterImageP ri(img);
709 if (!ri) return false;
710
711 raster = ri->getRaster();
712 return true;
713 }
714
715 //-----------------------------------------------------------
716
717 //-----------------------------------------------------------
718
load(const TRasterP & ras,const TPoint & pos,int shrinkX,int shrinkY)719 void TImageReader::load(const TRasterP &ras, const TPoint &pos, int shrinkX,
720 int shrinkY) {
721 TImageP srcImage = load();
722 TRasterImageP srcRasImage = srcImage;
723 TRaster32P srcRaster = srcRasImage->getRaster();
724 /*
725 TRaster32P clippedRas = srcRaster->extractT
726 (shrinkX*pos.x, shrinkY*pos.y,
727 (pos.x + ras->getLx()) * shrinkX - 1, (pos.y + ras->getLy()) * shrinkY - 1);
728
729 if (shrinkX != 1 || shrinkY != 1)
730 {
731 TRaster32P ras32 = ras;
732 if (ras32)
733 ras32->fill(TPixel32::Transparent);
734 TRop::resample(ras, clippedRas, TScale(1./shrinkX, 1./shrinkY),
735 TRop::ClosestPixel);
736 }
737 else*/
738 ras->copy(srcRaster);
739 }
740
741 //-----------------------------------------------------------
742
load(const TFilePath & path,TImageP & image)743 bool TImageReader::load(const TFilePath &path, TImageP &image) {
744 image = TImageReaderP(path)->load();
745 return image;
746 }
747
748 //-----------------------------------------------------------
749
save(const TFilePath & path,TRasterP raster)750 void TImageWriter::save(const TFilePath &path, TRasterP raster) {
751 TRasterImageP rasImage(raster);
752 TImageWriterP(path)->save(TImageP(rasImage));
753 }
754
755 //-----------------------------------------------------------
756
save(const TFilePath & path,const TImageP & image)757 void TImageWriter::save(const TFilePath &path, const TImageP &image) {
758 TImageWriterP(path)->save(image);
759 }
760
761 //===========================================================
762 // Background color for saving ransparent pixel to the format not
763 // supporting alpha channel. Specified in the preferences.
764
765 TPixel32 TImageWriter::m_backgroundColor;
766
setBackgroundColor(TPixel32 color)767 void TImageWriter::setBackgroundColor(TPixel32 color) {
768 m_backgroundColor = color;
769 }
770
getBackgroundColor()771 TPixel32 TImageWriter::getBackgroundColor() { return m_backgroundColor; }
772
773 //===========================================================
774 //
775 // funzioni per la registrazione dei formati (chiamate dal Plugin)
776 //
777 //===========================================================
778
define(QString extension,TImageReaderCreateProc * proc)779 void TImageReader::define(QString extension, TImageReaderCreateProc *proc) {
780 ImageReaderTable[extension] = proc;
781 }
782
783 //-----------------------------------------------------------
784
define(QString extension,TImageWriterCreateProc * proc,bool isRenderFormat)785 void TImageWriter::define(QString extension, TImageWriterCreateProc *proc,
786 bool isRenderFormat) {
787 ImageWriterTable[extension] =
788 std::pair<TImageWriterCreateProc *, bool>(proc, isRenderFormat);
789 }
790
791 //-----------------------------------------------------------
792
getSupportedFormats(QStringList & names)793 void TImageReader::getSupportedFormats(QStringList &names) {
794 for (std::map<QString, TImageReaderCreateProc *>::iterator it =
795 ImageReaderTable.begin();
796 it != ImageReaderTable.end(); ++it) {
797 names.push_back(it->first);
798 }
799 }
800
801 //-----------------------------------------------------------
802
getSupportedFormats(QStringList & names,bool onlyRenderFormat)803 void TImageWriter::getSupportedFormats(QStringList &names,
804 bool onlyRenderFormat) {
805 for (std::map<QString, std::pair<TImageWriterCreateProc *, bool>>::iterator
806 it = ImageWriterTable.begin();
807 it != ImageWriterTable.end(); ++it) {
808 if (!onlyRenderFormat || it->second.second) names.push_back(it->first);
809 }
810 }
811
812 //-----------------------------------------------------------
813
getImageInfo() const814 const TImageInfo *TImageReader::getImageInfo() const {
815 if (m_reader)
816 return &(m_reader->getImageInfo());
817 else
818 return 0;
819 }
820
821 //-----------------------------------------------------------
822
823 //===========================================================
824 //
825 // Eccezioni
826 //
827 //===========================================================
828
TImageException(const TFilePath & fp,const std::string & msg)829 TImageException::TImageException(const TFilePath &fp, const std::string &msg)
830 : TException(msg), m_fp(fp) {}
831
832 //-----------------------------------------------------------
833
getMessage() const834 TString TImageException::getMessage() const {
835 return m_fp.getWideString() + L": " + TException::getMessage();
836 }
837
838 //===========================================================
839
TImageVersionException(const TFilePath & fp,int major,int minor)840 TImageVersionException::TImageVersionException(const TFilePath &fp, int major,
841 int minor)
842 : TException(L"The file " + fp.getWideString() +
843 L" was generated by a newer version of OpenToonz and cannot "
844 L"be loaded.")
845 , m_fp(fp)
846 , m_major(major)
847 , m_minor(minor) {}
848