1 /*
2     delaboratory - color correction utility
3     Copyright (C) 2011 Jacek Poplawski
4 
5     This program is free software: you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation, either version 3 of the License, or
8     (at your option) any later version.
9 
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14 
15     You should have received a copy of the GNU General Public License
16     along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #include "renderer.h"
20 #include "project.h"
21 #include "image.h"
22 #include "base_layer.h"
23 #include <iostream>
24 #include "layer_processor.h"
25 #include "str.h"
26 #include "logger.h"
27 #include "channel_manager.h"
28 #include "layer_stack.h"
29 #include "conversion_processor.h"
30 #include "canvas.h"
31 
renderChannel(const deImage & image,int c,unsigned char * data,deChannelManager & channelManager,bool reversed)32 void renderChannel(const deImage& image, int c, unsigned char* data, deChannelManager& channelManager, bool reversed)
33 {
34     const deSize& s = image.getChannelSize();
35 
36     const deValue* pixels = image.startRead(c);
37 
38     if (!pixels)
39     {
40         logError("can't render channel - NULL pixels");
41         return;
42     }
43 
44     int n = s.getN();
45     int i;
46     int pos = 0;
47     for (i = 0; i < n; i++)
48     {
49         deValue s = pixels[i];
50 
51         if (reversed)
52         {
53             s = 1.0 - s;
54         }
55 
56         unsigned char ss = 255 * s;
57 
58         data[pos] = ss;
59         pos++;
60         data[pos] = ss;
61         pos++;
62         data[pos] = ss;
63         pos++;
64     }
65 
66     image.finishRead(c);
67 
68 }
69 
deRenderer(deChannelManager & _channelManager)70 deRenderer::deRenderer(deChannelManager& _channelManager)
71 :size(0,0),
72  channelManager(_channelManager)
73 {
74 }
75 
~deRenderer()76 deRenderer::~deRenderer()
77 {
78 }
79 
prepareImage(const deViewManager & viewManager,deLayerProcessor & layerProcessor,deLayerStack & layerStack)80 bool deRenderer::prepareImage(const deViewManager& viewManager, deLayerProcessor& layerProcessor, deLayerStack& layerStack)
81 {
82     if (channelManager.isImageEmpty())
83     {
84         logError("image is empty");
85         return false;
86     }
87 
88     mutex.lock();
89 
90     int viewV = viewManager.getView();
91     int view = layerProcessor.getLastValidLayer();
92     if (view > viewV)
93     {
94         view = viewV;
95     }
96 
97     if (view < 0)
98     {
99         logError("view < 0");
100         mutex.unlock();
101         return false;
102     }
103 
104     const deBaseLayer* layer = layerStack.startReadLayer(view);
105 
106     if (layer)
107     {
108         const deImage& layerImage = layer->getLayerImage();
109 
110         if (viewManager.isSingleChannel())
111         {
112             bool reversed = false;
113             deColorSpace colorSpace = layerImage.getColorSpace();
114             if (colorSpace == deColorSpaceCMYK)
115             {
116                 reversed = true;
117             }
118             renderChannel(layerImage, viewManager.getChannel(), getCurrentImageData(), channelManager, reversed);
119             renderedImage.clearError();
120         }
121         else
122         {
123             deConversionProcessor p;
124             if (!p.renderImageToRGBNew(layerImage, getCurrentImageData()))
125             {
126                 logError("render image FAILED");
127                 renderedImage.setError();
128             }
129             else
130             {
131                 renderedImage.clearError();
132             }
133         }
134     }
135     else
136     {
137         logError("no layer in renderer");
138     }
139 
140     layerStack.finishReadLayer(view);
141 
142     mutex.unlock();
143 
144     return true;
145 }
146 
render(deCanvas & canvas)147 bool deRenderer::render(deCanvas& canvas)
148 {
149     mutex.lock();
150 
151     bool result = renderedImage.render(canvas);
152 
153     if (!result)
154     {
155         canvas.clear();
156     }
157 
158     mutex.unlock();
159 
160     return result;
161 }
162 
getCurrentImageData()163 unsigned char* deRenderer::getCurrentImageData()
164 {
165     const deSize& s = channelManager.getChannelSizeFromChannelManager();
166     renderedImage.setSize(s);
167     return renderedImage.getCurrentImageData();
168 }
169