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