1 //
2 // SPDX-License-Identifier: BSD-3-Clause
3 // Copyright (c) Contributors to the OpenEXR Project.
4 //
5 
6 //----------------------------------------------------------------------------
7 //
8 //      class DeepImageChannel
9 //
10 //----------------------------------------------------------------------------
11 #include "ImfUtilExport.h"
12 #include <ImathExport.h>
13 #include <ImathNamespace.h>
14 
15 IMATH_INTERNAL_NAMESPACE_HEADER_ENTER
16 class IMFUTIL_EXPORT_TYPE half;
17 IMATH_INTERNAL_NAMESPACE_HEADER_EXIT
18 
19 #define COMPILING_IMF_DEEP_IMAGE_CHANNEL
20 
21 #include "ImfDeepImageChannel.h"
22 #include "ImfDeepImageLevel.h"
23 #include <Iex.h>
24 
25 using namespace IMATH_NAMESPACE;
26 using namespace IEX_NAMESPACE;
27 using namespace std;
28 
29 OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER
30 
31 
DeepImageChannel(DeepImageLevel & level,bool pLinear)32 DeepImageChannel::DeepImageChannel
33     (DeepImageLevel &level,
34      bool pLinear)
35 :
36     ImageChannel (level, 1, 1, pLinear)
37 {
38     // empty
39 }
40 
41 
~DeepImageChannel()42 DeepImageChannel::~DeepImageChannel ()
43 {
44     // empty
45 }
46 
47 DeepImageLevel &
deepLevel()48 DeepImageChannel::deepLevel ()
49 {
50     return static_cast <DeepImageLevel &> (level());
51 }
52 
53 
54 const DeepImageLevel &
deepLevel() const55 DeepImageChannel::deepLevel () const
56 {
57     return static_cast <const DeepImageLevel &> (level());
58 }
59 
60 
61 SampleCountChannel &
sampleCounts()62 DeepImageChannel::sampleCounts ()
63 {
64     return deepLevel().sampleCounts();
65 }
66 
67 
68 const SampleCountChannel &
sampleCounts() const69 DeepImageChannel::sampleCounts () const
70 {
71     return deepLevel().sampleCounts();
72 }
73 
74 
75 void
resize()76 DeepImageChannel::resize ()
77 {
78     ImageChannel::resize();
79 }
80 
81 //-----------------------------------------------------------------------------
82 
83 template <class T>
TypedDeepImageChannel(DeepImageLevel & level,bool pLinear)84 TypedDeepImageChannel<T>::TypedDeepImageChannel
85     (DeepImageLevel &level,
86      bool pLinear)
87 :
88     DeepImageChannel (level, pLinear),
89     _sampleListPointers (0),
90     _base (0),
91     _sampleBuffer (0)
92 {
93     resize();
94 }
95 
96 
97 template <class T>
~TypedDeepImageChannel()98 TypedDeepImageChannel<T>::~TypedDeepImageChannel ()
99 {
100     delete [] _sampleListPointers;
101     delete [] _sampleBuffer;
102 }
103 
104 
105 template <class T>
106 DeepSlice
slice() const107 TypedDeepImageChannel<T>::slice () const
108 {
109     return DeepSlice (pixelType(),                  // type
110                       (char *) _base,               // base
111                       sizeof (T*),                  // xStride
112                       pixelsPerRow() * sizeof (T*), // yStride
113                       sizeof (T),                   // sampleStride
114                       xSampling(),
115                       ySampling());
116 }
117 template <class T>
118 void
setSamplesToZero(size_t i,unsigned int oldNumSamples,unsigned int newNumSamples)119 TypedDeepImageChannel<T>::setSamplesToZero
120     (size_t i,
121      unsigned int oldNumSamples,
122      unsigned int newNumSamples)
123 {
124     //
125     // Expand the size of a sample list for a single pixel and
126     // set the new samples in the list to 0.
127     //
128     // i                The position of the affected pixel in
129     //                  the channel's _sampleListPointers.
130     //
131     // oldNumSamples    Original number of samples in the sample list.
132     //
133     // newNumSamples    New number of samples in the sample list.
134     //
135 
136     for (unsigned int j = oldNumSamples; j < newNumSamples; ++j)
137         _sampleListPointers[i][j] = 0;
138 }
139 
140 
141 template <class T>
142 void
moveSampleList(size_t i,unsigned int oldNumSamples,unsigned int newNumSamples,size_t newSampleListPosition)143 TypedDeepImageChannel<T>::moveSampleList
144     (size_t i,
145      unsigned int oldNumSamples,
146      unsigned int newNumSamples,
147      size_t newSampleListPosition)
148 {
149     //
150     // Resize the sample list for a single pixel and move it to a new
151     // position in the sample buffer for this channel.
152     //
153     // i                        The position of the affected pixel in
154     //                          the channel's _sampleListPointers.
155     //
156     // oldNumSamples            Original number of samples in sample list.
157     //
158     // newNumSamples            New number of samples in the sample list.
159     //                          If the new number of samples is larger than
160     //                          the old number of samples for a given sample
161     //                          list, then the end of the new sample list
162     //                          is filled with zeroes.  If the new number of
163     //                          samples is smaller than the old one, then
164     //                          samples at the end of the old sample list
165     //                          are discarded.
166     //
167     // newSampleListPosition    The new position of the sample list in the
168     //                          sample buffer.
169     //
170 
171     T * oldSampleList = _sampleListPointers[i];
172     T * newSampleList = _sampleBuffer + newSampleListPosition;
173 
174     if (oldNumSamples > newNumSamples)
175     {
176         for (unsigned int j = 0; j < newNumSamples; ++j)
177             newSampleList[j] = oldSampleList[j];
178     }
179     else
180     {
181         for (unsigned int j = 0; j < oldNumSamples; ++j)
182             newSampleList[j] = oldSampleList[j];
183 
184         for (unsigned int j = oldNumSamples; j < newNumSamples; ++j)
185             newSampleList[j] = 0;
186     }
187 
188     _sampleListPointers[i] = newSampleList;
189 }
190 
191 
192 template <class T>
193 void
moveSamplesToNewBuffer(const unsigned int * oldNumSamples,const unsigned int * newNumSamples,const size_t * newSampleListPositions)194 TypedDeepImageChannel<T>::moveSamplesToNewBuffer
195     (const unsigned int * oldNumSamples,
196      const unsigned int * newNumSamples,
197      const size_t * newSampleListPositions)
198 {
199     //
200     // Allocate a new sample buffer for this channel.
201     // Copy the sample lists for all pixels into the new buffer.
202     // Then delete the old sample buffer.
203     //
204     // oldNumSamples            Number of samples in each sample list in the
205     //                          old sample buffer.
206     //
207     // newNumSamples            Number of samples in each sample list in
208     //                          the new sample buffer.  If the new number
209     //                          of samples is larger than the old number of
210     //                          samples for a given sample list, then the
211     //                          end of the new sample list is filled with
212     //                          zeroes.  If the new number of samples is
213     //                          smaller than the old one, then samples at
214     //                          the end of the old sample list are discarded.
215     //
216     // newSampleListPositions   The positions of the new sample lists in the
217     //                          new sample buffer.
218     //
219 
220     T * oldSampleBuffer = _sampleBuffer;
221     _sampleBuffer = new T [sampleCounts().sampleBufferSize()];
222 
223     for (size_t i = 0; i < numPixels(); ++i)
224     {
225         T * oldSampleList = _sampleListPointers[i];
226         T * newSampleList = _sampleBuffer + newSampleListPositions[i];
227 
228         if (oldNumSamples[i] > newNumSamples[i])
229         {
230             for (unsigned int j = 0; j < newNumSamples[i]; ++j)
231                 newSampleList[j] = oldSampleList[j];
232         }
233         else
234         {
235             for (unsigned int j = 0; j < oldNumSamples[i]; ++j)
236                 newSampleList[j] = oldSampleList[j];
237 
238             for (unsigned int j = oldNumSamples[i]; j < newNumSamples[i]; ++j)
239                 newSampleList[j] = 0;
240         }
241 
242         _sampleListPointers[i] = newSampleList;
243     }
244 
245     delete [] oldSampleBuffer;
246 }
247 
248 
249 template <class T>
250 void
initializeSampleLists()251 TypedDeepImageChannel<T>::initializeSampleLists ()
252 {
253     //
254     // Allocate a new set of sample lists for this channel, and
255     // construct zero-filled sample lists for the pixels.
256     //
257 
258     delete [] _sampleBuffer;
259 
260     _sampleBuffer = 0;          // set to 0 to prevent double deletion
261                                 // in case of an exception
262 
263     const unsigned int * numSamples = sampleCounts().numSamples();
264     const size_t * sampleListPositions = sampleCounts().sampleListPositions();
265 
266     _sampleBuffer = new T [sampleCounts().sampleBufferSize()];
267 
268     resetBasePointer();
269 
270     for (size_t i = 0; i < numPixels(); ++i)
271     {
272         _sampleListPointers[i] = _sampleBuffer + sampleListPositions[i];
273 
274         for (unsigned int j = 0; j < numSamples[i]; ++j)
275             _sampleListPointers[i][j] = T (0);
276     }
277 }
278 
279 template <class T>
280 void
resize()281 TypedDeepImageChannel<T>::resize ()
282 {
283     DeepImageChannel::resize();
284 
285     delete [] _sampleListPointers;
286     _sampleListPointers = 0;
287     _sampleListPointers = new T * [numPixels()];
288     initializeSampleLists();
289 }
290 
291 
292 template <class T>
293 void
resetBasePointer()294 TypedDeepImageChannel<T>::resetBasePointer ()
295 {
296     _base = _sampleListPointers -
297             level().dataWindow().min.y * pixelsPerRow() -
298             level().dataWindow().min.x;
299 }
300 
301 
302 template <>
303 PixelType
pixelType() const304 TypedDeepImageChannel<half>::pixelType () const
305 {
306     return HALF;
307 }
308 
309 
310 template <>
311 PixelType
pixelType() const312 TypedDeepImageChannel<float>::pixelType () const
313 {
314     return FLOAT;
315 }
316 
317 
318 template <>
319 PixelType
pixelType() const320 TypedDeepImageChannel<unsigned int>::pixelType () const
321 {
322     return UINT;
323 }
324 
325 
326 template class IMFUTIL_EXPORT_TEMPLATE_INSTANCE TypedDeepImageChannel<half>;
327 template class IMFUTIL_EXPORT_TEMPLATE_INSTANCE TypedDeepImageChannel<float>;
328 template class IMFUTIL_EXPORT_TEMPLATE_INSTANCE TypedDeepImageChannel<unsigned int>;
329 
330 
331 OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT
332