Esempio n. 1
0
dng_rect dng_area_spec::Overlap (const dng_rect &tile) const
	{

	// Special case - if the fArea is empty, then dng_area_spec covers
	// the entire image, no matter how large it is.

	if (fArea.IsEmpty ())
		{
		return tile;
		}

	dng_rect overlap = fArea & tile;

	if (overlap.NotEmpty ())
		{

		overlap.t = fArea.t + ((overlap.t - fArea.t + fRowPitch - 1) / fRowPitch) * fRowPitch;
		overlap.l = fArea.l + ((overlap.l - fArea.l + fColPitch - 1) / fColPitch) * fColPitch;

		if (overlap.NotEmpty ())
			{

			overlap.b = overlap.t + ((overlap.H () - 1) / fRowPitch) * fRowPitch + 1;
			overlap.r = overlap.l + ((overlap.W () - 1) / fColPitch) * fColPitch + 1;

			return overlap;

			}

		}

	return dng_rect ();

	}
Esempio n. 2
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;
}
Esempio n. 3
0
void NegativeProcessor::buildDNGImage() {
    libraw_image_sizes_t *sizes = &m_RawProcessor->imgdata.sizes;

    // -----------------------------------------------------------------------------------------
    // Select right data source from LibRaw

    unsigned short *rawBuffer = (unsigned short*) m_RawProcessor->imgdata.rawdata.raw_image;
    uint32 inputPlanes = 1;

    if (rawBuffer == NULL) {
        rawBuffer = (unsigned short*) m_RawProcessor->imgdata.rawdata.color3_image;
        inputPlanes = 3;
    }
    if (rawBuffer == NULL) {
        rawBuffer = (unsigned short*) m_RawProcessor->imgdata.rawdata.color4_image;
        inputPlanes = 4;
    }

    uint32 outputPlanes = (inputPlanes == 1) ? 1 : m_RawProcessor->imgdata.idata.colors;

    // -----------------------------------------------------------------------------------------
    // Create new dng_image and copy data

    dng_rect bounds = dng_rect(sizes->raw_height, sizes->raw_width);
    dng_simple_image *image = new dng_simple_image(bounds, outputPlanes, ttShort, m_host->Allocator());

    dng_pixel_buffer buffer; image->GetPixelBuffer(buffer);
    unsigned short *imageBuffer = (unsigned short*)buffer.fData;

    if (inputPlanes == outputPlanes)
        memcpy(imageBuffer, rawBuffer, sizes->raw_height * sizes->raw_width * outputPlanes * sizeof(unsigned short));
    else {
        for (int i = 0; i < (sizes->raw_height * sizes->raw_width); i++) {
            memcpy(imageBuffer, rawBuffer, outputPlanes * sizeof(unsigned short));
            imageBuffer += outputPlanes;
            rawBuffer += inputPlanes;
        }
    }

    AutoPtr<dng_image> castImage(dynamic_cast<dng_image*>(image));
    m_negative->SetStage1Image(castImage);
}
void dng_image::Get (dng_pixel_buffer &buffer,
					 edge_option edgeOption,
				     uint32 repeatV,
				     uint32 repeatH) const
	{
	
	// Find the overlap with the image bounds.
	
	dng_rect overlap = buffer.fArea & fBounds;
	
	// Move the overlapping pixels.
	
	if (overlap.NotEmpty ())
		{
	
		dng_pixel_buffer temp (buffer);
		
		temp.fArea = overlap;
		
		temp.fData = buffer.DirtyPixel (overlap.t,
								   		overlap.l,
								   		buffer.fPlane);
	
		DoGet (temp);
		
		}
		
	// See if we need to pad the edge values.
	
	if ((edgeOption != edge_none) && (overlap != buffer.fArea))
		{
		
		dng_rect areaT (buffer.fArea);
		dng_rect areaL (buffer.fArea);
		dng_rect areaB (buffer.fArea);
		dng_rect areaR (buffer.fArea);
		
		areaT.b = Min_int32 (areaT.b, fBounds.t);
		areaL.r = Min_int32 (areaL.r, fBounds.l);
		areaB.t = Max_int32 (areaB.t, fBounds.b);
		areaR.l = Max_int32 (areaR.l, fBounds.r);
		
		dng_rect areaH (buffer.fArea);
		dng_rect areaV (buffer.fArea);
		
		areaH.l = Max_int32 (areaH.l, fBounds.l);
		areaH.r = Min_int32 (areaH.r, fBounds.r);
		
		areaV.t = Max_int32 (areaV.t, fBounds.t);
		areaV.b = Min_int32 (areaV.b, fBounds.b);
		
		// Top left.
		
		dng_rect areaTL = areaT & areaL;
		
		if (areaTL.NotEmpty ())
			{
			
			GetEdge (buffer,
					 edgeOption,
					 dng_rect (fBounds.t,
					 		   fBounds.l,
					 		   fBounds.t + (int32)repeatV,
					 		   fBounds.l + (int32)repeatH),
					 areaTL);
			
			}
			
		// Top middle.
		
		dng_rect areaTM = areaT & areaH;
		
		if (areaTM.NotEmpty ())
			{
			
			GetEdge (buffer,
					 edgeOption,
					 dng_rect (fBounds.t,
					 		   areaTM.l,
					 		   fBounds.t + (int32)repeatV,
					 		   areaTM.r),
					 areaTM);
			
			}
		
		// Top right.
		
		dng_rect areaTR = areaT & areaR;
		
		if (areaTR.NotEmpty ())
			{
			
			GetEdge (buffer,
					 edgeOption,
					 dng_rect (fBounds.t,
					 		   fBounds.r - (int32)repeatH,
					 		   fBounds.t + (int32)repeatV,
					 		   fBounds.r),
					 areaTR);
			
			}
			
		// Left middle.
		
		dng_rect areaLM = areaL & areaV;
		
		if (areaLM.NotEmpty ())
			{
			
			GetEdge (buffer,
					 edgeOption,
					 dng_rect (areaLM.t,
					 		   fBounds.l,
					 		   areaLM.b,
					 		   fBounds.l + (int32)repeatH),
					 areaLM);
			
			}
		
		// Right middle.
		
		dng_rect areaRM = areaR & areaV;
		
		if (areaRM.NotEmpty ())
			{
			
			GetEdge (buffer,
					 edgeOption,
					 dng_rect (areaRM.t,
					 		   fBounds.r - (int32)repeatH,
					 		   areaRM.b,
					 		   fBounds.r),
					 areaRM);
			
			}
		
		// Bottom left.
		
		dng_rect areaBL = areaB & areaL;
		
		if (areaBL.NotEmpty ())
			{
			
			GetEdge (buffer,
					 edgeOption,
					 dng_rect (fBounds.b - (int32)repeatV,
					 		   fBounds.l,
					 		   fBounds.b,
					 		   fBounds.l + (int32)repeatH),
					 areaBL);
			
			}
			
		// Bottom middle.
		
		dng_rect areaBM = areaB & areaH;
		
		if (areaBM.NotEmpty ())
			{
			
			GetEdge (buffer,
					 edgeOption,
					 dng_rect (fBounds.b - (int32)repeatV,
					 		   areaBM.l,
					 		   fBounds.b,
					 		   areaBM.r),
					 areaBM);
			
			}
		
		// Bottom right.
		
		dng_rect areaBR = areaB & areaR;
		
		if (areaBR.NotEmpty ())
			{
			
			GetEdge (buffer,
					 edgeOption,
					 dng_rect (fBounds.b - (int32)repeatV,
					 		   fBounds.r - (int32)repeatH,
					 		   fBounds.b,
					 		   fBounds.r),
					 areaBR);
			
			}
			
		}
	
	}
void dng_image::GetRepeat (dng_pixel_buffer &buffer,
				           const dng_rect &srcArea,
				           const dng_rect &dstArea) const
	{
	
	// If we already have the entire srcArea in the
	// buffer, we can just repeat that.
	
	if ((srcArea & buffer.fArea) == srcArea)
		{
		
		buffer.RepeatArea (srcArea,
						   dstArea);
		
		}
		
	// Else we first need to get the srcArea into the buffer area.
	
	else
		{
		
		// Find repeating pattern size.
		
		dng_point repeat = srcArea.Size ();
		
		// Find pattern phase at top-left corner of destination area.
		
		dng_point phase = dng_pixel_buffer::RepeatPhase (srcArea,
													     dstArea);
			
		// Find new source area at top-left of dstArea.
		
		dng_rect newArea = srcArea + (dstArea.TL () -
								      srcArea.TL ());
										 
		// Find quadrant split coordinates.
		
		int32 splitV = newArea.t + repeat.v - phase.v;
		int32 splitH = newArea.l + repeat.h - phase.h;
			
		// Top-left quadrant.
		
		dng_rect dst1 (dng_rect (newArea.t,
					   			 newArea.l,
					   			 splitV,
					   			 splitH) & dstArea);
					    
		if (dst1.NotEmpty ())
			{
			
			dng_pixel_buffer temp (buffer);
			
			temp.fArea = dst1 + (srcArea.TL () -
								 dstArea.TL () +
								 dng_point (phase.v, phase.h));
			
			temp.fData = buffer.DirtyPixel (dst1.t,
									        dst1.l,
									        buffer.fPlane);
									        
			DoGet (temp);
			
			}
			
		// Top-right quadrant.
		
		dng_rect dst2 (dng_rect (newArea.t,
								 splitH,
								 splitV,
								 newArea.r) & dstArea);
								 
		if (dst2.NotEmpty ())
			{
			
			dng_pixel_buffer temp (buffer);
			
			temp.fArea = dst2 + (srcArea.TL () -
								 dstArea.TL () +
								 dng_point (phase.v, -phase.h));
			
			temp.fData = buffer.DirtyPixel (dst2.t,
									        dst2.l,
									        buffer.fPlane);
									        
			DoGet (temp);
			
			}
			
		// Bottom-left quadrant.
		
		dng_rect dst3 (dng_rect (splitV,
								 newArea.l,
								 newArea.b,
								 splitH) & dstArea);
								 
		if (dst3.NotEmpty ())
			{
			
			dng_pixel_buffer temp (buffer);
			
			temp.fArea = dst3 + (srcArea.TL () -
								 dstArea.TL () +
								 dng_point (-phase.v, phase.h));
			
			temp.fData = buffer.DirtyPixel (dst3.t,
									        dst3.l,
									        buffer.fPlane);
									        
			DoGet (temp);
			
			}
			
		// Bottom-right quadrant.
		
		dng_rect dst4 (dng_rect (splitV,
								 splitH,
								 newArea.b,
								 newArea.r) & dstArea);
								 
		if (dst4.NotEmpty ())
			{
			
			dng_pixel_buffer temp (buffer);
			
			temp.fArea = dst4 + (srcArea.TL () -
								 dstArea.TL () +
								 dng_point (-phase.v, -phase.h));
			
			temp.fData = buffer.DirtyPixel (dst4.t,
									        dst4.l,
									        buffer.fPlane);
									        
			DoGet (temp);
			
			} 
					   
		// Replicate this new source area.
		
		buffer.RepeatArea (newArea,
						   dstArea);
		
		}
			
	}
Esempio n. 6
0
void NegativeProcessor::setDNGPropertiesFromRaw() {
    libraw_image_sizes_t *sizes   = &m_RawProcessor->imgdata.sizes;
    libraw_iparams_t     *iparams = &m_RawProcessor->imgdata.idata;

    // -----------------------------------------------------------------------------------------
    // Raw filename

    std::string file(m_RawImage->io().path());
    size_t found = std::min(file.rfind("\\"), file.rfind("/"));
    if (found != std::string::npos) file = file.substr(found + 1, file.length() - found - 1);
    m_negative->SetOriginalRawFileName(file.c_str());

	// -----------------------------------------------------------------------------------------
	// Model

    dng_string makeModel;
    makeModel.Append(iparams->make);
    makeModel.Append(" ");
    makeModel.Append(iparams->model);
    m_negative->SetModelName(makeModel.Get());

    // -----------------------------------------------------------------------------------------
    // Orientation 

    switch (sizes->flip) {
        case 180:
        case 3:  m_negative->SetBaseOrientation(dng_orientation::Rotate180()); break;
        case 270:
        case 5:  m_negative->SetBaseOrientation(dng_orientation::Rotate90CCW()); break;
        case 90:
        case 6:  m_negative->SetBaseOrientation(dng_orientation::Rotate90CW()); break;
        default: m_negative->SetBaseOrientation(dng_orientation::Normal()); break;
    }

	// -----------------------------------------------------------------------------------------
	// ColorKeys (this needs to happen before Mosaic - how about documenting that in the SDK???)

    m_negative->SetColorChannels(iparams->colors);
    m_negative->SetColorKeys(colorKey(iparams->cdesc[0]), colorKey(iparams->cdesc[1]), 
                             colorKey(iparams->cdesc[2]), colorKey(iparams->cdesc[3]));

    // -----------------------------------------------------------------------------------------
    // Mosaic

    if (iparams->colors == 4) m_negative->SetQuadMosaic(iparams->filters);
    else switch(iparams->filters) {
            case 0xe1e1e1e1:  m_negative->SetBayerMosaic(0); break;
            case 0xb4b4b4b4:  m_negative->SetBayerMosaic(1); break;
            case 0x1e1e1e1e:  m_negative->SetBayerMosaic(2); break;
            case 0x4b4b4b4b:  m_negative->SetBayerMosaic(3); break;
            default: break;  // not throwing error, because this might be set in a sub-class (e.g., Fuji)
        }

	// -----------------------------------------------------------------------------------------
	// Default scale and crop/active area

    m_negative->SetDefaultScale(dng_urational(sizes->iwidth, sizes->width), dng_urational(sizes->iheight, sizes->height));
    m_negative->SetActiveArea(dng_rect(sizes->top_margin, sizes->left_margin,
                                       sizes->top_margin + sizes->height, sizes->left_margin + sizes->width));

    uint32 cropWidth, cropHeight;
    if (!getRawExifTag("Exif.Photo.PixelXDimension", 0, &cropWidth) ||
        !getRawExifTag("Exif.Photo.PixelYDimension", 0, &cropHeight)) {
        cropWidth = sizes->width - 16;
        cropHeight = sizes->height - 16;
    }

    int cropLeftMargin = (cropWidth > sizes->width ) ? 0 : (sizes->width  - cropWidth) / 2;
    int cropTopMargin = (cropHeight > sizes->height) ? 0 : (sizes->height - cropHeight) / 2;

    m_negative->SetDefaultCropOrigin(cropLeftMargin, cropTopMargin);
    m_negative->SetDefaultCropSize(cropWidth, cropHeight);

    // -----------------------------------------------------------------------------------------
    // CameraNeutral

    //TODO/CHECK/FORK: what does this actually do?
    dng_vector cameraNeutral(iparams->colors);
    for (int i = 0; i < iparams->colors; i++)
        cameraNeutral[i] = 1.0 / m_RawProcessor->imgdata.color.cam_mul[i];
    m_negative->SetCameraNeutral(cameraNeutral);

    // -----------------------------------------------------------------------------------------
    // BlackLevel & WhiteLevel

    libraw_colordata_t *colors  = &m_RawProcessor->imgdata.color;

    for (int i = 0; i < 4; i++)
	    m_negative->SetWhiteLevel(static_cast<uint32>(colors->maximum), i);

    if ((m_negative->GetMosaicInfo() != NULL) && (m_negative->GetMosaicInfo()->fCFAPatternSize == dng_point(2, 2)))
        m_negative->SetQuadBlacks(colors->black + colors->cblack[0],
                                  colors->black + colors->cblack[1],
                                  colors->black + colors->cblack[2],
                                  colors->black + colors->cblack[3]);
    else 
    	m_negative->SetBlackLevel(colors->black + colors->cblack[0], 0);

    // -----------------------------------------------------------------------------------------
    // Fixed properties

    m_negative->SetBaselineExposure(0.0);                       // should be fixed per camera
    m_negative->SetBaselineNoise(1.0);
    m_negative->SetBaselineSharpness(1.0);

    // default
    m_negative->SetAntiAliasStrength(dng_urational(100, 100));  // = no aliasing artifacts
    m_negative->SetLinearResponseLimit(1.0);                    // = no non-linear sensor response
    m_negative->SetAnalogBalance(dng_vector_3(1.0, 1.0, 1.0));
    m_negative->SetShadowScale(dng_urational(1, 1));
}
Esempio n. 7
0
dng_rect dng_area_task::RepeatingTile3 () const
	{
	
	return dng_rect ();
	
	}
Esempio n. 8
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;
}