filters

kis_openexr_export.cpp
1/*
2 * Copyright (c) 2005 Adrian Page <adrian@pagenet.plus.com>
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 <tqfile.h>
21
22#include <tdemessagebox.h>
23
24#include <half.h>
25#include <ImfRgbaFile.h>
26
27#include <kgenericfactory.h>
28#include <KoDocument.h>
29#include <KoFilterChain.h>
30
31#include "kis_doc.h"
32#include "kis_image.h"
33#include "kis_layer.h"
34#include "kis_paint_layer.h"
35#include "kis_annotation.h"
36#include "kis_types.h"
37#include "kis_iterators_pixel.h"
38#include "kis_abstract_colorspace.h"
39#include "kis_paint_device.h"
40#include "kis_rgb_f32_colorspace.h"
41#include "kis_rgb_f16half_colorspace.h"
42
43#include "kis_openexr_export.h"
44
45using namespace std;
46using namespace Imf;
47using namespace Imath;
48
49typedef KGenericFactory<KisOpenEXRExport, KoFilter> KisOpenEXRExportFactory;
50K_EXPORT_COMPONENT_FACTORY(libchalk_openexr_export, KisOpenEXRExportFactory("kofficefilters"))
51
52KisOpenEXRExport::KisOpenEXRExport(KoFilter *, const char *, const TQStringList&) : KoFilter()
53{
54}
55
56KisOpenEXRExport::~KisOpenEXRExport()
57{
58}
59
60KoFilter::ConversionStatus KisOpenEXRExport::convert(const TQCString& from, const TQCString& to)
61{
62 if (to != "image/x-exr" || from != "application/x-chalk") {
63 return KoFilter::NotImplemented;
64 }
65
66 kdDebug(41008) << "Chalk exporting to OpenEXR\n";
67
68 // XXX: Add dialog about flattening layers here
69
70 KisDoc *doc = dynamic_cast<KisDoc*>(m_chain -> inputDocument());
71 TQString filename = m_chain -> outputFile();
72
73 if (!doc) {
74 return KoFilter::CreationError;
75 }
76
77 if (filename.isEmpty()) {
78 return KoFilter::FileNotFound;
79 }
80
81 KisImageSP img = new KisImage(*doc -> currentImage());
82 TQ_CHECK_PTR(img);
83
84 // Don't store this information in the document's undo adapter
85 bool undo = doc -> undoAdapter() -> undo();
86 doc -> undoAdapter() -> setUndo(false);
87
88 img -> flatten();
89
90 KisPaintLayerSP layer = dynamic_cast<KisPaintLayer*>(img->activeLayer().data());
91 Q_ASSERT(layer);
92
93 doc -> undoAdapter() -> setUndo(undo);
94
95 //KisF32RgbColorSpace * cs = static_cast<KisF32RgbColorSpace *>((KisColorSpaceRegistry::instance() -> get(KisID("RGBAF32", ""))));
96 KisRgbF16HalfColorSpace *cs = dynamic_cast<KisRgbF16HalfColorSpace *>(layer->paintDevice()->colorSpace());
97
98 if (cs == 0) {
99 // We could convert automatically, but the conversion wants to be done with
100 // selectable profiles and rendering intent.
101 KMessageBox::information(0, i18n("The image is using an unsupported color space. "
102 "Please convert to 16-bit floating point RGB/Alpha "
103 "before saving in the OpenEXR format."));
104
105 // Don't show the couldn't save error dialog.
106 doc -> setErrorMessage("USER_CANCELED");
107
108 return KoFilter::WrongFormat;
109 }
110
111 Box2i displayWindow(V2i(0, 0), V2i(img -> width() - 1, img -> height() - 1));
112
113 TQRect dataExtent = layer -> exactBounds();
114 int dataWidth = dataExtent.width();
115 int dataHeight = dataExtent.height();
116
117 Box2i dataWindow(V2i(dataExtent.left(), dataExtent.top()), V2i(dataExtent.right(), dataExtent.bottom()));
118
119 RgbaOutputFile file(TQFile::encodeName(filename), displayWindow, dataWindow, WRITE_RGBA);
120
121 TQMemArray<Rgba> pixels(dataWidth);
122
123 for (int y = 0; y < dataHeight; ++y) {
124
125 file.setFrameBuffer(pixels.data() - dataWindow.min.x - (dataWindow.min.y + y) * dataWidth, 1, dataWidth);
126
127 KisHLineIterator it = layer->paintDevice()->createHLineIterator(dataWindow.min.x, dataWindow.min.y + y, dataWidth, false);
128 Rgba *rgba = pixels.data();
129
130 while (!it.isDone()) {
131
132 // XXX: Currently we use unmultiplied data so premult it.
133 half unmultipliedRed;
134 half unmultipliedGreen;
135 half unmultipliedBlue;
136 half alpha;
137
138 cs -> getPixel(it.rawData(), &unmultipliedRed, &unmultipliedGreen, &unmultipliedBlue, &alpha);
139 rgba -> r = unmultipliedRed * alpha;
140 rgba -> g = unmultipliedGreen * alpha;
141 rgba -> b = unmultipliedBlue * alpha;
142 rgba -> a = alpha;
143 ++it;
144 ++rgba;
145 }
146 file.writePixels();
147 }
148
149 //vKisAnnotationSP_it beginIt = img -> beginAnnotations();
150 //vKisAnnotationSP_it endIt = img -> endAnnotations();
151 return KoFilter::OK;
152}
153
154#include "kis_openexr_export.moc"
155