📄 imfrgbafile.cpp
字号:
Lock lock (*_toYca); return _toYca->currentScanLine(); } else { return _outputFile->currentScanLine(); }}const Header &RgbaOutputFile::header () const{ return _outputFile->header();}const FrameBuffer &RgbaOutputFile::frameBuffer () const{ return _outputFile->frameBuffer();}const Imath::Box2i &RgbaOutputFile::displayWindow () const{ return _outputFile->header().displayWindow();}const Imath::Box2i &RgbaOutputFile::dataWindow () const{ return _outputFile->header().dataWindow();}float RgbaOutputFile::pixelAspectRatio () const{ return _outputFile->header().pixelAspectRatio();}const Imath::V2fRgbaOutputFile::screenWindowCenter () const{ return _outputFile->header().screenWindowCenter();}float RgbaOutputFile::screenWindowWidth () const{ return _outputFile->header().screenWindowWidth();}LineOrderRgbaOutputFile::lineOrder () const{ return _outputFile->header().lineOrder();}CompressionRgbaOutputFile::compression () const{ return _outputFile->header().compression();}RgbaChannelsRgbaOutputFile::channels () const{ return rgbaChannels (_outputFile->header().channels());}void RgbaOutputFile::updatePreviewImage (const PreviewRgba newPixels[]){ _outputFile->updatePreviewImage (newPixels);}void RgbaOutputFile::setYCRounding (unsigned int roundY, unsigned int roundC){ if (_toYca) { Lock lock (*_toYca); _toYca->setYCRounding (roundY, roundC); }}void RgbaOutputFile::breakScanLine (int y, int offset, int length, char c){ _outputFile->breakScanLine (y, offset, length, c);}class RgbaInputFile::FromYca: public Mutex{ public: FromYca (InputFile &inputFile, RgbaChannels rgbaChannels); ~FromYca (); void setFrameBuffer (Rgba *base, size_t xStride, size_t yStride); void readPixels (int scanLine1, int scanLine2); private: void readPixels (int scanLine); void rotateBuf1 (int d); void rotateBuf2 (int d); void readYCAScanLine (int y, Rgba buf[]); void padTmpBuf (); InputFile & _inputFile; bool _readC; int _xMin; int _yMin; int _yMax; int _width; int _height; int _currentScanLine; LineOrder _lineOrder; V3f _yw; Rgba * _buf1[N + 2]; Rgba * _buf2[3]; Rgba * _tmpBuf; Rgba * _fbBase; size_t _fbXStride; size_t _fbYStride;};RgbaInputFile::FromYca::FromYca (InputFile &inputFile, RgbaChannels rgbaChannels): _inputFile (inputFile){ _readC = (rgbaChannels & WRITE_C)? true: false; const Box2i dw = _inputFile.header().dataWindow(); _xMin = dw.min.x; _yMin = dw.min.y; _yMax = dw.max.y; _width = dw.max.x - dw.min.x + 1; _height = dw.max.y - dw.min.y + 1; _currentScanLine = dw.min.y - N - 2; _lineOrder = _inputFile.header().lineOrder(); _yw = ywFromHeader (_inputFile.header()); for (int i = 0; i < N + 2; ++i) _buf1[i] = new Rgba[_width]; for (int i = 0; i < 3; ++i) _buf2[i] = new Rgba[_width]; _tmpBuf = new Rgba[_width + N - 1]; _fbBase = 0; _fbXStride = 0; _fbYStride = 0;}RgbaInputFile::FromYca::~FromYca (){ for (int i = 0; i < N + 2; ++i) delete [] _buf1[i]; for (int i = 0; i < 3; ++i) delete [] _buf2[i]; delete [] _tmpBuf;}voidRgbaInputFile::FromYca::setFrameBuffer (Rgba *base, size_t xStride, size_t yStride){ if (_fbBase == 0) { FrameBuffer fb; fb.insert ("Y", Slice (HALF, // type (char *) &_tmpBuf[N2 - _xMin].g, // base sizeof (Rgba), // xStride 0, // yStride 1, // xSampling 1, // ySampling 0.5)); // fillValue if (_readC) { fb.insert ("RY", Slice (HALF, // type (char *) &_tmpBuf[N2 - _xMin].r, // base sizeof (Rgba) * 2, // xStride 0, // yStride 2, // xSampling 2, // ySampling 0.0)); // fillValue fb.insert ("BY", Slice (HALF, // type (char *) &_tmpBuf[N2 - _xMin].b, // base sizeof (Rgba) * 2, // xStride 0, // yStride 2, // xSampling 2, // ySampling 0.0)); // fillValue } fb.insert ("A", Slice (HALF, // type (char *) &_tmpBuf[N2 - _xMin].a, // base sizeof (Rgba), // xStride 0, // yStride 1, // xSampling 1, // ySampling 1.0)); // fillValue _inputFile.setFrameBuffer (fb); } _fbBase = base; _fbXStride = xStride; _fbYStride = yStride;}void RgbaInputFile::FromYca::readPixels (int scanLine1, int scanLine2){ int minY = min (scanLine1, scanLine2); int maxY = max (scanLine1, scanLine2); if (_lineOrder == INCREASING_Y) { for (int y = minY; y <= maxY; ++y) readPixels (y); } else { for (int y = maxY; y >= minY; --y) readPixels (y); }}void RgbaInputFile::FromYca::readPixels (int scanLine){ if (_fbBase == 0) { THROW (Iex::ArgExc, "No frame buffer was specified as the " "pixel data destination for image file " "\"" << _inputFile.fileName() << "\"."); } // // In order to convert one scan line to RGB format, we need that // scan line plus N2+1 extra scan lines above and N2+1 scan lines // below in luminance/chroma format. // // We allow random access to scan lines, but we buffer partially // processed luminance/chroma data in order to make reading pixels // in increasing y or decreasing y order reasonably efficient: // // _currentScanLine holds the y coordinate of the scan line // that was most recently read. // // _buf1 contains scan lines _currentScanLine-N2-1 // through _currentScanLine+N2+1 in // luminance/chroma format. Odd-numbered // lines contain no chroma data. Even-numbered // lines have valid chroma data for all pixels. // // _buf2 contains scan lines _currentScanLine-1 // through _currentScanLine+1, in RGB format. // Super-saturated pixels (see ImfRgbaYca.h) // have not yet been eliminated. // // If the scan line we are trying to read now is close enough to // _currentScanLine, we don't have to recompute the contents of _buf1 // and _buf2 from scratch. We can rotate _buf1 and _buf2, and fill // in the missing data. // int dy = scanLine - _currentScanLine; if (abs (dy) < N + 2) rotateBuf1 (dy); if (abs (dy) < 3) rotateBuf2 (dy); if (dy < 0) { { int n = min (-dy, N + 2); int yMin = scanLine - N2 - 1; for (int i = n - 1; i >= 0; --i) readYCAScanLine (yMin + i, _buf1[i]); } { int n = min (-dy, 3); for (int i = 0; i < n; ++i) { if ((scanLine + i) & 1) { YCAtoRGBA (_yw, _width, _buf1[N2 + i], _buf2[i]); } else { reconstructChromaVert (_width, _buf1 + i, _buf2[i]); YCAtoRGBA (_yw, _width, _buf2[i], _buf2[i]); } } } } else { { int n = min (dy, N + 2); int yMax = scanLine + N2 + 1; for (int i = n - 1; i >= 0; --i) readYCAScanLine (yMax - i, _buf1[N + 1 - i]); } { int n = min (dy, 3); for (int i = 2; i > 2 - n; --i) { if ((scanLine + i) & 1) { YCAtoRGBA (_yw, _width, _buf1[N2 + i], _buf2[i]); } else { reconstructChromaVert (_width, _buf1 + i, _buf2[i]); YCAtoRGBA (_yw, _width, _buf2[i], _buf2[i]); } } } } fixSaturation (_yw, _width, _buf2, _tmpBuf); for (int i = 0; i < _width; ++i) _fbBase[_fbYStride * scanLine + _fbXStride * (i + _xMin)] = _tmpBuf[i]; _currentScanLine = scanLine;}voidRgbaInputFile::FromYca::rotateBuf1 (int d){ d = modp (d, N + 2); Rgba *tmp[N + 2]; for (int i = 0; i < N + 2; ++i) tmp[i] = _buf1[i]; for (int i = 0; i < N + 2; ++i) _buf1[i] = tmp[(i + d) % (N + 2)];}voidRgbaInputFile::FromYca::rotateBuf2 (int d){ d = modp (d, 3); Rgba *tmp[3]; for (int i = 0; i < 3; ++i) tmp[i] = _buf2[i]; for (int i = 0; i < 3; ++i) _buf2[i] = tmp[(i + d) % 3];}voidRgbaInputFile::FromYca::readYCAScanLine (int y, Rgba *buf){ // // Clamp y. // if (y < _yMin) y = _yMin; else if (y > _yMax) y = _yMax - 1; // // Read scan line y into _tmpBuf. // _inputFile.readPixels (y); // // Reconstruct missing chroma samples and copy // the scan line into buf. // if (!_readC) { for (int i = 0; i < _width; ++i) { _tmpBuf[i + N2].r = 0; _tmpBuf[i + N2].b = 0; } } if (y & 1) { memcpy (buf, _tmpBuf + N2, _width * sizeof (Rgba)); } else { padTmpBuf(); reconstructChromaHoriz (_width, _tmpBuf, buf); }}voidRgbaInputFile::FromYca::padTmpBuf (){ for (int i = 0; i < N2; ++i) { _tmpBuf[i] = _tmpBuf[N2]; _tmpBuf[_width + N2 + i] = _tmpBuf[_width + N2 - 2]; }}RgbaInputFile::RgbaInputFile (const char name[], int numThreads): _inputFile (new InputFile (name, numThreads)), _fromYca (0){ RgbaChannels rgbaChannels = channels(); if (rgbaChannels & (WRITE_Y | WRITE_C)) _fromYca = new FromYca (*_inputFile, rgbaChannels);}RgbaInputFile::RgbaInputFile (IStream &is, int numThreads): _inputFile (new InputFile (is, numThreads)), _fromYca (0){ RgbaChannels rgbaChannels = channels(); if (rgbaChannels & (WRITE_Y | WRITE_C)) _fromYca = new FromYca (*_inputFile, rgbaChannels);}RgbaInputFile::~RgbaInputFile (){ delete _inputFile; delete _fromYca;}void RgbaInputFile::setFrameBuffer (Rgba *base, size_t xStride, size_t yStride){ if (_fromYca) { Lock lock (*_fromYca); _fromYca->setFrameBuffer (base, xStride, yStride); } else { size_t xs = xStride * sizeof (Rgba); size_t ys = yStride * sizeof (Rgba); FrameBuffer fb; fb.insert ("R", Slice (HALF, (char *) &base[0].r, xs, ys, 1, 1, // xSampling, ySampling 0.0)); // fillValue fb.insert ("G", Slice (HALF, (char *) &base[0].g, xs, ys, 1, 1, // xSampling, ySampling 0.0)); // fillValue fb.insert ("B", Slice (HALF, (char *) &base[0].b, xs, ys, 1, 1, // xSampling, ySampling 0.0)); // fillValue fb.insert ("A", Slice (HALF, (char *) &base[0].a, xs, ys, 1, 1, // xSampling, ySampling 1.0)); // fillValue _inputFile->setFrameBuffer (fb); }}void RgbaInputFile::readPixels (int scanLine1, int scanLine2){ if (_fromYca) { Lock lock (*_fromYca); _fromYca->readPixels (scanLine1, scanLine2); } else { _inputFile->readPixels (scanLine1, scanLine2); }}void RgbaInputFile::readPixels (int scanLine){ readPixels (scanLine, scanLine);}boolRgbaInputFile::isComplete () const{ return _inputFile->isComplete();}const Header &RgbaInputFile::header () const{ return _inputFile->header();}const char *RgbaInputFile::fileName () const{ return _inputFile->fileName();}const FrameBuffer & RgbaInputFile::frameBuffer () const{ return _inputFile->frameBuffer();}const Imath::Box2i &RgbaInputFile::displayWindow () const{ return _inputFile->header().displayWindow();}const Imath::Box2i &RgbaInputFile::dataWindow () const{ return _inputFile->header().dataWindow();}float RgbaInputFile::pixelAspectRatio () const{ return _inputFile->header().pixelAspectRatio();}const Imath::V2f RgbaInputFile::screenWindowCenter () const{ return _inputFile->header().screenWindowCenter();}float RgbaInputFile::screenWindowWidth () const{ return _inputFile->header().screenWindowWidth();}LineOrderRgbaInputFile::lineOrder () const{ return _inputFile->header().lineOrder();}CompressionRgbaInputFile::compression () const{ return _inputFile->header().compression();}RgbaChannels RgbaInputFile::channels () const{ return rgbaChannels (_inputFile->header().channels());}intRgbaInputFile::version () const{ return _inputFile->version();}} // namespace Imf
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -