1 /*
2 Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
3 All Rights Reserved.
4 
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8 * Redistributions of source code must retain the above copyright
9   notice, this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright
11   notice, this list of conditions and the following disclaimer in the
12   documentation and/or other materials provided with the distribution.
13 * Neither the name of Sony Pictures Imageworks nor the names of its
14   contributors may be used to endorse or promote products derived from
15   this software without specific prior written permission.
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28 
29 #include <OpenColorIO/OpenColorIO.h>
30 
31 #include <sstream>
32 #include <iostream>
33 #include <cassert>
34 #include <cstdlib>
35 #include <cstring>
36 
37 #include "ImagePacking.h"
38 
39 OCIO_NAMESPACE_ENTER
40 {
41 
42     namespace
43     {
44         // GENERIC CASE, SLOW BUT ALWAYS WORKS
45 
46         void PackRGBAFromImageDesc_Generic(const GenericImageDesc& srcImg,
47                                            float* outputBuffer,
48                                            int* numPixelsCopied,
49                                            int outputBufferSize,
50                                            long imagePixelStartIndex)
51         {
52             assert(outputBuffer);
53             assert(numPixelsCopied);
54 
55             long imgWidth = srcImg.width;
56             long imgHeight = srcImg.height;
57             long imgPixels = imgWidth * imgHeight;
58 
59             if(imagePixelStartIndex<0 || imagePixelStartIndex>=imgPixels)
60             {
61                 *numPixelsCopied = 0;
62                 return;
63             }
64 
65             ptrdiff_t xStrideBytes  = srcImg.xStrideBytes;
66             ptrdiff_t yStrideBytes  = srcImg.yStrideBytes;
67             long yIndex = imagePixelStartIndex / imgWidth;
68             long xIndex = imagePixelStartIndex % imgWidth;
69 
70             // Figure out our initial ptr positions
71             char* rRow = reinterpret_cast<char*>(srcImg.rData) +
72                 yStrideBytes * yIndex;
73             char* gRow = reinterpret_cast<char*>(srcImg.gData) +
74                 yStrideBytes * yIndex;
75             char* bRow = reinterpret_cast<char*>(srcImg.bData) +
76                 yStrideBytes * yIndex;
77             char* aRow = NULL;
78 
79             float* rPtr = reinterpret_cast<float*>(rRow + xStrideBytes*xIndex);
80             float* gPtr = reinterpret_cast<float*>(gRow + xStrideBytes*xIndex);
81             float* bPtr = reinterpret_cast<float*>(bRow + xStrideBytes*xIndex);
82             float* aPtr = NULL;
83 
84             if(srcImg.aData)
85             {
86                 aRow = reinterpret_cast<char*>(srcImg.aData) + yStrideBytes * yIndex;
87                 aPtr = reinterpret_cast<float*>(aRow + xStrideBytes*xIndex);
88             }
89 
90             if(aPtr)
91             {
92                 int pixelsCopied = 0;
93                 while(pixelsCopied < outputBufferSize)
94                 {
95                     outputBuffer[4*pixelsCopied] = *rPtr;
96                     outputBuffer[4*pixelsCopied+1] = *gPtr;
97                     outputBuffer[4*pixelsCopied+2] = *bPtr;
98                     outputBuffer[4*pixelsCopied+3] = *aPtr;
99                     pixelsCopied++;
100                     xIndex++;
101 
102                     // Jump to the next scanline
103                     if(xIndex == imgWidth)
104                     {
105                         yIndex += 1;
106                         if(yIndex == imgHeight)
107                         {
108                             *numPixelsCopied = pixelsCopied;
109                             return;
110                         }
111 
112                         xIndex = 0;
113                         rRow += yStrideBytes;
114                         gRow += yStrideBytes;
115                         bRow += yStrideBytes;
116                         aRow += yStrideBytes;
117 
118                         rPtr = reinterpret_cast<float*>(rRow);
119                         gPtr = reinterpret_cast<float*>(gRow);
120                         bPtr = reinterpret_cast<float*>(bRow);
121                         aPtr = reinterpret_cast<float*>(aRow);
122                     }
123                     // Jump to the next pixel
124                     else
125                     {
126                         rPtr = reinterpret_cast<float*>(
127                             reinterpret_cast<char*>(rPtr) + xStrideBytes);
128                         gPtr = reinterpret_cast<float*>(
129                             reinterpret_cast<char*>(gPtr) + xStrideBytes);
130                         bPtr = reinterpret_cast<float*>(
131                             reinterpret_cast<char*>(bPtr) + xStrideBytes);
132                         aPtr = reinterpret_cast<float*>(
133                             reinterpret_cast<char*>(aPtr) + xStrideBytes);
134                     }
135                 }
136 
137                 *numPixelsCopied = pixelsCopied;
138             }
139             else
140             {
141                 int pixelsCopied = 0;
142                 while(pixelsCopied < outputBufferSize)
143                 {
144                     outputBuffer[4*pixelsCopied] = *rPtr;
145                     outputBuffer[4*pixelsCopied+1] = *gPtr;
146                     outputBuffer[4*pixelsCopied+2] = *bPtr;
147                     outputBuffer[4*pixelsCopied+3] = 0.0;
148                     pixelsCopied++;
149                     xIndex++;
150 
151                     // Jump to the next scanline
152                     if(xIndex == imgWidth)
153                     {
154                         yIndex += 1;
155                         if(yIndex == imgHeight)
156                         {
157                             *numPixelsCopied = pixelsCopied;
158                             return;
159                         }
160 
161                         xIndex = 0;
162                         rRow += yStrideBytes;
163                         gRow += yStrideBytes;
164                         bRow += yStrideBytes;
165 
166                         rPtr = reinterpret_cast<float*>(rRow);
167                         gPtr = reinterpret_cast<float*>(gRow);
168                         bPtr = reinterpret_cast<float*>(bRow);
169                     }
170                     // Jump to the next pixel
171                     else
172                     {
173                         rPtr = reinterpret_cast<float*>(
174                             reinterpret_cast<char*>(rPtr) + xStrideBytes);
175                         gPtr = reinterpret_cast<float*>(
176                             reinterpret_cast<char*>(gPtr) + xStrideBytes);
177                         bPtr = reinterpret_cast<float*>(
178                             reinterpret_cast<char*>(bPtr) + xStrideBytes);
179                     }
180                 }
181 
182                 *numPixelsCopied = pixelsCopied;
183             }
184         }
185 
186         void UnpackRGBAToImageDesc_Generic(GenericImageDesc& dstImg,
187                                            float* inputBuffer,
188                                            int numPixelsToUnpack,
189                                            long imagePixelStartIndex)
190         {
191             assert(inputBuffer);
192 
193             long imgWidth = dstImg.width;
194             long imgHeight = dstImg.height;
195             long imgPixels = imgWidth * imgHeight;
196 
197             if(imagePixelStartIndex<0 || imagePixelStartIndex>=imgPixels)
198             {
199                 return;
200             }
201 
202             ptrdiff_t xStrideBytes  = dstImg.xStrideBytes;
203             ptrdiff_t yStrideBytes  = dstImg.yStrideBytes;
204             long yIndex = imagePixelStartIndex / imgWidth;
205             long xIndex = imagePixelStartIndex % imgWidth;
206 
207             // Figure out our initial ptr positions
208             char* rRow = reinterpret_cast<char*>(dstImg.rData) +
209                 yStrideBytes * yIndex;
210             char* gRow = reinterpret_cast<char*>(dstImg.gData) +
211                 yStrideBytes * yIndex;
212             char* bRow = reinterpret_cast<char*>(dstImg.bData) +
213                 yStrideBytes * yIndex;
214             char* aRow = NULL;
215 
216             float* rPtr = reinterpret_cast<float*>(rRow + xStrideBytes*xIndex);
217             float* gPtr = reinterpret_cast<float*>(gRow + xStrideBytes*xIndex);
218             float* bPtr = reinterpret_cast<float*>(bRow + xStrideBytes*xIndex);
219             float* aPtr = NULL;
220 
221             if(dstImg.aData)
222             {
223                 aRow = reinterpret_cast<char*>(dstImg.aData) + yStrideBytes * yIndex;
224                 aPtr = reinterpret_cast<float*>(aRow + xStrideBytes*xIndex);
225             }
226 
227             if(aPtr)
228             {
229                 int pixelsCopied = 0;
230                 while(pixelsCopied < numPixelsToUnpack)
231                 {
232                     *rPtr = inputBuffer[4*pixelsCopied];
233                     *gPtr = inputBuffer[4*pixelsCopied+1];
234                     *bPtr = inputBuffer[4*pixelsCopied+2];
235                     *aPtr = inputBuffer[4*pixelsCopied+3];
236 
237                     pixelsCopied++;
238                     xIndex++;
239 
240                     // Jump to the next scanline
241                     if(xIndex == imgWidth)
242                     {
243                         yIndex += 1;
244                         if(yIndex == imgHeight)
245                         {
246                             return;
247                         }
248 
249                         xIndex = 0;
250                         rRow += yStrideBytes;
251                         gRow += yStrideBytes;
252                         bRow += yStrideBytes;
253                         aRow += yStrideBytes;
254 
255                         rPtr = reinterpret_cast<float*>(rRow);
256                         gPtr = reinterpret_cast<float*>(gRow);
257                         bPtr = reinterpret_cast<float*>(bRow);
258                         aPtr = reinterpret_cast<float*>(aRow);
259                     }
260                     // Jump to the next pixel
261                     else
262                     {
263                         rPtr = reinterpret_cast<float*>(
264                             reinterpret_cast<char*>(rPtr) + xStrideBytes);
265                         gPtr = reinterpret_cast<float*>(
266                             reinterpret_cast<char*>(gPtr) + xStrideBytes);
267                         bPtr = reinterpret_cast<float*>(
268                             reinterpret_cast<char*>(bPtr) + xStrideBytes);
269                         aPtr = reinterpret_cast<float*>(
270                             reinterpret_cast<char*>(aPtr) + xStrideBytes);
271                     }
272                 }
273             }
274             else
275             {
276                 int pixelsCopied = 0;
277                 while(pixelsCopied < numPixelsToUnpack)
278                 {
279                     *rPtr = inputBuffer[4*pixelsCopied];
280                     *gPtr = inputBuffer[4*pixelsCopied+1];
281                     *bPtr = inputBuffer[4*pixelsCopied+2];
282 
283                     pixelsCopied++;
284                     xIndex++;
285 
286                     // Jump to the next scanline
287                     if(xIndex == imgWidth)
288                     {
289                         yIndex += 1;
290                         if(yIndex == imgHeight)
291                         {
292                             return;
293                         }
294 
295                         xIndex = 0;
296                         rRow += yStrideBytes;
297                         gRow += yStrideBytes;
298                         bRow += yStrideBytes;
299 
300                         rPtr = reinterpret_cast<float*>(rRow);
301                         gPtr = reinterpret_cast<float*>(gRow);
302                         bPtr = reinterpret_cast<float*>(bRow);
303                     }
304                     // Jump to the next pixel
305                     else
306                     {
307                         rPtr = reinterpret_cast<float*>(
308                             reinterpret_cast<char*>(rPtr) + xStrideBytes);
309                         gPtr = reinterpret_cast<float*>(
310                             reinterpret_cast<char*>(gPtr) + xStrideBytes);
311                         bPtr = reinterpret_cast<float*>(
312                             reinterpret_cast<char*>(bPtr) + xStrideBytes);
313                     }
314                 }
315             }
316         }
317 
318     }
319 
320 
321     /*
322     namespace
323     {
324 
325         void PackRGBAFromImageDesc_RGBAMemcpy(const GenericImageDesc& srcImg,
326                                               float* outputBuffer,
327                                               int* numPixelsCopied,
328                                               int outputBufferSize,
329                                               int imagePixelStartIndex)
330         {
331             assert(outputBuffer);
332             assert(numPixelsCopied);
333 
334             long imgWidth = srcImg.getWidth();
335             long imgHeight = srcImg.getHeight();
336             long imgPixels = srcImg.getNumPixels();
337 
338             if(imagePixelStartIndex<0 || imagePixelStartIndex>=imgPixels)
339             {
340                 *numPixelsCopied = 0;
341                 return;
342             }
343 
344             ptrdiff_t xStrideBytes  = srcImg.getXStrideBytes();
345             ptrdiff_t yStrideBytes  = srcImg.getYStrideBytes();
346             int yIndex = imagePixelStartIndex / imgWidth;
347             int xIndex = imagePixelStartIndex % imgWidth;
348 
349             // Figure out our initial ptr positions
350             char* imgRow = reinterpret_cast<char*>(srcImg.getRData()) +
351                 yStrideBytes * yIndex;
352 
353             char* imgPtr = imgRow + xStrideBytes*xIndex;
354 
355             int totalPixelsCopied = 0;
356             int pixelsRemainingToCopy = outputBufferSize;
357 
358             while(pixelsRemainingToCopy>0 && yIndex < imgHeight)
359             {
360                 int imgScanlinePixels = imgWidth - xIndex;
361                 int numPixels = std::min(imgScanlinePixels,
362                                          pixelsRemainingToCopy);
363                 memcpy(outputBuffer+totalPixelsCopied,
364                        imgPtr, numPixels);
365 
366                 yIndex += 1;
367                 xIndex = 0;
368 
369                 imgRow += yStrideBytes;
370                 imgPtr = imgRow;
371                 totalPixelsCopied += numPixels;
372                 pixelsRemainingToCopy -= numPixels;
373             }
374 
375             if(numPixelsCopied) *numPixelsCopied = totalPixelsCopied;
376         }
377     }
378     */
379 
380     ////////////////////////////////////////////////////////////////////////////
381 
382     // TODO: Add optimized codepaths to image packing / unpacking
383 
384     void PackRGBAFromImageDesc(const GenericImageDesc& srcImg,
385                                float* outputBuffer,
386                                int* numPixelsCopied,
387                                int outputBufferSize,
388                                long imagePixelStartIndex)
389     {
390         PackRGBAFromImageDesc_Generic(srcImg, outputBuffer,
391                                       numPixelsCopied,
392                                       outputBufferSize,
393                                       imagePixelStartIndex);
394     }
395 
396 
397     void UnpackRGBAToImageDesc(GenericImageDesc& dstImg,
398                                float* inputBuffer,
399                                int numPixelsToUnpack,
400                                long imagePixelStartIndex)
401     {
402         UnpackRGBAToImageDesc_Generic(dstImg, inputBuffer,
403                                       numPixelsToUnpack,
404                                       imagePixelStartIndex);
405     }
406 }
407 OCIO_NAMESPACE_EXIT
408