📄 imfoutputfile.cpp
字号:
// slices.push_back (OutSliceInfo (i.channel().type, 0, // base 0, // xStride, 0, // yStride, i.channel().xSampling, i.channel().ySampling, true)); // zero } else { // // Channel i is present in the frame buffer. // slices.push_back (OutSliceInfo (j.slice().type, j.slice().base, j.slice().xStride, j.slice().yStride, j.slice().xSampling, j.slice().ySampling, false)); // zero } } // // Store the new frame buffer. // _data->frameBuffer = frameBuffer; _data->slices = slices;}const FrameBuffer &OutputFile::frameBuffer () const{ Lock lock (*_data); return _data->frameBuffer;}void OutputFile::writePixels (int numScanLines){ try { Lock lock (*_data); if (_data->slices.size() == 0) throw Iex::ArgExc ("No frame buffer specified " "as pixel data source."); // // Maintain two iterators: // nextWriteBuffer: next linebuffer to be written to the file // nextCompressBuffer: next linebuffer to compress // int first = (_data->currentScanLine - _data->minY) / _data->linesInBuffer; int nextWriteBuffer = first; int nextCompressBuffer; int stop; int step; int scanLineMin; int scanLineMax; { // // Create a task group for all line buffer tasks. When the // taskgroup goes out of scope, the destructor waits until // all tasks are complete. // TaskGroup taskGroup; // // Determine the range of lineBuffers that intersect the scan // line range. Then add the initial compression tasks to the // thread pool. We always add in at least one task but the // individual task might not do anything if numScanLines == 0. // if (_data->lineOrder == INCREASING_Y) { int last = (_data->currentScanLine + (numScanLines - 1) - _data->minY) / _data->linesInBuffer; scanLineMin = _data->currentScanLine; scanLineMax = _data->currentScanLine + numScanLines - 1; int numTasks = max (min ((int)_data->lineBuffers.size(), last - first + 1), 1); for (int i = 0; i < numTasks; i++) { ThreadPool::addGlobalTask (new LineBufferTask (&taskGroup, _data, first + i, scanLineMin, scanLineMax)); } nextCompressBuffer = first + numTasks; stop = last + 1; step = 1; } else { int last = (_data->currentScanLine - (numScanLines - 1) - _data->minY) / _data->linesInBuffer; scanLineMax = _data->currentScanLine; scanLineMin = _data->currentScanLine - numScanLines + 1; int numTasks = max (min ((int)_data->lineBuffers.size(), first - last + 1), 1); for (int i = 0; i < numTasks; i++) { ThreadPool::addGlobalTask (new LineBufferTask (&taskGroup, _data, first - i, scanLineMin, scanLineMax)); } nextCompressBuffer = first - numTasks; stop = last - 1; step = -1; } while (true) { if (_data->missingScanLines <= 0) { throw Iex::ArgExc ("Tried to write more scan lines " "than specified by the data window."); } // // Wait until the next line buffer is ready to be written // LineBuffer *writeBuffer = _data->getLineBuffer (nextWriteBuffer); writeBuffer->wait(); int numLines = writeBuffer->scanLineMax - writeBuffer->scanLineMin + 1; _data->missingScanLines -= numLines; // // If the line buffer is only partially full, then it is // not complete and we cannot write it to disk yet. // if (writeBuffer->partiallyFull) { _data->currentScanLine = _data->currentScanLine + step * numLines; writeBuffer->post(); return; } // // Write the line buffer // writePixelData (_data, writeBuffer); nextWriteBuffer += step; _data->currentScanLine = _data->currentScanLine + step * numLines; #ifdef DEBUG assert (_data->currentScanLine == ((_data->lineOrder == INCREASING_Y) ? writeBuffer->scanLineMax + 1: writeBuffer->scanLineMin - 1)); #endif // // Release the lock on the line buffer // writeBuffer->post(); // // If this was the last line buffer in the scanline range // if (nextWriteBuffer == stop) break; // // If there are no more line buffers to compress, // then only continue to write out remaining lineBuffers // if (nextCompressBuffer == stop) continue; // // Add nextCompressBuffer as a compression task // ThreadPool::addGlobalTask (new LineBufferTask (&taskGroup, _data, nextCompressBuffer, scanLineMin, scanLineMax)); // // Update the next line buffer we need to compress // nextCompressBuffer += step; } // // Finish all tasks // } // // Exeption handling: // // LineBufferTask::execute() may have encountered exceptions, but // those exceptions occurred in another thread, not in the thread // that is executing this call to OutputFile::writePixels(). // LineBufferTask::execute() has caught all exceptions and stored // the exceptions' what() strings in the line buffers. // Now we check if any line buffer contains a stored exception; if // this is the case then we re-throw the exception in this thread. // (It is possible that multiple line buffers contain stored // exceptions. We re-throw the first exception we find and // ignore all others.) // const string *exception = 0; for (int i = 0; i < _data->lineBuffers.size(); ++i) { LineBuffer *lineBuffer = _data->lineBuffers[i]; if (lineBuffer->hasException && !exception) exception = &lineBuffer->exception; lineBuffer->hasException = false; } if (exception) throw Iex::IoExc (*exception); } catch (Iex::BaseExc &e) { REPLACE_EXC (e, "Failed to write pixel data to image " "file \"" << fileName() << "\". " << e); throw; }}int OutputFile::currentScanLine () const{ Lock lock (*_data); return _data->currentScanLine;}void OutputFile::copyPixels (InputFile &in){ Lock lock (*_data); // // Check if this file's and and the InputFile's // headers are compatible. // const Header &hdr = _data->header; const Header &inHdr = in.header(); if (inHdr.find("tiles") != inHdr.end()) THROW (Iex::ArgExc, "Cannot copy pixels from image " "file \"" << in.fileName() << "\" to image " "file \"" << fileName() << "\". " "The input file is tiled, but the output file is " "not. Try using TiledOutputFile::copyPixels " "instead."); if (!(hdr.dataWindow() == inHdr.dataWindow())) THROW (Iex::ArgExc, "Cannot copy pixels from image " "file \"" << in.fileName() << "\" to image " "file \"" << fileName() << "\". " "The files have different data windows."); if (!(hdr.lineOrder() == inHdr.lineOrder())) THROW (Iex::ArgExc, "Quick pixel copy from image " "file \"" << in.fileName() << "\" to image " "file \"" << fileName() << "\" failed. " "The files have different line orders."); if (!(hdr.compression() == inHdr.compression())) THROW (Iex::ArgExc, "Quick pixel copy from image " "file \"" << in.fileName() << "\" to image " "file \"" << fileName() << "\" failed. " "The files use different compression methods."); if (!(hdr.channels() == inHdr.channels())) THROW (Iex::ArgExc, "Quick pixel copy from image " "file \"" << in.fileName() << "\" to image " "file \"" << fileName() << "\" failed. " "The files have different channel lists."); // // Verify that no pixel data have been written to this file yet. // const Box2i &dataWindow = hdr.dataWindow(); if (_data->missingScanLines != dataWindow.max.y - dataWindow.min.y + 1) THROW (Iex::LogicExc, "Quick pixel copy from image " "file \"" << in.fileName() << "\" to image " "file \"" << fileName() << "\" failed. " "\"" << fileName() << "\" already contains " "pixel data."); // // Copy the pixel data. // while (_data->missingScanLines > 0) { const char *pixelData; int pixelDataSize; in.rawPixelData (_data->currentScanLine, pixelData, pixelDataSize); writePixelData (_data, lineBufferMinY (_data->currentScanLine, _data->minY, _data->linesInBuffer), pixelData, pixelDataSize); _data->currentScanLine += (_data->lineOrder == INCREASING_Y)? _data->linesInBuffer: -_data->linesInBuffer; _data->missingScanLines -= _data->linesInBuffer; }}voidOutputFile::updatePreviewImage (const PreviewRgba newPixels[]){ Lock lock (*_data); if (_data->previewPosition <= 0) THROW (Iex::LogicExc, "Cannot update preview image pixels. " "File \"" << fileName() << "\" does not " "contain a preview image."); // // Store the new pixels in the header's preview image attribute. // PreviewImageAttribute &pia = _data->header.typedAttribute <PreviewImageAttribute> ("preview"); PreviewImage &pi = pia.value(); PreviewRgba *pixels = pi.pixels(); int numPixels = pi.width() * pi.height(); for (int i = 0; i < numPixels; ++i) pixels[i] = newPixels[i]; // // Save the current file position, jump to the position in // the file where the preview image starts, store the new // preview image, and jump back to the saved file position. // Int64 savedPosition = _data->os->tellp(); try { _data->os->seekp (_data->previewPosition); pia.writeValueTo (*_data->os, _data->version); _data->os->seekp (savedPosition); } catch (Iex::BaseExc &e) { REPLACE_EXC (e, "Cannot update preview image pixels for " "file \"" << fileName() << "\". " << e); throw; }}void OutputFile::breakScanLine (int y, int offset, int length, char c){ Lock lock (*_data); Int64 position = _data->lineOffsets[(y - _data->minY) / _data->linesInBuffer]; if (!position) THROW (Iex::ArgExc, "Cannot overwrite scan line " << y << ". " "The scan line has not yet been stored in " "file \"" << fileName() << "\"."); _data->currentPosition = 0; _data->os->seekp (position + offset); for (int i = 0; i < length; ++i) _data->os->write (&c, 1);}} // namespace Imf
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -