SkCodec::Result SkRawCodec::onGetPixels(const SkImageInfo& requestedInfo, void* dst, size_t dstRowBytes, const Options& options, SkPMColor ctable[], int* ctableCount, int* rowsDecoded) { if (!conversion_possible(requestedInfo, this->getInfo())) { SkCodecPrintf("Error: cannot convert input type to output type.\n"); return kInvalidConversion; } SkAutoTDelete<SkSwizzler> swizzler(SkSwizzler::CreateSwizzler( SkSwizzler::kRGB, nullptr, requestedInfo, options)); SkASSERT(swizzler); const int width = requestedInfo.width(); const int height = requestedInfo.height(); SkAutoTDelete<dng_image> image(fDngImage->render(width, height)); if (!image) { return kInvalidInput; } // Because the DNG SDK can not guarantee to render to requested size, we allow a small // difference. Only the overlapping region will be converted. const float maxDiffRatio = 1.03f; const dng_point& imageSize = image->Size(); if (imageSize.h / width > maxDiffRatio || imageSize.h < width || imageSize.v / height > maxDiffRatio || imageSize.v < height) { return SkCodec::kInvalidScale; } void* dstRow = dst; SkAutoTMalloc<uint8_t> srcRow(width * 3); dng_pixel_buffer buffer; buffer.fData = &srcRow[0]; buffer.fPlane = 0; buffer.fPlanes = 3; buffer.fColStep = buffer.fPlanes; buffer.fPlaneStep = 1; buffer.fPixelType = ttByte; buffer.fPixelSize = sizeof(uint8_t); buffer.fRowStep = width * 3; for (int i = 0; i < height; ++i) { buffer.fArea = dng_rect(i, 0, i + 1, width); try { image->Get(buffer, dng_image::edge_zero); } catch (...) { *rowsDecoded = i; return kIncompleteInput; } swizzler->swizzle(dstRow, &srcRow[0]); dstRow = SkTAddOffset<void>(dstRow, dstRowBytes); } return kSuccess; }
void createInvLumpedBlock ( const MatrixEpetraStructuredView<DataType>& srcBlock, const MatrixEpetraStructuredView<DataType>& destBlock ) { // SQUARE TEST ASSERT( srcBlock.numRows() == srcBlock.numColumns() , "The source block must be square" ); ASSERT( destBlock.numRows() == destBlock.numColumns() , "The destination block must be square" ); // BLOCK COMPATIBILITY TEST ASSERT( srcBlock.numRows() == destBlock.numRows(), "The two blocks must have the same number of rows" ); ASSERT( srcBlock.numColumns() == destBlock.numColumns(), "The two blocks must have the same number of columnss" ); // BLOCK PTR TEST ASSERT( srcBlock.matrixPtr() != 0 , "The source block does not have a valid pointer" ); ASSERT( destBlock.matrixPtr() != 0 , "The destination block does not have a valid pointer" ); Int indexBase(0); // Processor informations Int numSrcElements = srcBlock.matrixPtr()->matrixPtr()->RowMap().NumMyElements(); Int* srcGlobalElements = srcBlock.matrixPtr()->matrixPtr()->RowMap().MyGlobalElements(); UInt srcRowElement(0); // Source informations handlers Int numSrcEntries; DataType* srcValues; Int* srcIndices; UInt srcGlobalIndex(0); Int srcRow(0); for(Int i(0);i<numSrcElements;++i) { // Collecting the data from the source srcRowElement = srcGlobalElements[i]; // Test if the rows are in the source block if((srcRowElement>=srcBlock.firstRowIndex()+indexBase) && (srcRowElement<=srcBlock.lastRowIndex()+indexBase)) { // Get the data of the row srcRow = srcBlock.matrixPtr()->matrixPtr()->LRID(srcRowElement); srcBlock.matrixPtr()->matrixPtr()->ExtractMyRowView(srcRow, numSrcEntries, srcValues, srcIndices); Int diagIndex=srcRowElement-srcBlock.firstRowIndex(); Int destRow = destBlock.firstRowIndex()+diagIndex; Int destIndex = destBlock.firstColumnIndex()+diagIndex; DataType srcBlockRowSum = 0.0; for(Int j(0);j<numSrcEntries;++j) { srcGlobalIndex = srcBlock.matrixPtr()->matrixPtr()->GCID(srcIndices[j]); // Test if the coefficient is in the block if((srcGlobalIndex>=srcBlock.firstColumnIndex()+indexBase) && (srcGlobalIndex<=srcBlock.lastColumnIndex()+indexBase)) { srcBlockRowSum += abs(srcValues[j]); } } // ZERO ON DIAGONAL TEST ASSERT( srcBlockRowSum != 0, "You cannot ask for inverse lumped block when there are rows of zeros" ); srcBlockRowSum = 1./srcBlockRowSum; if(destBlock.matrixPtr()->matrixPtr()->Map().MyGID(destRow)) destBlock.matrixPtr()->matrixPtr()->InsertGlobalValues(destRow,1,&srcBlockRowSum,&destIndex); else destBlock.matrixPtr()->matrixPtr()->SumIntoGlobalValues(destRow,1,&srcBlockRowSum,&destIndex); } } }
void createLowerTriangularBlock ( const MatrixEpetraStructuredView<DataType>& srcBlock, const MatrixEpetraStructuredView<DataType>& destBlock ) { // SQUARE TEST ASSERT( srcBlock.numRows() == srcBlock.numColumns() , "The source block must be square" ); ASSERT( destBlock.numRows() == destBlock.numColumns() , "The destination block must be square" ); // BLOCK COMPATIBILITY TEST ASSERT( srcBlock.numRows() == destBlock.numRows(), "The two blocks must have the same number of rows" ); ASSERT( srcBlock.numColumns() == destBlock.numColumns(), "The two blocks must have the same number of columnss" ); // BLOCK PTR TEST ASSERT( srcBlock.matrixPtr() != 0 , "The source block does not have a valid pointer" ); ASSERT( destBlock.matrixPtr() != 0 , "The destination block does not have a valid pointer" ); // Processor informations Int numSrcElements = srcBlock.matrixPtr()->matrixPtr()->RowMap().NumMyElements(); Int* srcGlobalElements = srcBlock.matrixPtr()->matrixPtr()->RowMap().MyGlobalElements(); UInt srcRowElement(0); //Offset between the first row/column of the source and destination blocks Int rowsOffset(destBlock.firstRowIndex()-srcBlock.firstRowIndex()); Int columnsOffset(destBlock.firstColumnIndex()-srcBlock.firstColumnIndex()); // Source informations handlers Int numSrcEntries; DataType* srcValues; Int* srcIndices; UInt srcGlobalIndex(0); Int srcRow(0); for(Int i(0);i<numSrcElements;++i) { // Collecting the data from the source srcRowElement = srcGlobalElements[i]; // Test if the rows are in the source block if((srcRowElement>=srcBlock.firstRowIndex()) && (srcRowElement<=srcBlock.lastRowIndex())) { // Get the data of the row srcRow = srcBlock.matrixPtr()->matrixPtr()->LRID(srcRowElement); srcBlock.matrixPtr()->matrixPtr()->ExtractMyRowView(srcRow, numSrcEntries, srcValues, srcIndices); std::vector<Int> destIndices(numSrcEntries); std::vector<DataType> destValues(numSrcEntries); Int numDestEntries(0); Int destRow(srcRowElement+rowsOffset); for(Int j(0);j<numSrcEntries;++j) { srcGlobalIndex = srcBlock.matrixPtr()->matrixPtr()->GCID(srcIndices[j]); // Test if the coefficient is: // a) in the block, and // b) on the lower triangular part of the block. if((srcGlobalIndex>=srcBlock.firstColumnIndex()) && (srcGlobalIndex<=srcBlock.lastColumnIndex()) && (srcGlobalIndex-srcBlock.firstColumnIndex()<=srcRowElement-srcBlock.firstRowIndex())) { destIndices[numDestEntries] = srcGlobalIndex+columnsOffset; destValues[numDestEntries] = srcValues[j]; numDestEntries++; } } if(destBlock.matrixPtr()->matrixPtr()->Map().MyGID(destRow)) destBlock.matrixPtr()->matrixPtr()->InsertGlobalValues(destRow,numDestEntries,&destValues[0],&destIndices[0]); else destBlock.matrixPtr()->matrixPtr()->SumIntoGlobalValues(destRow,numDestEntries,&destValues[0],&destIndices[0]); } } }
void copyBlock ( const MatrixEpetraStructuredView<DataType>& srcBlock, const MatrixEpetraStructuredView<DataType>& destBlock ) { // BLOCK COMPATIBILITY TEST ASSERT( srcBlock.numRows() == destBlock.numRows(), "The two blocks must have the same number of rows" ); ASSERT( srcBlock.numColumns() == destBlock.numColumns(), "The two blocks must have the same number of columnss" ); // BLOCK PTR TEST ASSERT( srcBlock.matrixPtr() != 0 , "The source block does not have a valid pointer" ); ASSERT( destBlock.matrixPtr() != 0 , "The destination block does not have a valid pointer" ); // Processor informations const Int numSrcElements = srcBlock.matrixPtr()->matrixPtr()->RowMap().NumMyElements(); const Int* srcGlobalElements = srcBlock.matrixPtr()->matrixPtr()->RowMap().MyGlobalElements(); Int srcRowElement(0); //Offset between the first row/column of the source and destination blocks const Int rowsOffset(destBlock.firstRowIndex()-srcBlock.firstRowIndex()); const Int columnsOffset(destBlock.firstColumnIndex()-srcBlock.firstColumnIndex()); // Source informations handlers Int numSrcEntries; DataType* srcValues; Int* srcIndices; Int srcGlobalIndex(0); Int srcRow(0); for(Int i(0);i<numSrcElements;++i) { // Collecting the data from the source srcRowElement = srcGlobalElements[i]; // Test if the rows are in the source block if(( static_cast<UInt>(srcRowElement)>=srcBlock.firstRowIndex()) && ( static_cast<UInt>(srcRowElement)<=srcBlock.lastRowIndex())) { // Get the data of the row srcRow = srcBlock.matrixPtr()->matrixPtr()->LRID(srcRowElement); srcBlock.matrixPtr()->matrixPtr()->ExtractMyRowView(srcRow, numSrcEntries, srcValues, srcIndices); std::vector<Int> destIndices(numSrcEntries); std::vector<DataType> destValues(numSrcEntries); Int numDestEntries(0); Int destRow(srcRowElement+rowsOffset); for(Int j(0);j<numSrcEntries;++j) { srcGlobalIndex = srcBlock.matrixPtr()->matrixPtr()->GCID(srcIndices[j]); // Test if the coefficient is in the block if(( static_cast<UInt>(srcGlobalIndex)>=srcBlock.firstColumnIndex()) && ( static_cast<UInt>(srcGlobalIndex)<=srcBlock.lastColumnIndex())) { destIndices[numDestEntries] = srcGlobalIndex+columnsOffset; destValues[numDestEntries] = srcValues[j]; numDestEntries++; } } if(destBlock.matrixPtr()->matrixPtr()->Map().MyGID(destRow)) { #ifdef NDEBUG destBlock.matrixPtr()->matrixPtr()->InsertGlobalValues(destRow,numDestEntries,&destValues[0],&destIndices[0]); #else Int errorCode = destBlock.matrixPtr()->matrixPtr()->InsertGlobalValues(destRow,numDestEntries,&destValues[0],&destIndices[0]); ASSERT(errorCode >=0, " Error in block copy: insertion failed"); #endif } else { #ifdef NDEBUG destBlock.matrixPtr()->matrixPtr()->SumIntoGlobalValues(destRow,numDestEntries,&destValues[0],&destIndices[0]); #else Int errorCode = destBlock.matrixPtr()->matrixPtr()->SumIntoGlobalValues(destRow,numDestEntries,&destValues[0],&destIndices[0]); ASSERT(errorCode >=0, " Error in block copy: sum failed"); #endif } } } }
SkCodec::Result SkRawCodec::onGetPixels(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes, const Options& options, SkPMColor ctable[], int* ctableCount, int* rowsDecoded) { if (!conversion_possible(dstInfo, this->getInfo()) || !this->initializeColorXform(dstInfo, options.fPremulBehavior)) { SkCodecPrintf("Error: cannot convert input type to output type.\n"); return kInvalidConversion; } static const SkColorType kXformSrcColorType = kRGBA_8888_SkColorType; SkImageInfo swizzlerInfo = dstInfo; std::unique_ptr<uint32_t[]> xformBuffer = nullptr; if (this->colorXform()) { swizzlerInfo = swizzlerInfo.makeColorType(kXformSrcColorType); xformBuffer.reset(new uint32_t[dstInfo.width()]); } std::unique_ptr<SkSwizzler> swizzler(SkSwizzler::CreateSwizzler( this->getEncodedInfo(), nullptr, swizzlerInfo, options)); SkASSERT(swizzler); const int width = dstInfo.width(); const int height = dstInfo.height(); std::unique_ptr<dng_image> image(fDngImage->render(width, height)); if (!image) { return kInvalidInput; } // Because the DNG SDK can not guarantee to render to requested size, we allow a small // difference. Only the overlapping region will be converted. const float maxDiffRatio = 1.03f; const dng_point& imageSize = image->Size(); if (imageSize.h / (float) width > maxDiffRatio || imageSize.h < width || imageSize.v / (float) height > maxDiffRatio || imageSize.v < height) { return SkCodec::kInvalidScale; } void* dstRow = dst; SkAutoTMalloc<uint8_t> srcRow(width * 3); dng_pixel_buffer buffer; buffer.fData = &srcRow[0]; buffer.fPlane = 0; buffer.fPlanes = 3; buffer.fColStep = buffer.fPlanes; buffer.fPlaneStep = 1; buffer.fPixelType = ttByte; buffer.fPixelSize = sizeof(uint8_t); buffer.fRowStep = width * 3; for (int i = 0; i < height; ++i) { buffer.fArea = dng_rect(i, 0, i + 1, width); try { image->Get(buffer, dng_image::edge_zero); } catch (...) { *rowsDecoded = i; return kIncompleteInput; } if (this->colorXform()) { swizzler->swizzle(xformBuffer.get(), &srcRow[0]); const SkColorSpaceXform::ColorFormat srcFormat = select_xform_format(kXformSrcColorType); const SkColorSpaceXform::ColorFormat dstFormat = select_xform_format(dstInfo.colorType()); this->colorXform()->apply(dstFormat, dstRow, srcFormat, xformBuffer.get(), dstInfo.width(), kOpaque_SkAlphaType); dstRow = SkTAddOffset<void>(dstRow, dstRowBytes); } else { swizzler->swizzle(dstRow, &srcRow[0]); dstRow = SkTAddOffset<void>(dstRow, dstRowBytes); } } return kSuccess; }