📄 imftiledoutputfile.cpp
字号:
dyStart = dy2; dyStop = dy1 - 1; dY = -1; } int numTiles = (dx2 - dx1 + 1) * (dy2 - dy1 + 1); int numTasks = min ((int)_data->tileBuffers.size(), numTiles); // // Create a task group for all tile buffer tasks. When the // task group goes out of scope, the destructor waits until // all tasks are complete. // { TaskGroup taskGroup; // // Add in the initial compression tasks to the thread pool // int nextCompBuffer = 0; int dxComp = dx1; int dyComp = dyStart; while (nextCompBuffer < numTasks) { ThreadPool::addGlobalTask (new TileBufferTask (&taskGroup, _data, nextCompBuffer++, dxComp, dyComp, lx, ly)); dxComp++; if (dxComp > dx2) { dxComp = dx1; dyComp += dY; } } // // Write the compressed buffers and add in more compression // tasks until done // int nextWriteBuffer = 0; int dxWrite = dx1; int dyWrite = dyStart; while (nextWriteBuffer < numTiles) { // // Wait until the nextWriteBuffer is ready to be written // TileBuffer* writeBuffer = _data->getTileBuffer (nextWriteBuffer); writeBuffer->wait(); // // Write the tilebuffer // bufferedTileWrite (_data, dxWrite, dyWrite, lx, ly, writeBuffer->dataPtr, writeBuffer->dataSize); // // Release the lock on nextWriteBuffer // writeBuffer->post(); // // If there are no more tileBuffers to compress, then // only continue to write out remaining tileBuffers, // otherwise keep adding compression tasks. // if (nextCompBuffer < numTiles) { // // add nextCompBuffer as a compression Task // ThreadPool::addGlobalTask (new TileBufferTask (&taskGroup, _data, nextCompBuffer, dxComp, dyComp, lx, ly)); } nextWriteBuffer++; dxWrite++; if (dxWrite > dx2) { dxWrite = dx1; dyWrite += dY; } nextCompBuffer++; dxComp++; if (dxComp > dx2) { dxComp = dx1; dyComp += dY; } } // // finish all tasks // } // // Exeption handling: // // TileBufferTask::execute() may have encountered exceptions, but // those exceptions occurred in another thread, not in the thread // that is executing this call to TiledOutputFile::writeTiles(). // TileBufferTask::execute() has caught all exceptions and stored // the exceptions' what() strings in the tile buffers. // Now we check if any tile buffer contains a stored exception; if // this is the case then we re-throw the exception in this thread. // (It is possible that multiple tile 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->tileBuffers.size(); ++i) { TileBuffer *tileBuffer = _data->tileBuffers[i]; if (tileBuffer->hasException && !exception) exception = &tileBuffer->exception; tileBuffer->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; }}void TiledOutputFile::writeTiles (int dx1, int dxMax, int dyMin, int dyMax, int l){ writeTiles (dx1, dxMax, dyMin, dyMax, l, l);}void TiledOutputFile::writeTile (int dx, int dy, int lx, int ly){ writeTiles (dx, dx, dy, dy, lx, ly);}voidTiledOutputFile::writeTile (int dx, int dy, int l){ writeTile(dx, dy, l, l);}void TiledOutputFile::copyPixels (TiledInputFile &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 (!hdr.hasTileDescription() || !inHdr.hasTileDescription()) THROW (Iex::ArgExc, "Cannot perform a quick pixel copy from image " "file \"" << in.fileName() << "\" to image " "file \"" << fileName() << "\". The " "output file is tiled, but the input file is not. " "Try using OutputFile::copyPixels() instead."); if (!(hdr.tileDescription() == inHdr.tileDescription())) THROW (Iex::ArgExc, "Quick pixel copy from image " "file \"" << in.fileName() << "\" to image " "file \"" << fileName() << "\" failed. " "The files have different tile descriptions."); 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. // if (!_data->tileOffsets.isEmpty()) THROW (Iex::LogicExc, "Quick pixel copy from image " "file \"" << in.fileName() << "\" to image " "file \"" << _data->os->fileName() << "\" " "failed. \"" << fileName() << "\" " "already contains pixel data."); // // Calculate the total number of tiles in the file // int numAllTiles = 0; switch (levelMode ()) { case ONE_LEVEL: case MIPMAP_LEVELS: for (size_t i_l = 0; i_l < numLevels (); ++i_l) numAllTiles += numXTiles (i_l) * numYTiles (i_l); break; case RIPMAP_LEVELS: for (size_t i_ly = 0; i_ly < numYLevels (); ++i_ly) for (size_t i_lx = 0; i_lx < numXLevels (); ++i_lx) numAllTiles += numXTiles (i_lx) * numYTiles (i_ly); break; default: throw Iex::ArgExc ("Unknown LevelMode format."); } for (int i = 0; i < numAllTiles; ++i) { const char *pixelData; int pixelDataSize; int dx = _data->nextTileToWrite.dx; int dy = _data->nextTileToWrite.dy; int lx = _data->nextTileToWrite.lx; int ly = _data->nextTileToWrite.ly; in.rawTileData (dx, dy, lx, ly, pixelData, pixelDataSize); writeTileData (_data, dx, dy, lx, ly, pixelData, pixelDataSize); }}void TiledOutputFile::copyPixels (InputFile &in){ copyPixels (*in.tFile());}unsigned intTiledOutputFile::tileXSize () const{ return _data->tileDesc.xSize;}unsigned intTiledOutputFile::tileYSize () const{ return _data->tileDesc.ySize;}LevelModeTiledOutputFile::levelMode () const{ return _data->tileDesc.mode;}LevelRoundingModeTiledOutputFile::levelRoundingMode () const{ return _data->tileDesc.roundingMode;}intTiledOutputFile::numLevels () const{ if (levelMode() == RIPMAP_LEVELS) THROW (Iex::LogicExc, "Error calling numLevels() on image " "file \"" << fileName() << "\" " "(numLevels() is not defined for RIPMAPs)."); return _data->numXLevels;}intTiledOutputFile::numXLevels () const{ return _data->numXLevels;}intTiledOutputFile::numYLevels () const{ return _data->numYLevels;}bool TiledOutputFile::isValidLevel (int lx, int ly) const{ if (lx < 0 || ly < 0) return false; if (levelMode() == MIPMAP_LEVELS && lx != ly) return false; if (lx >= numXLevels() || ly >= numYLevels()) return false; return true;}intTiledOutputFile::levelWidth (int lx) const{ try { int retVal = levelSize (_data->minX, _data->maxX, lx, _data->tileDesc.roundingMode); return retVal; } catch (Iex::BaseExc &e) { REPLACE_EXC (e, "Error calling levelWidth() on image " "file \"" << fileName() << "\". " << e); throw; }}intTiledOutputFile::levelHeight (int ly) const{ try { return levelSize (_data->minY, _data->maxY, ly, _data->tileDesc.roundingMode); } catch (Iex::BaseExc &e) { REPLACE_EXC (e, "Error calling levelHeight() on image " "file \"" << fileName() << "\". " << e); throw; }}intTiledOutputFile::numXTiles (int lx) const{ if (lx < 0 || lx >= _data->numXLevels) THROW (Iex::LogicExc, "Error calling numXTiles() on image " "file \"" << _data->os->fileName() << "\" " "(Argument is not in valid range)."); return _data->numXTiles[lx];}intTiledOutputFile::numYTiles (int ly) const{ if (ly < 0 || ly >= _data->numYLevels) THROW (Iex::LogicExc, "Error calling numXTiles() on image " "file \"" << _data->os->fileName() << "\" " "(Argument is not in valid range)."); return _data->numYTiles[ly];}Box2iTiledOutputFile::dataWindowForLevel (int l) const{ return dataWindowForLevel (l, l);}Box2iTiledOutputFile::dataWindowForLevel (int lx, int ly) const{ try { return Imf::dataWindowForLevel (_data->tileDesc, _data->minX, _data->maxX, _data->minY, _data->maxY, lx, ly); } catch (Iex::BaseExc &e) { REPLACE_EXC (e, "Error calling dataWindowForLevel() on image " "file \"" << fileName() << "\". " << e); throw; }}Box2iTiledOutputFile::dataWindowForTile (int dx, int dy, int l) const{ return dataWindowForTile (dx, dy, l, l);}Box2iTiledOutputFile::dataWindowForTile (int dx, int dy, int lx, int ly) const{ try { if (!isValidTile (dx, dy, lx, ly)) throw Iex::ArgExc ("Arguments not in valid range."); return Imf::dataWindowForTile (_data->tileDesc, _data->minX, _data->maxX, _data->minY, _data->maxY, dx, dy, lx, ly); } catch (Iex::BaseExc &e) { REPLACE_EXC (e, "Error calling dataWindowForTile() on image " "file \"" << fileName() << "\". " << e); throw; }}boolTiledOutputFile::isValidTile (int dx, int dy, int lx, int ly) const{ return ((lx < _data->numXLevels && lx >= 0) && (ly < _data->numYLevels && ly >= 0) && (dx < _data->numXTiles[lx] && dx >= 0) && (dy < _data->numYTiles[ly] && dy >= 0));}voidTiledOutputFile::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; }}voidTiledOutputFile::breakTile (int dx, int dy, int lx, int ly, int offset, int length, char c){ Lock lock (*_data); Int64 position = _data->tileOffsets (dx, dy, lx, ly); if (!position) THROW (Iex::ArgExc, "Cannot overwrite tile " "(" << dx << ", " << dy << ", " << lx << "," << ly << "). " "The tile 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 + -