예제 #1
0
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
            }
        }
    }
}
예제 #5
0
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;
}