PageRenderTime 55ms CodeModel.GetById 10ms app.highlight 39ms RepoModel.GetById 1ms app.codeStats 0ms

/src/FreeImage/Source/OpenEXR/IlmImf/ImfMisc.cpp

https://bitbucket.org/cabalistic/ogredeps/
C++ | 787 lines | 542 code | 172 blank | 73 comment | 80 complexity | aaf31256e57e679a4e004ddebf282ddf MD5 | raw file
  1///////////////////////////////////////////////////////////////////////////
  2//
  3// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
  4// Digital Ltd. LLC
  5// 
  6// All rights reserved.
  7// 
  8// Redistribution and use in source and binary forms, with or without
  9// modification, are permitted provided that the following conditions are
 10// met:
 11// *       Redistributions of source code must retain the above copyright
 12// notice, this list of conditions and the following disclaimer.
 13// *       Redistributions in binary form must reproduce the above
 14// copyright notice, this list of conditions and the following disclaimer
 15// in the documentation and/or other materials provided with the
 16// distribution.
 17// *       Neither the name of Industrial Light & Magic nor the names of
 18// its contributors may be used to endorse or promote products derived
 19// from this software without specific prior written permission. 
 20// 
 21// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 22// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 23// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 24// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 25// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 26// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 27// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 28// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 29// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 30// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 31// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 32//
 33///////////////////////////////////////////////////////////////////////////
 34
 35
 36
 37//-----------------------------------------------------------------------------
 38//
 39//	Miscellaneous helper functions for OpenEXR image file I/O
 40//
 41//-----------------------------------------------------------------------------
 42
 43#include <ImfMisc.h>
 44#include <ImfHeader.h>
 45#include <ImfCompressor.h>
 46#include <ImfChannelList.h>
 47#include <ImfXdr.h>
 48#include <ImathFun.h>
 49#include <Iex.h>
 50#include <ImfStdIO.h>
 51#include <ImfConvert.h>
 52
 53namespace Imf {
 54
 55using Imath::Box2i;
 56using Imath::divp;
 57using Imath::modp;
 58using std::vector;
 59
 60int
 61pixelTypeSize (PixelType type)
 62{
 63    int size;
 64
 65    switch (type)
 66    {
 67      case UINT:
 68	
 69	size = Xdr::size <unsigned int> ();
 70	break;
 71
 72      case HALF:
 73
 74	size = Xdr::size <half> ();
 75	break;
 76
 77      case FLOAT:
 78
 79	size = Xdr::size <float> ();
 80	break;
 81
 82      default:
 83
 84	throw Iex::ArgExc ("Unknown pixel type.");
 85    }
 86
 87    return size;
 88}
 89
 90
 91int
 92numSamples (int s, int a, int b)
 93{
 94    int a1 = divp (a, s);
 95    int b1 = divp (b, s);
 96    return  b1 - a1 + ((a1 * s < a)? 0: 1);
 97}
 98
 99
100size_t
101bytesPerLineTable (const Header &header,
102		   vector<size_t> &bytesPerLine)
103{
104    const Box2i &dataWindow = header.dataWindow();
105    const ChannelList &channels = header.channels();
106
107    bytesPerLine.resize (dataWindow.max.y - dataWindow.min.y + 1);
108
109    for (ChannelList::ConstIterator c = channels.begin();
110	 c != channels.end();
111	 ++c)
112    {
113	int nBytes = pixelTypeSize (c.channel().type) *
114		     (dataWindow.max.x - dataWindow.min.x + 1) /
115		     c.channel().xSampling;
116
117	for (int y = dataWindow.min.y, i = 0; y <= dataWindow.max.y; ++y, ++i)
118	    if (modp (y, c.channel().ySampling) == 0)
119		bytesPerLine[i] += nBytes;
120    }
121
122    size_t maxBytesPerLine = 0;
123
124    for (int y = dataWindow.min.y, i = 0; y <= dataWindow.max.y; ++y, ++i)
125	if (maxBytesPerLine < bytesPerLine[i])
126	    maxBytesPerLine = bytesPerLine[i];
127
128    return maxBytesPerLine;
129}
130
131
132void
133offsetInLineBufferTable (const vector<size_t> &bytesPerLine,
134			 int linesInLineBuffer,
135			 vector<size_t> &offsetInLineBuffer)
136{
137    offsetInLineBuffer.resize (bytesPerLine.size());
138
139    size_t offset = 0;
140
141    for (int i = 0; i < bytesPerLine.size(); ++i)
142    {
143	if (i % linesInLineBuffer == 0)
144	    offset = 0;
145
146	offsetInLineBuffer[i] = offset;
147	offset += bytesPerLine[i];
148    }
149}
150
151
152int
153lineBufferMinY (int y, int minY, int linesInLineBuffer)
154{
155    return ((y - minY) / linesInLineBuffer) * linesInLineBuffer + minY;
156}
157
158
159int
160lineBufferMaxY (int y, int minY, int linesInLineBuffer)
161{
162    return lineBufferMinY (y, minY, linesInLineBuffer) + linesInLineBuffer - 1;
163}
164
165
166Compressor::Format
167defaultFormat (Compressor * compressor)
168{
169    return compressor? compressor->format(): Compressor::XDR;
170}
171
172
173int
174numLinesInBuffer (Compressor * compressor)
175{
176    return compressor? compressor->numScanLines(): 1;
177}
178
179
180void
181copyIntoFrameBuffer (const char *& readPtr,
182		     char * writePtr,
183		     char * endPtr,
184                     size_t xStride,
185		     bool fill,
186		     double fillValue,
187                     Compressor::Format format,
188                     PixelType typeInFrameBuffer,
189                     PixelType typeInFile)
190{
191    //
192    // Copy a horizontal row of pixels from an input
193    // file's line or tile buffer to a frame buffer.
194    //
195
196    if (fill)
197    {
198        //
199        // The file contains no data for this channel.
200        // Store a default value in the frame buffer.
201        //
202
203        switch (typeInFrameBuffer)
204        {
205	  case UINT:
206            
207            {
208                unsigned int fillVal = (unsigned int) (fillValue);
209
210                while (writePtr <= endPtr)
211                {
212                    *(unsigned int *) writePtr = fillVal;
213                    writePtr += xStride;
214                }
215            }
216            break;
217
218          case HALF:
219
220            {
221                half fillVal = half (fillValue);
222
223                while (writePtr <= endPtr)
224                {
225                    *(half *) writePtr = fillVal;
226                    writePtr += xStride;
227                }
228            }
229            break;
230
231          case FLOAT:
232
233            {
234                float fillVal = float (fillValue);
235
236                while (writePtr <= endPtr)
237                {
238                    *(float *) writePtr = fillVal;
239                    writePtr += xStride;
240                }
241            }
242            break;
243
244          default:
245
246            throw Iex::ArgExc ("Unknown pixel data type.");
247        }
248    }
249    else if (format == Compressor::XDR)
250    {
251        //
252        // The the line or tile buffer is in XDR format.
253        //
254        // Convert the pixels from the file's machine-
255        // independent representation, and store the
256        // results in the frame buffer.
257        //
258
259        switch (typeInFrameBuffer)
260        {
261          case UINT:
262    
263            switch (typeInFile)
264            {
265              case UINT:
266
267                while (writePtr <= endPtr)
268                {
269                    Xdr::read <CharPtrIO> (readPtr, *(unsigned int *) writePtr);
270                    writePtr += xStride;
271                }
272                break;
273
274              case HALF:
275
276                while (writePtr <= endPtr)
277                {
278                    half h;
279                    Xdr::read <CharPtrIO> (readPtr, h);
280                    *(unsigned int *) writePtr = halfToUint (h);
281                    writePtr += xStride;
282                }
283                break;
284
285              case FLOAT:
286
287                while (writePtr <= endPtr)
288                {
289                    float f;
290                    Xdr::read <CharPtrIO> (readPtr, f);
291                    *(unsigned int *)writePtr = floatToUint (f);
292                    writePtr += xStride;
293                }
294                break;
295            }
296            break;
297
298          case HALF:
299
300            switch (typeInFile)
301            {
302              case UINT:
303
304                while (writePtr <= endPtr)
305                {
306                    unsigned int ui;
307                    Xdr::read <CharPtrIO> (readPtr, ui);
308                    *(half *) writePtr = uintToHalf (ui);
309                    writePtr += xStride;
310                }
311                break;
312                
313              case HALF:
314
315                while (writePtr <= endPtr)
316                {
317                    Xdr::read <CharPtrIO> (readPtr, *(half *) writePtr);
318                    writePtr += xStride;
319                }
320                break;
321
322              case FLOAT:
323
324                while (writePtr <= endPtr)
325                {
326                    float f;
327                    Xdr::read <CharPtrIO> (readPtr, f);
328                    *(half *) writePtr = floatToHalf (f);
329                    writePtr += xStride;
330                }
331                break;
332            }
333            break;
334
335          case FLOAT:
336
337            switch (typeInFile)
338            {
339              case UINT:
340
341                while (writePtr <= endPtr)
342                {
343                    unsigned int ui;
344                    Xdr::read <CharPtrIO> (readPtr, ui);
345                    *(float *) writePtr = float (ui);
346                    writePtr += xStride;
347                }
348                break;
349
350              case HALF:
351
352                while (writePtr <= endPtr)
353                {
354                    half h;
355                    Xdr::read <CharPtrIO> (readPtr, h);
356                    *(float *) writePtr = float (h);
357                    writePtr += xStride;
358                }
359                break;
360
361              case FLOAT:
362
363                while (writePtr <= endPtr)
364                {
365                    Xdr::read <CharPtrIO> (readPtr, *(float *) writePtr);
366                    writePtr += xStride;
367                }
368                break;
369            }
370            break;
371
372          default:
373
374            throw Iex::ArgExc ("Unknown pixel data type.");
375        }
376    }
377    else
378    {
379        //
380        // The the line or tile buffer is in NATIVE format.
381        // Copy the results into the frame buffer.
382        //
383
384        switch (typeInFrameBuffer)
385        {
386          case UINT:
387    
388            switch (typeInFile)
389            {
390              case UINT:
391
392                while (writePtr <= endPtr)
393                {
394                    for (size_t i = 0; i < sizeof (unsigned int); ++i)
395                        writePtr[i] = readPtr[i];
396
397                    readPtr += sizeof (unsigned int);
398                    writePtr += xStride;
399                }
400                break;
401
402              case HALF:
403
404                while (writePtr <= endPtr)
405                {
406                    half h = *(half *) readPtr;
407                    *(unsigned int *) writePtr = halfToUint (h);
408                    readPtr += sizeof (half);
409                    writePtr += xStride;
410                }
411                break;
412
413              case FLOAT:
414
415                while (writePtr <= endPtr)
416                {
417                    float f;
418
419                    for (size_t i = 0; i < sizeof (float); ++i)
420                        ((char *)&f)[i] = readPtr[i];
421
422                    *(unsigned int *)writePtr = floatToUint (f);
423                    readPtr += sizeof (float);
424                    writePtr += xStride;
425                }
426                break;
427            }
428            break;
429
430          case HALF:
431
432            switch (typeInFile)
433            {
434              case UINT:
435
436                while (writePtr <= endPtr)
437                {
438                    unsigned int ui;
439
440                    for (size_t i = 0; i < sizeof (unsigned int); ++i)
441                        ((char *)&ui)[i] = readPtr[i];
442
443                    *(half *) writePtr = uintToHalf (ui);
444                    readPtr += sizeof (unsigned int);
445                    writePtr += xStride;
446                }
447                break;
448
449              case HALF:
450
451                while (writePtr <= endPtr)
452                {
453                    *(half *) writePtr = *(half *)readPtr;
454                    readPtr += sizeof (half);
455                    writePtr += xStride;
456                }
457                break;
458
459              case FLOAT:
460
461                while (writePtr <= endPtr)
462                {
463                    float f;
464
465                    for (size_t i = 0; i < sizeof (float); ++i)
466                        ((char *)&f)[i] = readPtr[i];
467
468                    *(half *) writePtr = floatToHalf (f);
469                    readPtr += sizeof (float);
470                    writePtr += xStride;
471                }
472                break;
473            }
474            break;
475
476          case FLOAT:
477
478            switch (typeInFile)
479            {
480              case UINT:
481
482                while (writePtr <= endPtr)
483                {
484                    unsigned int ui;
485
486                    for (size_t i = 0; i < sizeof (unsigned int); ++i)
487                        ((char *)&ui)[i] = readPtr[i];
488
489                    *(float *) writePtr = float (ui);
490                    readPtr += sizeof (unsigned int);
491                    writePtr += xStride;
492                }
493                break;
494
495              case HALF:
496
497                while (writePtr <= endPtr)
498                {
499                    half h = *(half *) readPtr;
500                    *(float *) writePtr = float (h);
501                    readPtr += sizeof (half);
502                    writePtr += xStride;
503                }
504                break;
505
506              case FLOAT:
507
508                while (writePtr <= endPtr)
509                {
510                    for (size_t i = 0; i < sizeof (float); ++i)
511                        writePtr[i] = readPtr[i];
512
513                    readPtr += sizeof (float);
514                    writePtr += xStride;
515                }
516                break;
517            }
518            break;
519
520          default:
521
522            throw Iex::ArgExc ("Unknown pixel data type.");
523        }
524    }
525}
526
527
528void
529skipChannel (const char *& readPtr,
530             PixelType typeInFile,
531	     size_t xSize)
532{
533    switch (typeInFile)
534    {
535      case UINT:
536        
537        Xdr::skip <CharPtrIO> (readPtr, Xdr::size <unsigned int> () * xSize);
538        break;
539
540      case HALF:
541
542        Xdr::skip <CharPtrIO> (readPtr, Xdr::size <half> () * xSize);
543        break;
544
545      case FLOAT:
546
547        Xdr::skip <CharPtrIO> (readPtr, Xdr::size <float> () * xSize);
548        break;
549
550      default:
551
552        throw Iex::ArgExc ("Unknown pixel data type.");
553    }
554}
555
556
557void
558convertInPlace (char *& writePtr,
559                const char *& readPtr,
560		PixelType type,
561                size_t numPixels)
562{
563    switch (type)
564    {
565      case UINT:
566    
567        for (int j = 0; j < numPixels; ++j)
568        {
569            Xdr::write <CharPtrIO> (writePtr, *(const unsigned int *) readPtr);
570            readPtr += sizeof(unsigned int);
571        }
572        break;
573    
574      case HALF:
575    
576        for (int j = 0; j < numPixels; ++j)
577        {               
578            Xdr::write <CharPtrIO> (writePtr, *(const half *) readPtr);
579            readPtr += sizeof(half);
580        }
581        break;
582    
583      case FLOAT:
584    
585        for (int j = 0; j < numPixels; ++j)
586        {
587            Xdr::write <CharPtrIO> (writePtr, *(const float *) readPtr);
588            readPtr += sizeof(float);
589        }
590        break;
591    
592      default:
593    
594        throw Iex::ArgExc ("Unknown pixel data type.");
595    }
596}
597
598
599void
600copyFromFrameBuffer (char *& writePtr,
601		     const char *& readPtr,
602                     const char * endPtr,
603		     size_t xStride,
604                     Compressor::Format format,
605		     PixelType type)
606{
607    //
608    // Copy a horizontal row of pixels from a frame
609    // buffer to an output file's line or tile buffer.
610    //
611
612    if (format == Compressor::XDR)
613    {
614        //
615        // The the line or tile buffer is in XDR format.
616        //
617
618        switch (type)
619        {
620          case UINT:
621
622            while (readPtr <= endPtr)
623            {
624                Xdr::write <CharPtrIO> (writePtr,
625                                        *(const unsigned int *) readPtr);
626                readPtr += xStride;
627            }
628            break;
629
630          case HALF:
631
632            while (readPtr <= endPtr)
633            {
634                Xdr::write <CharPtrIO> (writePtr, *(const half *) readPtr);
635                readPtr += xStride;
636            }
637            break;
638
639          case FLOAT:
640
641            while (readPtr <= endPtr)
642            {
643                Xdr::write <CharPtrIO> (writePtr, *(const float *) readPtr);
644                readPtr += xStride;
645            }
646            break;
647
648          default:
649
650            throw Iex::ArgExc ("Unknown pixel data type.");
651        }
652    }
653    else
654    {
655        //
656        // The the line or tile buffer is in NATIVE format.
657        //
658
659        switch (type)
660        {
661          case UINT:
662
663            while (readPtr <= endPtr)
664            {
665                for (size_t i = 0; i < sizeof (unsigned int); ++i)
666                    *writePtr++ = readPtr[i];
667
668                readPtr += xStride;
669            }
670            break;
671
672          case HALF:
673
674            while (readPtr <= endPtr)
675            {
676                *(half *) writePtr = *(const half *) readPtr;
677                writePtr += sizeof (half);
678                readPtr += xStride;
679            }
680            break;
681
682          case FLOAT:
683
684            while (readPtr <= endPtr)
685            {
686                for (size_t i = 0; i < sizeof (float); ++i)
687                    *writePtr++ = readPtr[i];
688
689                readPtr += xStride;
690            }
691            break;
692            
693          default:
694
695            throw Iex::ArgExc ("Unknown pixel data type.");
696        }
697    }
698}
699
700
701void
702fillChannelWithZeroes (char *& writePtr,
703		       Compressor::Format format,
704		       PixelType type,
705		       size_t xSize)
706{
707    if (format == Compressor::XDR)
708    {
709        //
710        // Fill with data in XDR format.
711        //
712
713        switch (type)
714        {
715          case UINT:
716
717            for (int j = 0; j < xSize; ++j)
718                Xdr::write <CharPtrIO> (writePtr, (unsigned int) 0);
719
720            break;
721
722          case HALF:
723
724            for (int j = 0; j < xSize; ++j)
725                Xdr::write <CharPtrIO> (writePtr, (half) 0);
726
727            break;
728
729          case FLOAT:
730
731            for (int j = 0; j < xSize; ++j)
732                Xdr::write <CharPtrIO> (writePtr, (float) 0);
733
734            break;
735            
736          default:
737
738            throw Iex::ArgExc ("Unknown pixel data type.");
739        }
740    }
741    else
742    {
743        //
744        // Fill with data in NATIVE format.
745        //
746
747        switch (type)
748        {
749          case UINT:
750
751            for (int j = 0; j < xSize; ++j)
752            {
753                static const unsigned int ui = 0;
754
755                for (size_t i = 0; i < sizeof (ui); ++i)
756                    *writePtr++ = ((char *) &ui)[i];
757            }
758            break;
759
760          case HALF:
761
762            for (int j = 0; j < xSize; ++j)
763            {
764                *(half *) writePtr = half (0);
765                writePtr += sizeof (half);
766            }
767            break;
768
769          case FLOAT:
770
771            for (int j = 0; j < xSize; ++j)
772            {
773                static const float f = 0;
774
775                for (size_t i = 0; i < sizeof (f); ++i)
776                    *writePtr++ = ((char *) &f)[i];
777            }
778            break;
779            
780          default:
781
782            throw Iex::ArgExc ("Unknown pixel data type.");
783        }
784    }
785}
786
787} // namespace Imf