10b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener/*****************************************************************************/
20b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener// Copyright 2006-2009 Adobe Systems Incorporated
30b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener// All Rights Reserved.
40b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener//
50b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener// NOTICE:  Adobe permits you to use, modify, and distribute this file in
60b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener// accordance with the terms of the Adobe license agreement accompanying it.
70b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener/*****************************************************************************/
80b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
90b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener/* $Id: //mondo/dng_sdk_1_4/dng_sdk/source/dng_mosaic_info.cpp#1 $ */
100b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener/* $DateTime: 2012/05/30 13:28:51 $ */
110b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener/* $Change: 832332 $ */
120b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener/* $Author: tknoll $ */
130b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
140b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener/*****************************************************************************/
150b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
160b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener#include "dng_mosaic_info.h"
170b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
180b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener#include "dng_area_task.h"
190b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener#include "dng_assertions.h"
200b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener#include "dng_bottlenecks.h"
210b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener#include "dng_exceptions.h"
220b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener#include "dng_filter_task.h"
230b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener#include "dng_host.h"
240b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener#include "dng_ifd.h"
250b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener#include "dng_image.h"
260b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener#include "dng_info.h"
270b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener#include "dng_negative.h"
280b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener#include "dng_pixel_buffer.h"
290b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener#include "dng_tag_types.h"
300b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener#include "dng_tag_values.h"
310b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener#include "dng_tile_iterator.h"
320b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener#include "dng_utils.h"
330b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
340b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener/*****************************************************************************/
350b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
360b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener// A interpolation kernel for a single pixel of a single plane.
370b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
380b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Krienerclass dng_bilinear_kernel
390b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	{
400b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
410b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	public:
420b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
430b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		enum
440b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
450b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			kMaxCount = 8
460b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			};
470b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
480b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		uint32 fCount;
490b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
500b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		dng_point fDelta [kMaxCount];
510b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
520b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		real32 fWeight32 [kMaxCount];
530b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		uint16 fWeight16 [kMaxCount];
540b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
550b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		int32 fOffset [kMaxCount];
560b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
570b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	public:
580b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
590b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		dng_bilinear_kernel ()
600b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			:	fCount (0)
610b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
620b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
630b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
640b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		void Add (const dng_point &delta,
650b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				  real32 weight);
660b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
670b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		void Finalize (const dng_point &scale,
680b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					   uint32 patRow,
690b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					   uint32 patCol,
700b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					   int32 rowStep,
710b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					   int32 colStep);
720b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
730b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	};
740b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
750b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener/*****************************************************************************/
760b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
770b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Krienervoid dng_bilinear_kernel::Add (const dng_point &delta,
780b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				  			   real32 weight)
790b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	{
800b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
810b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	// Don't add zero weight elements.
820b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
830b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	if (weight <= 0.0f)
840b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		{
850b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		return;
860b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		}
870b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
880b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	// If the delta already matches an existing element, just combine the
890b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	// weights.
900b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
910b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	for (uint32 j = 0; j < fCount; j++)
920b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		{
930b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
940b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		if (fDelta [j] == delta)
950b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
960b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
970b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			fWeight32 [j] += weight;
980b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
990b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			return;
1000b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
1010b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
1020b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
1030b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		}
1040b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
1050b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	// Add element to list.
1060b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
1070b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	DNG_ASSERT (fCount < kMaxCount, "Too many kernel entries")
1080b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
1090b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	fDelta    [fCount] = delta;
1100b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	fWeight32 [fCount] = weight;
1110b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
1120b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	fCount++;
1130b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
1140b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	}
1150b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
1160b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener/*****************************************************************************/
1170b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
1180b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Krienervoid dng_bilinear_kernel::Finalize (const dng_point &scale,
1190b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener									uint32 patRow,
1200b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener							   		uint32 patCol,
1210b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener							   		int32 rowStep,
1220b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener							   		int32 colStep)
1230b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	{
1240b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
1250b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	uint32 j;
1260b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
1270b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	// Adjust deltas to compensate for interpolation upscaling.
1280b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
1290b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	for (j = 0; j < fCount; j++)
1300b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		{
1310b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
1320b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		dng_point &delta = fDelta [j];
1330b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
1340b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		if (scale.v == 2)
1350b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
1360b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
1370b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			delta.v = (delta.v + (int32) (patRow & 1)) >> 1;
1380b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
1390b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
1400b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
1410b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		if (scale.h == 2)
1420b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
1430b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
1440b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			delta.h = (delta.h + (int32) (patCol & 1)) >> 1;
1450b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
1460b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
1470b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
1480b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		}
1490b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
1500b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	// Sort entries into row-column scan order.
1510b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
1520b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	while (true)
1530b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		{
1540b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
1550b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		bool didSwap = false;
1560b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
1570b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		for (j = 1; j < fCount; j++)
1580b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
1590b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
1600b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			dng_point &delta0 = fDelta [j - 1];
1610b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			dng_point &delta1 = fDelta [j    ];
1620b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
1630b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			if (delta0.v > delta1.v ||
1640b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					(delta0.v == delta1.v &&
1650b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					 delta0.h >  delta1.h))
1660b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
1670b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
1680b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				didSwap = true;
1690b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
1700b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				dng_point tempDelta = delta0;
1710b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
1720b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				delta0 = delta1;
1730b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				delta1 = tempDelta;
1740b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
1750b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				real32 tempWeight = fWeight32 [j - 1];
1760b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
1770b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				fWeight32 [j - 1] = fWeight32 [j];
1780b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				fWeight32 [j    ] = tempWeight;
1790b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
1800b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
1810b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
1820b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
1830b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
1840b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		if (!didSwap)
1850b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
1860b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			break;
1870b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
1880b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
1890b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		}
1900b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
1910b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	// Calculate offsets.
1920b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
1930b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	for (j = 0; j < fCount; j++)
1940b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		{
1950b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
1960b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		fOffset [j] = rowStep * fDelta [j].v +
1970b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					  colStep * fDelta [j].h;
1980b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
1990b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		}
2000b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
2010b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	// Calculate 16-bit weights.
2020b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
2030b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	uint16 total   = 0;
2040b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	uint32 biggest = 0;
2050b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
2060b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	for (j = 0; j < fCount; j++)
2070b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		{
2080b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
2090b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		// Round weights to 8 fractional bits.
2100b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
2110b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		fWeight16 [j] = (uint16) Round_uint32 (fWeight32 [j] * 256.0);
2120b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
2130b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		// Keep track of total of weights.
2140b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
2150b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		total += fWeight16 [j];
2160b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
2170b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		// Keep track of which weight is biggest.
2180b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
2190b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		if (fWeight16 [biggest] < fWeight16 [j])
2200b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
2210b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
2220b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			biggest = j;
2230b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
2240b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
2250b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
2260b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		}
2270b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
2280b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	// Adjust largest entry so total of weights is exactly 256.
2290b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
2300b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	fWeight16 [biggest] += (256 - total);
2310b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
2320b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	// Recompute the floating point weights from the rounded integer weights
2330b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	// so results match more closely.
2340b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
2350b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	for (j = 0; j < fCount; j++)
2360b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		{
2370b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
2380b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		fWeight32 [j] = fWeight16 [j] * (1.0f / 256.0f);
2390b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
2400b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		}
2410b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
2420b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	}
2430b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
2440b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener/*****************************************************************************/
2450b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
2460b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Krienerclass dng_bilinear_pattern
2470b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	{
2480b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
2490b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	public:
2500b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
2510b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		enum
2520b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
2530b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			kMaxPattern = kMaxCFAPattern * 2
2540b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			};
2550b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
2560b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		dng_point fScale;
2570b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
2580b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		uint32 fPatRows;
2590b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		uint32 fPatCols;
2600b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
2610b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		dng_bilinear_kernel fKernel [kMaxPattern]
2620b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					  		        [kMaxPattern];
2630b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
2640b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		uint32 fCounts [kMaxPattern]
2650b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					   [kMaxPattern];
2660b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
2670b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		int32 *fOffsets [kMaxPattern]
2680b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						[kMaxPattern];
2690b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
2700b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		uint16 *fWeights16 [kMaxPattern]
2710b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						   [kMaxPattern];
2720b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
2730b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		real32 *fWeights32 [kMaxPattern]
2740b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						   [kMaxPattern];
2750b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
2760b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	public:
2770b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
2780b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		dng_bilinear_pattern ()
2790b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
2800b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			:	fScale ()
2810b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			,	fPatRows (0)
2820b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			,	fPatCols (0)
2830b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
2840b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
2850b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
2860b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
2870b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	private:
2880b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
2890b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener#if defined(__clang__) && defined(__has_attribute)
2900b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener#if __has_attribute(no_sanitize)
2910b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener__attribute__((no_sanitize("unsigned-integer-overflow")))
2920b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener#endif
2930b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener#endif
2940b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		uint32 DeltaRow (uint32 row, int32 delta)
2950b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
296c89552e7ed1e0ea69c69addf2bb5de011188d297Florian Kriener			// Potential overflow in the conversion from delta to a uint32 as
297c89552e7ed1e0ea69c69addf2bb5de011188d297Florian Kriener			// well as in the subsequent addition is intentional.
298c89552e7ed1e0ea69c69addf2bb5de011188d297Florian Kriener			return (SafeUint32Add(row, fPatRows) + (uint32) delta) % fPatRows;
2990b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
300c89552e7ed1e0ea69c69addf2bb5de011188d297Florian Kriener
3010b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener#if defined(__clang__) && defined(__has_attribute)
3020b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener#if __has_attribute(no_sanitize)
3030b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener__attribute__((no_sanitize("unsigned-integer-overflow")))
304c89552e7ed1e0ea69c69addf2bb5de011188d297Florian Kriener#endif
3050b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener#endif
3060b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		uint32 DeltaCol (uint32 col, int32 delta)
3070b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
308c89552e7ed1e0ea69c69addf2bb5de011188d297Florian Kriener			// Potential overflow in the conversion from delta to a uint32 as
309c89552e7ed1e0ea69c69addf2bb5de011188d297Florian Kriener			// well as in the subsequent addition is intentional.
310c89552e7ed1e0ea69c69addf2bb5de011188d297Florian Kriener			return (SafeUint32Add(col, fPatCols) + (uint32) delta) % fPatCols;
3110b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
3120b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
3130b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		real32 LinearWeight1 (int32 d1, int32 d2)
3140b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
3150b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			if (d1 == d2)
3160b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				return 1.0f;
3170b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			else
3180b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				return d2 / (real32) (d2 - d1);
3190b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
3200b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
3210b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		real32 LinearWeight2 (int32 d1, int32 d2)
3220b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
3230b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			if (d1 == d2)
3240b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				return 0.0f;
3250b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			else
3260b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				return -d1 / (real32) (d2 - d1);
3270b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
3280b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
3290b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	public:
3300b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
3310b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		void Calculate (const dng_mosaic_info &info,
3320b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						uint32 dstPlane,
3330b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						int32 rowStep,
3340b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						int32 colStep);
3350b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
3360b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	};
3370b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
3380b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener/*****************************************************************************/
3390b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
3400b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Krienervoid dng_bilinear_pattern::Calculate (const dng_mosaic_info &info,
3410b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						  			  uint32 dstPlane,
3420b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						  			  int32 rowStep,
3430b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						  			  int32 colStep)
3440b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	{
3450b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
3460b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	uint32 j;
3470b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	uint32 k;
3480b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	uint32 patRow;
3490b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	uint32 patCol;
3500b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
3510b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	// Find destination pattern size.
3520b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
3530b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	fScale = info.FullScale ();
3540b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
3550b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	fPatRows = info.fCFAPatternSize.v * fScale.v;
3560b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	fPatCols = info.fCFAPatternSize.h * fScale.h;
3570b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
3580b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	// See if we need to scale up just while computing the kernels.
3590b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
3600b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	dng_point tempScale (1, 1);
3610b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
3620b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	if (info.fCFALayout >= 6)
3630b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		{
3640b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
3650b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		tempScale = dng_point (2, 2);
3660b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
3670b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		fPatRows *= tempScale.v;
3680b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		fPatCols *= tempScale.h;
3690b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
3700b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		}
3710b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
3720b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	// Find a boolean map for this plane color and layout.
3730b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
3740b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	bool map [kMaxPattern]
3750b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			 [kMaxPattern];
3760b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
3770b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	uint8 planeColor = info.fCFAPlaneColor [dstPlane];
3780b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
3790b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	switch (info.fCFALayout)
3800b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		{
3810b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
3820b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		case 1:		// Rectangular (or square) layout
3830b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
3840b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
3850b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			for (j = 0; j < fPatRows; j++)
3860b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
3870b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
3880b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				for (k = 0; k < fPatCols; k++)
3890b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					{
3900b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
3910b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					map [j] [k] = (info.fCFAPattern [j] [k] == planeColor);
3920b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
3930b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					}
3940b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
3950b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
3960b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
3970b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			break;
3980b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
3990b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
4000b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4010b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		// Note that when the descriptions of the staggered patterns refer to even rows or
4020b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		// columns, this mean the second, fourth, etc. (i.e. using one-based numbering).
4030b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		// This needs to be clarified in the DNG specification.
4040b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4050b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		case 2:		// Staggered layout A: even (1-based) columns are offset down by 1/2 row
4060b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
4070b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4080b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			for (j = 0; j < fPatRows; j++)
4090b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
4100b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4110b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				for (k = 0; k < fPatCols; k++)
4120b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					{
4130b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4140b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					if ((j & 1) != (k & 1))
4150b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						{
4160b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4170b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						map [j] [k] = false;
4180b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4190b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						}
4200b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4210b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					else
4220b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						{
4230b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4240b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						map [j] [k] = (info.fCFAPattern [j >> 1] [k] == planeColor);
4250b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4260b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						}
4270b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4280b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					}
4290b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4300b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
4310b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4320b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			break;
4330b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4340b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
4350b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4360b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		case 3:		// Staggered layout B: even (1-based) columns are offset up by 1/2 row
4370b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
4380b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4390b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			for (j = 0; j < fPatRows; j++)
4400b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
4410b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4420b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				for (k = 0; k < fPatCols; k++)
4430b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					{
4440b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4450b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					if ((j & 1) == (k & 1))
4460b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						{
4470b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4480b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						map [j] [k] = false;
4490b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4500b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						}
4510b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4520b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					else
4530b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						{
4540b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4550b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						map [j] [k] = (info.fCFAPattern [j >> 1] [k] == planeColor);
4560b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4570b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						}
4580b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4590b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					}
4600b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4610b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
4620b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4630b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			break;
4640b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4650b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
4660b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4670b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		case 4:		// Staggered layout C: even (1-based) rows are offset right by 1/2 column
4680b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
4690b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4700b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			for (j = 0; j < fPatRows; j++)
4710b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
4720b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4730b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				for (k = 0; k < fPatCols; k++)
4740b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					{
4750b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4760b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					if ((j & 1) != (k & 1))
4770b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						{
4780b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4790b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						map [j] [k] = false;
4800b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4810b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						}
4820b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4830b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					else
4840b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						{
4850b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4860b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						map [j] [k] = (info.fCFAPattern [j] [k >> 1] == planeColor);
4870b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4880b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						}
4890b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4900b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					}
4910b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4920b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
4930b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4940b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			break;
4950b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4960b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
4970b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
4980b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		case 5:		// Staggered layout D: even (1-based) rows are offset left by 1/2 column
4990b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
5000b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
5010b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			for (j = 0; j < fPatRows; j++)
5020b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
5030b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
5040b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				for (k = 0; k < fPatCols; k++)
5050b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					{
5060b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
5070b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					if ((j & 1) == (k & 1))
5080b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						{
5090b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
5100b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						map [j] [k] = false;
5110b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
5120b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						}
5130b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
5140b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					else
5150b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						{
5160b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
5170b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						map [j] [k] = (info.fCFAPattern [j] [k >> 1] == planeColor);
5180b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
5190b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						}
5200b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
5210b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					}
5220b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
5230b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
5240b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
5250b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			break;
5260b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
5270b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
5280b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
5290b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		case 6:		// Staggered layout E: even rows are offset up by 1/2 row, even columns are offset left by 1/2 column
5300b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		case 7:		// Staggered layout F: even rows are offset up by 1/2 row, even columns are offset right by 1/2 column
5310b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		case 8:		// Staggered layout G: even rows are offset down by 1/2 row, even columns are offset left by 1/2 column
5320b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		case 9:		// Staggered layout H: even rows are offset down by 1/2 row, even columns are offset right by 1/2 column
5330b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
5340b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
5350b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			uint32 eRow = (info.fCFALayout == 6 ||
5360b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						   info.fCFALayout == 7) ? 1 : 3;
5370b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
5380b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			uint32 eCol = (info.fCFALayout == 6 ||
5390b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						   info.fCFALayout == 8) ? 1 : 3;
5400b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
5410b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			for (j = 0; j < fPatRows; j++)
5420b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
5430b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
5440b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				for (k = 0; k < fPatCols; k++)
5450b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					{
5460b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
5470b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					uint32 jj = j & 3;
5480b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					uint32 kk = k & 3;
5490b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
5500b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					if ((jj != 0 && jj != eRow) ||
5510b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						(kk != 0 && kk != eCol))
5520b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						{
5530b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
5540b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						map [j] [k] = false;
5550b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
5560b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						}
5570b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
5580b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					else
5590b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						{
5600b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
5610b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						map [j] [k] = (info.fCFAPattern [((j >> 1) & ~1) + Min_uint32 (jj, 1)]
5620b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener														[((k >> 1) & ~1) + Min_uint32 (kk, 1)] == planeColor);
5630b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
5640b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						}
5650b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
5660b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					}
5670b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
5680b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
5690b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
5700b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			break;
5710b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
5720b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
5730b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
5740b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		default:
5750b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			ThrowProgramError ();
5760b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
5770b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		}
5780b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
5790b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	// Find projections of maps.
5800b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
5810b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	bool mapH [kMaxPattern];
5820b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	bool mapV [kMaxPattern];
5830b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
5840b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	for (j = 0; j < kMaxPattern; j++)
5850b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		{
5860b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
5870b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		mapH [j] = false;
5880b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		mapV [j] = false;
5890b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
5900b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		}
5910b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
5920b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	for (j = 0; j < fPatRows; j++)
5930b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		{
5940b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
5950b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		for (k = 0; k < fPatCols; k++)
5960b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
5970b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
5980b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			if (map [j] [k])
5990b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
6000b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
6010b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				mapV [j] = true;
6020b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				mapH [k] = true;
6030b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
6040b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
6050b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
6060b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
6070b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
6080b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		}
6090b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
6100b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	// Find kernel for each patten entry.
6110b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
6120b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	for (patRow = 0; patRow < fPatRows; patRow += tempScale.v)
6130b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		{
6140b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
6150b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		for (patCol = 0; patCol < fPatCols; patCol += tempScale.h)
6160b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
6170b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
6180b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			dng_bilinear_kernel &kernel = fKernel [patRow] [patCol];
6190b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
6200b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			// Special case no interpolation case.
6210b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
6220b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			if (map [patRow] [patCol])
6230b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
6240b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
6250b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				kernel.Add (dng_point (0, 0), 1.0f);
6260b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
6270b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				continue;
6280b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
6290b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
6300b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
6310b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			// Special case common patterns in 3 by 3 neighborhood.
6320b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
6330b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			uint32 n = DeltaRow (patRow, -1);
6340b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			uint32 s = DeltaRow (patRow,  1);
6350b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			uint32 w = DeltaCol (patCol, -1);
6360b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			uint32 e = DeltaCol (patCol,  1);
6370b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
6380b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			bool mapNW = map [n] [w];
6390b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			bool mapN  = map [n] [patCol];
6400b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			bool mapNE = map [n] [e];
6410b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
6420b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			bool mapW = map [patRow] [w];
6430b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			bool mapE = map [patRow] [e];
6440b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
6450b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			bool mapSW = map [s] [w];
6460b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			bool mapS  = map [s] [patCol];
6470b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			bool mapSE = map [s] [e];
6480b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
6490b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			// All sides.
6500b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
6510b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			if (mapN && mapS && mapW && mapW)
6520b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
6530b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
6540b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				kernel.Add (dng_point (-1,  0), 0.25f);
6550b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				kernel.Add (dng_point ( 0, -1), 0.25f);
6560b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				kernel.Add (dng_point ( 0,  1), 0.25f);
6570b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				kernel.Add (dng_point ( 1,  0), 0.25f);
6580b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
6590b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				continue;
6600b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
6610b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
6620b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
6630b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			// N & S.
6640b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
6650b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			if (mapN && mapS)
6660b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
6670b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
6680b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				kernel.Add (dng_point (-1,  0), 0.5f);
6690b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				kernel.Add (dng_point ( 1,  0), 0.5f);
6700b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
6710b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				continue;
6720b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
6730b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
6740b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
6750b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			// E & W.
6760b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
6770b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			if (mapW && mapE)
6780b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
6790b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
6800b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				kernel.Add (dng_point ( 0, -1), 0.5f);
6810b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				kernel.Add (dng_point ( 0,  1), 0.5f);
6820b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
6830b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				continue;
6840b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
6850b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
6860b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
6870b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			// N & SW & SE.
6880b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
6890b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			if (mapN && mapSW && mapSE)
6900b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
6910b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
6920b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				kernel.Add (dng_point (-1,  0), 0.50f);
6930b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				kernel.Add (dng_point ( 1, -1), 0.25f);
6940b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				kernel.Add (dng_point ( 1,  1), 0.25f);
6950b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
6960b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				continue;
6970b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
6980b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
6990b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
7000b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			// S & NW & NE.
7010b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
7020b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			if (mapS && mapNW && mapNE)
7030b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
7040b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
7050b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				kernel.Add (dng_point (-1, -1), 0.25f);
7060b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				kernel.Add (dng_point (-1,  1), 0.25f);
7070b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				kernel.Add (dng_point ( 1,  0), 0.50f);
7080b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
7090b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				continue;
7100b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
7110b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
7120b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
7130b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			// W & NE & SE.
7140b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
7150b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			if (mapW && mapNE && mapSE)
7160b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
7170b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
7180b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				kernel.Add (dng_point (-1,  1), 0.25f);
7190b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				kernel.Add (dng_point ( 0, -1), 0.50f);
7200b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				kernel.Add (dng_point ( 1,  1), 0.25f);
7210b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
7220b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				continue;
7230b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
7240b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
7250b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
7260b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			// E & NW & SW.
7270b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
7280b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			if (mapE && mapNW && mapSW)
7290b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
7300b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
7310b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				kernel.Add (dng_point (-1, -1), 0.25f);
7320b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				kernel.Add (dng_point ( 0,  1), 0.50f);
7330b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				kernel.Add (dng_point ( 1, -1), 0.25f);
7340b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
7350b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				continue;
7360b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
7370b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
7380b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
7390b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			// Four corners.
7400b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
7410b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			if (mapNW && mapNE && mapSE && mapSW)
7420b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
7430b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
7440b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				kernel.Add (dng_point (-1, -1), 0.25f);
7450b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				kernel.Add (dng_point (-1,  1), 0.25f);
7460b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				kernel.Add (dng_point ( 1, -1), 0.25f);
7470b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				kernel.Add (dng_point ( 1,  1), 0.25f);
7480b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
7490b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				continue;
7500b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
7510b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
7520b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
7530b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			// NW & SE
7540b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
7550b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			if (mapNW && mapSE)
7560b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
7570b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
7580b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				kernel.Add (dng_point (-1, -1), 0.50f);
7590b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				kernel.Add (dng_point ( 1,  1), 0.50f);
7600b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
7610b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				continue;
7620b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
7630b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
7640b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
7650b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			// NE & SW
7660b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
7670b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			if (mapNE && mapSW)
7680b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
7690b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
7700b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				kernel.Add (dng_point (-1,  1), 0.50f);
7710b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				kernel.Add (dng_point ( 1, -1), 0.50f);
7720b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
7730b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				continue;
7740b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
7750b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
7760b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
7770b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			// Else use double-bilinear kernel.
7780b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
7790b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			int32 dv1 = 0;
7800b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			int32 dv2 = 0;
7810b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
7820b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			while (!mapV [DeltaRow (patRow, dv1)])
7830b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
7840b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				dv1--;
7850b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
7860b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
7870b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			while (!mapV [DeltaRow (patRow, dv2)])
7880b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
7890b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				dv2++;
7900b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
7910b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
7920b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			real32 w1 = LinearWeight1 (dv1, dv2) * 0.5f;
7930b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			real32 w2 = LinearWeight2 (dv1, dv2) * 0.5f;
7940b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
7950b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			int32 v1 = DeltaRow (patRow, dv1);
7960b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			int32 v2 = DeltaRow (patRow, dv2);
7970b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
7980b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			int32 dh1 = 0;
7990b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			int32 dh2 = 0;
8000b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
8010b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			while (!map [v1] [DeltaCol (patCol, dh1)])
8020b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
8030b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				dh1--;
8040b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
8050b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
8060b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			while (!map [v1] [DeltaCol (patCol, dh2)])
8070b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
8080b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				dh2++;
8090b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
8100b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
8110b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			kernel.Add (dng_point (dv1, dh1),
8120b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						LinearWeight1 (dh1, dh2) * w1);
8130b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
8140b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			kernel.Add (dng_point (dv1, dh2),
8150b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						LinearWeight2 (dh1, dh2) * w1);
8160b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
8170b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			dh1 = 0;
8180b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			dh2 = 0;
8190b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
8200b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			while (!map [v2] [DeltaCol (patCol, dh1)])
8210b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
8220b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				dh1--;
8230b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
8240b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
8250b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			while (!map [v2] [DeltaCol (patCol, dh2)])
8260b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
8270b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				dh2++;
8280b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
8290b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
8300b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			kernel.Add (dng_point (dv2, dh1),
8310b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						LinearWeight1 (dh1, dh2) * w2);
8320b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
8330b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			kernel.Add (dng_point (dv2, dh2),
8340b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						LinearWeight2 (dh1, dh2) * w2);
8350b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
8360b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			dh1 = 0;
8370b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			dh2 = 0;
8380b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
8390b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			while (!mapH [DeltaCol (patCol, dh1)])
8400b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
8410b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				dh1--;
8420b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
8430b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
8440b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			while (!mapH [DeltaCol (patCol, dh2)])
8450b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
8460b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				dh2++;
8470b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
8480b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
8490b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			w1 = LinearWeight1 (dh1, dh2) * 0.5f;
8500b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			w2 = LinearWeight2 (dh1, dh2) * 0.5f;
8510b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
8520b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			int32 h1 = DeltaCol (patCol, dh1);
8530b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			int32 h2 = DeltaCol (patCol, dh2);
8540b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
8550b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			dv1 = 0;
8560b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			dv2 = 0;
8570b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
8580b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			while (!map [DeltaRow (patRow, dv1)] [h1])
8590b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
8600b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				dv1--;
8610b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
8620b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
8630b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			while (!map [DeltaRow (patRow, dv2)] [h1])
8640b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
8650b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				dv2++;
8660b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
8670b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
8680b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			kernel.Add (dng_point (dv1, dh1),
8690b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						LinearWeight1 (dv1, dv2) * w1);
8700b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
8710b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			kernel.Add (dng_point (dv2, dh1),
8720b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						LinearWeight2 (dv1, dv2) * w1);
8730b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
8740b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			dv1 = 0;
8750b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			dv2 = 0;
8760b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
8770b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			while (!map [DeltaRow (patRow, dv1)] [h2])
8780b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
8790b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				dv1--;
8800b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
8810b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
8820b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			while (!map [DeltaRow (patRow, dv2)] [h2])
8830b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
8840b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				dv2++;
8850b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
8860b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
8870b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			kernel.Add (dng_point (dv1, dh2),
8880b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						LinearWeight1 (dv1, dv2) * w2);
8890b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
8900b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			kernel.Add (dng_point (dv2, dh2),
8910b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						LinearWeight2 (dv1, dv2) * w2);
8920b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
8930b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
8940b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
8950b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		}
8960b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
8970b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	// Deal with temp scale case.
8980b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
8990b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	if (tempScale == dng_point (2, 2))
9000b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		{
9010b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
9020b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		fPatRows /= tempScale.v;
9030b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		fPatCols /= tempScale.h;
9040b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
9050b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		for (patRow = 0; patRow < fPatRows; patRow++)
9060b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
9070b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
9080b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			for (patCol = 0; patCol < fPatCols; patCol++)
9090b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
9100b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
9110b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				int32 patRow2 = patRow << 1;
9120b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				int32 patCol2 = patCol << 1;
9130b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
9140b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				dng_bilinear_kernel &kernel = fKernel [patRow2] [patCol2];
9150b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
9160b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				for (j = 0; j < kernel.fCount; j++)
9170b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					{
9180b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
9190b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					int32 x = patRow2 + kernel.fDelta [j].v;
9200b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
9210b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					if ((x & 3) != 0)
9220b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						{
9230b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						x = (x & ~3) + 2;
9240b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						}
9250b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
9260b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					kernel.fDelta [j].v = ((x - patRow2) >> 1);
9270b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
9280b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					x = patCol2 + kernel.fDelta [j].h;
9290b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
9300b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					if ((x & 3) != 0)
9310b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						{
9320b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						x = (x & ~3) + 2;
9330b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						}
9340b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
9350b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					kernel.fDelta [j].h = ((x - patCol2) >> 1);
9360b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
9370b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					}
9380b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
9390b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				kernel.Finalize (fScale,
9400b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener								 patRow,
9410b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener								 patCol,
9420b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener								 rowStep,
9430b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener								 colStep);
9440b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
9450b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				fCounts    [patRow] [patCol] = kernel.fCount;
9460b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				fOffsets   [patRow] [patCol] = kernel.fOffset;
9470b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				fWeights16 [patRow] [patCol] = kernel.fWeight16;
9480b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				fWeights32 [patRow] [patCol] = kernel.fWeight32;
9490b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
9500b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
9510b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
9520b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
9530b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
9540b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		}
9550b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
9560b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	// Non-temp scale case.
9570b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
9580b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	else
9590b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		{
9600b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
9610b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		for (patRow = 0; patRow < fPatRows; patRow++)
9620b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
9630b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
9640b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			for (patCol = 0; patCol < fPatCols; patCol++)
9650b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
9660b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
9670b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				dng_bilinear_kernel &kernel = fKernel [patRow] [patCol];
9680b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
9690b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				kernel.Finalize (fScale,
9700b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener								 patRow,
9710b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener								 patCol,
9720b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener								 rowStep,
9730b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener								 colStep);
9740b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
9750b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				fCounts    [patRow] [patCol] = kernel.fCount;
9760b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				fOffsets   [patRow] [patCol] = kernel.fOffset;
9770b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				fWeights16 [patRow] [patCol] = kernel.fWeight16;
9780b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				fWeights32 [patRow] [patCol] = kernel.fWeight32;
9790b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
9800b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
9810b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
9820b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
9830b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
9840b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		}
9850b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
9860b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	}
9870b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
9880b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener/*****************************************************************************/
9890b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
9900b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Krienerclass dng_bilinear_interpolator
9910b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	{
9920b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
9930b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	private:
9940b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
9950b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		dng_bilinear_pattern fPattern [kMaxColorPlanes];
9960b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
9970b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	public:
9980b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
9990b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		dng_bilinear_interpolator (const dng_mosaic_info &info,
10000b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener								   int32 rowStep,
10010b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener								   int32 colStep);
10020b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
10030b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		void Interpolate (dng_pixel_buffer &srcBuffer,
10040b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						  dng_pixel_buffer &dstBuffer);
10050b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
10060b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	};
10070b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
10080b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener/*****************************************************************************/
10090b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
10100b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Krienerdng_bilinear_interpolator::dng_bilinear_interpolator (const dng_mosaic_info &info,
10110b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener													  int32 rowStep,
10120b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener													  int32 colStep)
10130b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	{
10140b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
10150b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	for (uint32 dstPlane = 0; dstPlane < info.fColorPlanes; dstPlane++)
10160b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		{
10170b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
10180b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		fPattern [dstPlane] . Calculate (info,
10190b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener										 dstPlane,
10200b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener										 rowStep,
10210b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener										 colStep);
10220b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
10230b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		}
10240b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
10250b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	}
10260b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
10270b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener/*****************************************************************************/
10280b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
10290b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Krienervoid dng_bilinear_interpolator::Interpolate (dng_pixel_buffer &srcBuffer,
10300b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						  					 dng_pixel_buffer &dstBuffer)
10310b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	{
10320b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
10330b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	uint32 patCols = fPattern [0] . fPatCols;
10340b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	uint32 patRows = fPattern [0] . fPatRows;
10350b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
10360b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	dng_point scale = fPattern [0] . fScale;
10370b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
10380b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	uint32 sRowShift = scale.v - 1;
10390b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	uint32 sColShift = scale.h - 1;
10400b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
10410b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	int32 dstCol = dstBuffer.fArea.l;
10420b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
10430b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	int32 srcCol = dstCol >> sColShift;
10440b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
10450b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	uint32 patPhase = dstCol % patCols;
10460b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
10470b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	for (int32 dstRow = dstBuffer.fArea.t;
10480b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		 dstRow < dstBuffer.fArea.b;
10490b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		 dstRow++)
10500b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		{
10510b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
10520b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		int32 srcRow = dstRow >> sRowShift;
10530b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
10540b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		uint32 patRow = dstRow % patRows;
10550b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
10560b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		for (uint32 dstPlane = 0;
10570b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			 dstPlane < dstBuffer.fPlanes;
10580b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			 dstPlane++)
10590b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
10600b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
10610b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			const void *sPtr = srcBuffer.ConstPixel (srcRow,
10620b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener													  srcCol,
10630b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener													  srcBuffer.fPlane);
10640b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
10650b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			void *dPtr = dstBuffer.DirtyPixel (dstRow,
10660b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener										  	   dstCol,
10670b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener										  	   dstPlane);
10680b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
10690b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			if (dstBuffer.fPixelType == ttShort)
10700b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
10710b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
10720b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				DoBilinearRow16 ((const uint16 *) sPtr,
10730b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					   			 (uint16 *) dPtr,
10740b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					   			 dstBuffer.fArea.W (),
10750b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					   			 patPhase,
10760b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					   			 patCols,
10770b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					   			 fPattern [dstPlane].fCounts    [patRow],
10780b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					   			 fPattern [dstPlane].fOffsets   [patRow],
10790b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					   			 fPattern [dstPlane].fWeights16 [patRow],
10800b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					   			 sColShift);
10810b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
10820b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
10830b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
10840b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			else
10850b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
10860b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
10870b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				DoBilinearRow32 ((const real32 *) sPtr,
10880b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					   			 (real32 *) dPtr,
10890b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					   			 dstBuffer.fArea.W (),
10900b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					   			 patPhase,
10910b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					   			 patCols,
10920b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					   			 fPattern [dstPlane].fCounts    [patRow],
10930b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					   			 fPattern [dstPlane].fOffsets   [patRow],
10940b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					   			 fPattern [dstPlane].fWeights32 [patRow],
10950b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					   			 sColShift);
10960b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
10970b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
10980b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
10990b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
11000b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
11010b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		}
11020b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
11030b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	}
11040b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
11050b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener/*****************************************************************************/
11060b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
11070b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Krienerclass dng_fast_interpolator: public dng_filter_task
11080b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	{
11090b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
11100b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	protected:
11110b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
11120b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		const dng_mosaic_info &fInfo;
11130b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
11140b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		dng_point fDownScale;
11150b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
11160b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		uint32 fFilterColor [kMaxCFAPattern] [kMaxCFAPattern];
11170b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
11180b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	public:
11190b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
11200b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		dng_fast_interpolator (const dng_mosaic_info &info,
11210b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener							   const dng_image &srcImage,
11220b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener							   dng_image &dstImage,
11230b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener							   const dng_point &downScale,
11240b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener							   uint32 srcPlane);
11250b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
11260b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		virtual dng_rect SrcArea (const dng_rect &dstArea);
11270b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
11280b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		virtual void ProcessArea (uint32 threadIndex,
11290b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener								  dng_pixel_buffer &srcBuffer,
11300b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener								  dng_pixel_buffer &dstBuffer);
11310b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
11320b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	};
11330b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
11340b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener/*****************************************************************************/
11350b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
11360b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Krienerdng_fast_interpolator::dng_fast_interpolator (const dng_mosaic_info &info,
11370b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener											  const dng_image &srcImage,
11380b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener											  dng_image &dstImage,
11390b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener											  const dng_point &downScale,
11400b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener											  uint32 srcPlane)
11410b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
11420b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	:	dng_filter_task (srcImage,
11430b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						 dstImage)
11440b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
11450b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	,	fInfo       (info     )
11460b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	,	fDownScale  (downScale)
11470b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
11480b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	{
11490b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
11500b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	fSrcPlane  = srcPlane;
11510b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	fSrcPlanes = 1;
11520b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
11530b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	fSrcPixelType = ttShort;
11540b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	fDstPixelType = ttShort;
11550b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
11560b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	fSrcRepeat = fInfo.fCFAPatternSize;
11570b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
11580b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	fUnitCell = fInfo.fCFAPatternSize;
11590b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
11600b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	fMaxTileSize = dng_point (256 / fDownScale.v,
11610b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					  		  256 / fDownScale.h);
11620b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
11630b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	fMaxTileSize.h = Max_int32 (fMaxTileSize.h, fUnitCell.h);
11640b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	fMaxTileSize.v = Max_int32 (fMaxTileSize.v, fUnitCell.v);
11650b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
11660b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	// Find color map.
11670b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
11680b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		{
11690b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
11700b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		for (int32 r = 0; r < fInfo.fCFAPatternSize.v; r++)
11710b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
11720b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
11730b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			for (int32 c = 0; c < fInfo.fCFAPatternSize.h; c++)
11740b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
11750b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
11760b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				uint8 key = fInfo.fCFAPattern [r] [c];
11770b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
11780b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				for (uint32 index = 0; index < fInfo.fColorPlanes; index++)
11790b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					{
11800b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
11810b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					if (key == fInfo.fCFAPlaneColor [index])
11820b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						{
11830b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
11840b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						fFilterColor [r] [c] = index;
11850b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
11860b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						break;
11870b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
11880b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						}
11890b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
11900b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					}
11910b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
11920b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
11930b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
11940b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
11950b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
11960b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		}
11970b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
11980b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	}
11990b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
12000b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener/*****************************************************************************/
12010b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
12020b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Krienerdng_rect dng_fast_interpolator::SrcArea (const dng_rect &dstArea)
12030b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	{
12040b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
12050b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	return dng_rect (dstArea.t * fDownScale.v,
12060b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					 dstArea.l * fDownScale.h,
12070b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					 dstArea.b * fDownScale.v,
12080b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					 dstArea.r * fDownScale.h);
12090b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
12100b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	}
12110b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
12120b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener/*****************************************************************************/
12130b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
12140b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Krienervoid dng_fast_interpolator::ProcessArea (uint32 /* threadIndex */,
12150b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener								  	  	 dng_pixel_buffer &srcBuffer,
12160b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener								      	 dng_pixel_buffer &dstBuffer)
12170b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	{
12180b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
12190b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	dng_rect srcArea = srcBuffer.fArea;
12200b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	dng_rect dstArea = dstBuffer.fArea;
12210b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
12220b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	// Downsample buffer.
12230b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
12240b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	int32 srcRow = srcArea.t;
12250b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
12260b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	uint32 srcRowPhase1 = 0;
12270b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	uint32 srcRowPhase2 = 0;
12280b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
12290b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	uint32 patRows = fInfo.fCFAPatternSize.v;
12300b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	uint32 patCols = fInfo.fCFAPatternSize.h;
12310b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
12320b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	uint32 cellRows = fDownScale.v;
12330b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	uint32 cellCols = fDownScale.h;
12340b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
12350b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	uint32 plane;
12360b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	uint32 planes = fInfo.fColorPlanes;
12370b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
12380b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	int32 dstPlaneStep = dstBuffer.fPlaneStep;
12390b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
12400b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	uint32 total [kMaxColorPlanes];
12410b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	uint32 count [kMaxColorPlanes];
12420b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
12430b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	for (plane = 0; plane < planes; plane++)
12440b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		{
12450b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		total [plane] = 0;
12460b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		count [plane] = 0;
12470b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		}
12480b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
12490b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	for (int32 dstRow = dstArea.t; dstRow < dstArea.b; dstRow++)
12500b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		{
12510b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
12520b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		const uint16 *sPtr = srcBuffer.ConstPixel_uint16 (srcRow,
12530b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener														  srcArea.l,
12540b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener														  fSrcPlane);
12550b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
12560b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		uint16 *dPtr = dstBuffer.DirtyPixel_uint16 (dstRow,
12570b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener													dstArea.l,
12580b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener													0);
12590b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
12600b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		uint32 srcColPhase1 = 0;
12610b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		uint32 srcColPhase2 = 0;
12620b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
12630b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		for (int32 dstCol = dstArea.l; dstCol < dstArea.r; dstCol++)
12640b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
12650b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
12660b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			const uint16 *ssPtr = sPtr;
12670b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
12680b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			srcRowPhase2 = srcRowPhase1;
12690b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
12700b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			for (uint32 cellRow = 0; cellRow < cellRows; cellRow++)
12710b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
12720b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
12730b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				const uint32 *filterRow = fFilterColor [srcRowPhase2];
12740b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
12750b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				if (++srcRowPhase2 == patRows)
12760b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					{
12770b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					srcRowPhase2 = 0;
12780b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					}
12790b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
12800b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				srcColPhase2 = srcColPhase1;
12810b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
12820b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				for (uint32 cellCol = 0; cellCol < cellCols; cellCol++)
12830b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					{
12840b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
12850b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					uint32 color = filterRow [srcColPhase2];
12860b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
12870b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					if (++srcColPhase2 == patCols)
12880b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						{
12890b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						srcColPhase2 = 0;
12900b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						}
12910b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
12920b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					total [color] += (uint32) ssPtr [cellCol];
12930b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					count [color] ++;
12940b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
12950b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					}
12960b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
12970b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				ssPtr += srcBuffer.fRowStep;
12980b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
12990b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
13000b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
13010b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			for (plane = 0; plane < planes; plane++)
13020b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
13030b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
13040b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				uint32 t = total [plane];
13050b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				uint32 c = count [plane];
13060b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
13070b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				dPtr [plane * dstPlaneStep] = (uint16) ((t + (c >> 1)) / c);
13080b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
13090b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				total [plane] = 0;
13100b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				count [plane] = 0;
13110b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
13120b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
13130b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
13140b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			srcColPhase1 = srcColPhase2;
13150b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
13160b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			sPtr += cellCols;
13170b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
13180b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			dPtr ++;
13190b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
13200b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
13210b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
13220b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		srcRowPhase1 = srcRowPhase2;
13230b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
13240b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		srcRow += cellRows;
13250b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
13260b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		}
13270b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
13280b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	}
13290b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
13300b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener/*****************************************************************************/
13310b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
13320b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Krienerdng_mosaic_info::dng_mosaic_info ()
13330b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
13340b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	:	fCFAPatternSize  ()
13350b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	,	fColorPlanes     (0)
13360b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	,	fCFALayout		 (1)
13370b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	,	fBayerGreenSplit (0)
13380b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	,	fSrcSize		 ()
13390b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	,	fCroppedSize     ()
13400b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	,	fAspectRatio     (1.0)
13410b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
13420b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	{
13430b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
13440b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	}
13450b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
13460b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener/*****************************************************************************/
13470b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
13480b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Krienerdng_mosaic_info::~dng_mosaic_info ()
13490b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	{
13500b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
13510b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	}
13520b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
13530b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener/*****************************************************************************/
13540b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
13550b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Krienervoid dng_mosaic_info::Parse (dng_host & /* host */,
13560b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener							 dng_stream & /* stream */,
13570b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener							 dng_info &info)
13580b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	{
13590b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
13600b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	// Find main image IFD.
13610b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
13620b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	dng_ifd &rawIFD = *info.fIFD [info.fMainIndex].Get ();
13630b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
13640b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	// This information only applies to CFA images.
13650b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
13660b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	if (rawIFD.fPhotometricInterpretation != piCFA)
13670b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		{
13680b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		return;
13690b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		}
13700b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
13710b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	// Copy CFA pattern.
13720b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
13730b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	fCFAPatternSize.v = rawIFD.fCFARepeatPatternRows;
13740b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	fCFAPatternSize.h = rawIFD.fCFARepeatPatternCols;
13750b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
13760b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	for (int32 j = 0; j < fCFAPatternSize.v; j++)
13770b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		{
13780b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		for (int32 k = 0; k < fCFAPatternSize.h; k++)
13790b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
13800b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			fCFAPattern [j] [k] = rawIFD.fCFAPattern [j] [k];
13810b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
13820b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		}
13830b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
13840b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	// Copy CFA plane information.
13850b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
13860b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	fColorPlanes = info.fShared->fCameraProfile.fColorPlanes;
13870b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
13880b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	for (uint32 n = 0; n < fColorPlanes; n++)
13890b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		{
13900b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		fCFAPlaneColor [n] = rawIFD.fCFAPlaneColor [n];
13910b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		}
13920b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
13930b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	// Copy CFA layout information.
13940b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
13950b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	fCFALayout = rawIFD.fCFALayout;
13960b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
13970b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	// Green split value for Bayer patterns.
13980b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
13990b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	fBayerGreenSplit = rawIFD.fBayerGreenSplit;
14000b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
14010b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	}
14020b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
14030b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener/*****************************************************************************/
14040b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
14050b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Krienervoid dng_mosaic_info::PostParse (dng_host & /* host */,
14060b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener								 dng_negative &negative)
14070b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	{
14080b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
14090b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	// Keep track of source image size.
14100b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
14110b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	fSrcSize = negative.Stage2Image ()->Size ();
14120b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
14130b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	// Default cropped size.
14140b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
14150b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	fCroppedSize.v = Round_int32 (negative.DefaultCropSizeV ().As_real64 ());
14160b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	fCroppedSize.h = Round_int32 (negative.DefaultCropSizeH ().As_real64 ());
14170b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
14180b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	// Pixel aspect ratio.
14190b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
14200b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	fAspectRatio = negative.DefaultScaleH ().As_real64 () /
14210b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				   negative.DefaultScaleV ().As_real64 ();
14220b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
14230b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	}
14240b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
14250b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener/*****************************************************************************/
14260b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
14270b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Krienerbool dng_mosaic_info::SetFourColorBayer ()
14280b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	{
14290b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
14300b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	if (fCFAPatternSize != dng_point (2, 2))
14310b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		{
14320b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		return false;
14330b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		}
14340b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
14350b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	if (fColorPlanes != 3)
14360b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		{
14370b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		return false;
14380b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		}
14390b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
14400b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	uint8 color0 = fCFAPlaneColor [0];
14410b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	uint8 color1 = fCFAPlaneColor [1];
14420b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	uint8 color2 = fCFAPlaneColor [2];
14430b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
14440b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	// Look for color 1 repeated twice in a diagonal.
14450b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
14460b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	if ((fCFAPattern [0] [0] == color1 && fCFAPattern [1] [1] == color1) ||
14470b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		(fCFAPattern [0] [1] == color1 && fCFAPattern [1] [0] == color1))
14480b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		{
14490b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
14500b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		// OK, this looks like a Bayer pattern.
14510b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
14520b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		// Find unused color code.
14530b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
14540b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		uint8 color3 = 0;
14550b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
14560b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		while (color3 == color0 ||
14570b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			   color3 == color1 ||
14580b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			   color3 == color2)
14590b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
14600b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			color3++;
14610b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
14620b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
14630b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		// Switch the four color mosaic.
14640b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
14650b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		fColorPlanes = 4;
14660b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
14670b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		fCFAPlaneColor [3] = color3;
14680b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
14690b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		// Replace the "green" in the "blue" rows with the new color.
14700b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
14710b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		if (fCFAPattern [0] [0] == color0)
14720b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
14730b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			fCFAPattern [1] [0] = color3;
14740b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
14750b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
14760b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		else if (fCFAPattern [0] [1] == color0)
14770b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
14780b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			fCFAPattern [1] [1] = color3;
14790b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
14800b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
14810b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		else if (fCFAPattern [1] [0] == color0)
14820b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
14830b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			fCFAPattern [0] [0] = color3;
14840b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
14850b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
14860b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		else
14870b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
14880b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			fCFAPattern [0] [1] = color3;
14890b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
14900b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
14910b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		return true;
14920b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
14930b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		}
14940b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
14950b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	return false;
14960b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
14970b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	}
14980b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
14990b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener/*****************************************************************************/
15000b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
15010b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Krienerdng_point dng_mosaic_info::FullScale () const
15020b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	{
15030b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
15040b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	switch (fCFALayout)
15050b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		{
15060b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
15070b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		// Staggered layouts with offset columns double the row count
15080b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		// during interpolation.
15090b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
15100b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		case 2:
15110b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		case 3:
15120b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			return dng_point (2, 1);
15130b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
15140b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		// Staggered layouts with offset rows double the column count
15150b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		// during interpolation.
15160b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
15170b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		case 4:
15180b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		case 5:
15190b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			return dng_point (1, 2);
15200b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
15210b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		// Otherwise there is no size change during interpolation.
15220b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
15230b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		default:
15240b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			break;
15250b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
15260b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		}
15270b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
15280b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	return dng_point (1, 1);
15290b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
15300b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	}
15310b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
15320b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener/*****************************************************************************/
15330b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
15340b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Krienerbool dng_mosaic_info::IsSafeDownScale (const dng_point &downScale) const
15350b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	{
15360b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
15370b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	if (downScale.v >= fCFAPatternSize.v &&
15380b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		downScale.h >= fCFAPatternSize.h)
15390b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		{
15400b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
15410b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		return true;
15420b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
15430b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		}
15440b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
15450b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	dng_point test;
15460b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
15470b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	test.v = Min_int32 (downScale.v, fCFAPatternSize.v);
15480b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	test.h = Min_int32 (downScale.h, fCFAPatternSize.h);
15490b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
15500b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	for (int32 phaseV = 0; phaseV <= fCFAPatternSize.v - test.v; phaseV++)
15510b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		{
15520b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
15530b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		for (int32 phaseH = 0; phaseH <= fCFAPatternSize.h - test.h; phaseH++)
15540b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
15550b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
15560b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			uint32 plane;
15570b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
15580b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			bool contains [kMaxColorPlanes];
15590b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
15600b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			for (plane = 0; plane < fColorPlanes; plane++)
15610b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
15620b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
15630b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				contains [plane] = false;
15640b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
15650b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
15660b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
15670b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			for (int32 srcRow = 0; srcRow < test.v; srcRow++)
15680b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
15690b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
15700b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				for (int32 srcCol = 0; srcCol < test.h; srcCol++)
15710b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					{
15720b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
15730b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					uint8 srcKey = fCFAPattern [srcRow + phaseV]
15740b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener											   [srcCol + phaseH];
15750b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
15760b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					for (plane = 0; plane < fColorPlanes; plane++)
15770b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						{
15780b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
15790b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						if (srcKey == fCFAPlaneColor [plane])
15800b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener							{
15810b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
15820b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener							contains [plane] = true;
15830b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
15840b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener							}
15850b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
15860b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						}
15870b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
15880b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
15890b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					}
15900b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
15910b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
15920b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
15930b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			for (plane = 0; plane < fColorPlanes; plane++)
15940b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
15950b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
15960b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				if (!contains [plane])
15970b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					{
15980b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
15990b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					return false;
16000b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16010b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					}
16020b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16030b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
16040b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16050b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
16060b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16070b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		}
16080b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16090b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	return true;
16100b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16110b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	}
16120b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16130b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener/*****************************************************************************/
16140b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16150b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Krieneruint32 dng_mosaic_info::SizeForDownScale (const dng_point &downScale) const
16160b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	{
16170b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16180b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	uint32 sizeV = Max_uint32 (1, (fCroppedSize.v + (downScale.v >> 1)) / downScale.v);
16190b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	uint32 sizeH = Max_uint32 (1, (fCroppedSize.h + (downScale.h >> 1)) / downScale.h);
16200b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16210b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	return Max_int32 (sizeV, sizeH);
16220b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16230b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	}
16240b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16250b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener/*****************************************************************************/
16260b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16270b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Krienerbool dng_mosaic_info::ValidSizeDownScale (const dng_point &downScale,
16280b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener										  uint32 minSize) const
16290b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	{
16300b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16310b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	const int32 kMaxDownScale = 64;
16320b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16330b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	if (downScale.h > kMaxDownScale ||
16340b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		downScale.v > kMaxDownScale)
16350b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		{
16360b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16370b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		return false;
16380b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16390b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		}
16400b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16410b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	return SizeForDownScale (downScale) >= minSize;
16420b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16430b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	}
16440b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16450b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener/*****************************************************************************/
16460b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16470b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Krienerdng_point dng_mosaic_info::DownScale (uint32 minSize,
16480b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener									  uint32 prefSize,
16490b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener									  real64 cropFactor) const
16500b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	{
16510b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16520b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	dng_point bestScale (1, 1);
16530b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16540b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	if (prefSize && IsColorFilterArray ())
16550b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		{
16560b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16570b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		// Adjust sizes for crop factor.
16580b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16590b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		minSize  = Round_uint32 (minSize  / cropFactor);
16600b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		prefSize = Round_uint32 (prefSize / cropFactor);
16610b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16620b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		prefSize = Max_uint32 (prefSize, minSize);
16630b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16640b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		// Start by assuming we need the full size image.
16650b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16660b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		int32 bestSize = SizeForDownScale (bestScale);
16670b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16680b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		// Find size of nearly square cell.
16690b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16700b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		dng_point squareCell (1, 1);
16710b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16720b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		if (fAspectRatio < 1.0 / 1.8)
16730b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
16740b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16750b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			squareCell.h = Min_int32 (4, Round_int32 (1.0 / fAspectRatio));
16760b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16770b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
16780b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16790b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		if (fAspectRatio > 1.8)
16800b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
16810b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16820b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			squareCell.v = Min_int32 (4, Round_int32 (fAspectRatio));
16830b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16840b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
16850b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16860b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		// Find minimum safe cell size.
16870b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16880b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		dng_point testScale = squareCell;
16890b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16900b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		while (!IsSafeDownScale (testScale))
16910b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
16920b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16930b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			testScale.v += squareCell.v;
16940b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			testScale.h += squareCell.h;
16950b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16960b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
16970b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
16980b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		// See if this scale is usable.
16990b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
17000b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		if (!ValidSizeDownScale (testScale, minSize))
17010b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
17020b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
17030b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			// We cannot downsample at all...
17040b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
17050b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			return bestScale;
17060b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
17070b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
17080b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
17090b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		// See if this is closer to the preferred size.
17100b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
17110b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		int32 testSize = SizeForDownScale (testScale);
17120b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
17130b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		if (Abs_int32 (testSize - (int32) prefSize) <=
17140b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		    Abs_int32 (bestSize - (int32) prefSize))
17150b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
17160b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			bestScale = testScale;
17170b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			bestSize  = testSize;
17180b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
17190b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
17200b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		else
17210b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
17220b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			return bestScale;
17230b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
17240b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
17250b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		// Now keep adding square cells as long as possible.
17260b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
17270b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		while (true)
17280b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
17290b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
17300b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			testScale.v += squareCell.v;
17310b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			testScale.h += squareCell.h;
17320b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
17330b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			if (IsSafeDownScale (testScale))
17340b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				{
17350b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
17360b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				if (!ValidSizeDownScale (testScale, minSize))
17370b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					{
17380b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					return bestScale;
17390b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					}
17400b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
17410b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				// See if this is closer to the preferred size.
17420b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
17430b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				testSize = SizeForDownScale (testScale);
17440b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
17450b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				if (Abs_int32 (testSize - (int32) prefSize) <=
17460b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					Abs_int32 (bestSize - (int32) prefSize))
17470b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					{
17480b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					bestScale = testScale;
17490b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					bestSize  = testSize;
17500b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					}
17510b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
17520b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				else
17530b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					{
17540b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					return bestScale;
17550b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener					}
17560b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
17570b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener				}
17580b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
17590b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
17600b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
17610b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		}
17620b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
17630b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	return bestScale;
17640b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
17650b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	}
17660b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
17670b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener/*****************************************************************************/
17680b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
17690b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Krienerdng_point dng_mosaic_info::DstSize (const dng_point &downScale) const
17700b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	{
17710b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
17720b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	if (downScale == dng_point (1, 1))
17730b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		{
17740b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
17750b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		dng_point scale = FullScale ();
17760b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
17770b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		return dng_point (fSrcSize.v * scale.v,
17780b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						  fSrcSize.h * scale.h);
17790b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
17800b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		}
17810b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
17820b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	const int32 kMaxDownScale = 64;
17830b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
17840b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	if (downScale.h > kMaxDownScale ||
17850b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		downScale.v > kMaxDownScale)
17860b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		{
17870b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
17880b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		return dng_point (0, 0);
17890b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
17900b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		}
17910b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
17920b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	dng_point size;
17930b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
17940b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	size.v = Max_int32 (1, (fSrcSize.v + (downScale.v >> 1)) / downScale.v);
17950b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	size.h = Max_int32 (1, (fSrcSize.h + (downScale.h >> 1)) / downScale.h);
17960b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
17970b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	return size;
17980b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
17990b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	}
18000b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
18010b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener/*****************************************************************************/
18020b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
18030b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Krienervoid dng_mosaic_info::InterpolateGeneric (dng_host &host,
18040b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener										  dng_negative & /* negative */,
18050b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener								   		  const dng_image &srcImage,
18060b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener								   		  dng_image &dstImage,
18070b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener								   		  uint32 srcPlane) const
18080b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	{
18090b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
18100b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	// Find destination to source bit shifts.
18110b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
18120b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	dng_point scale = FullScale ();
18130b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
18140b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	uint32 srcShiftV = scale.v - 1;
18150b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	uint32 srcShiftH = scale.h - 1;
18160b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
18170b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	// Find tile sizes.
18180b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
18190b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	const uint32 kMaxDstTileRows = 128;
18200b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	const uint32 kMaxDstTileCols = 128;
18210b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
18220b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	dng_point dstTileSize = dstImage.RepeatingTile ().Size ();
18230b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
18240b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	dstTileSize.v = Min_int32 (dstTileSize.v, kMaxDstTileRows);
18250b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	dstTileSize.h = Min_int32 (dstTileSize.h, kMaxDstTileCols);
18260b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
18270b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	dng_point srcTileSize = dstTileSize;
18280b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
18290b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	srcTileSize.v >>= srcShiftV;
18300b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	srcTileSize.h >>= srcShiftH;
18310b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
18320b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	srcTileSize.v += fCFAPatternSize.v * 2;
18330b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	srcTileSize.h += fCFAPatternSize.h * 2;
18340b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
18350b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	// Allocate source buffer.
18360b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
18370b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	dng_pixel_buffer srcBuffer (dng_rect (srcTileSize), srcPlane, 1,
18380b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		 srcImage.PixelType (), pcInterleaved, NULL);
18390b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
18400b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	uint32 srcBufferSize = ComputeBufferSize (srcBuffer.fPixelType,
18410b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener											  srcTileSize, srcBuffer.fPlanes,
18420b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener											  padNone);
18430b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
18440b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	AutoPtr<dng_memory_block> srcData (host.Allocate (srcBufferSize));
18450b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
18460b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	srcBuffer.fData = srcData->Buffer ();
18470b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
18480b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	// Allocate destination buffer.
18490b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
18500b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	dng_pixel_buffer dstBuffer (dng_rect (dstTileSize), 0, fColorPlanes,
18510b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		 dstImage.PixelType (), pcRowInterleaved, NULL);
18520b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
18530b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	uint32 dstBufferSize = ComputeBufferSize (dstBuffer.fPixelType,
18540b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener											  dstTileSize, dstBuffer.fPlanes,
18550b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener											  padNone);
18560b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
18570b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	AutoPtr<dng_memory_block> dstData (host.Allocate (dstBufferSize));
18580b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
18590b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	dstBuffer.fData = dstData->Buffer ();
18600b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
18610b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	// Create interpolator.
18620b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
18630b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	AutoPtr<dng_bilinear_interpolator> interpolator (new dng_bilinear_interpolator (*this,
18640b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener																					srcBuffer.fRowStep,
18650b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener																					srcBuffer.fColStep));
18660b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
18670b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	// Iterate over destination tiles.
18680b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
18690b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	dng_rect dstArea;
18700b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
18710b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	dng_tile_iterator iter1 (dstImage, dstImage.Bounds ());
18720b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
18730b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	while (iter1.GetOneTile (dstArea))
18740b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		{
18750b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
18760b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		// Break into buffer sized tiles.
18770b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
18780b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		dng_rect dstTile;
18790b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
18800b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		dng_tile_iterator iter2 (dstTileSize, dstArea);
18810b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
18820b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		while (iter2.GetOneTile (dstTile))
18830b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			{
18840b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
18850b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			host.SniffForAbort ();
18860b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
18870b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			// Setup buffers for this tile.
18880b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
18890b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			dng_rect srcTile (dstTile);
18900b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
18910b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			srcTile.t >>= srcShiftV;
18920b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			srcTile.b >>= srcShiftV;
18930b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
18940b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			srcTile.l >>= srcShiftH;
18950b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			srcTile.r >>= srcShiftH;
18960b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
18970b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			srcTile.t -= fCFAPatternSize.v;
18980b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			srcTile.b += fCFAPatternSize.v;
18990b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
19000b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			srcTile.l -= fCFAPatternSize.h;
19010b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			srcTile.r += fCFAPatternSize.h;
19020b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
19030b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			srcBuffer.fArea = srcTile;
19040b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			dstBuffer.fArea = dstTile;
19050b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
19060b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			// Get source data.
19070b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
19080b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			srcImage.Get (srcBuffer,
19090b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						  dng_image::edge_repeat,
19100b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						  fCFAPatternSize.v,
19110b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						  fCFAPatternSize.h);
19120b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
19130b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			// Process data.
19140b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
19150b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			interpolator->Interpolate (srcBuffer,
19160b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener									   dstBuffer);
19170b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
19180b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			// Save results.
19190b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
19200b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			dstImage.Put (dstBuffer);
19210b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
19220b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener			}
19230b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
19240b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		}
19250b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
19260b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	}
19270b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
19280b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener/*****************************************************************************/
19290b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
19300b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Krienervoid dng_mosaic_info::InterpolateFast (dng_host &host,
19310b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener									   dng_negative & /* negative */,
19320b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener							  	   	   const dng_image &srcImage,
19330b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener								   	   dng_image &dstImage,
19340b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener								       const dng_point &downScale,
19350b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener								       uint32 srcPlane) const
19360b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	{
19370b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
19380b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	// Create fast interpolator task.
19390b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
19400b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	dng_fast_interpolator interpolator (*this,
19410b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener										srcImage,
19420b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener										dstImage,
19430b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener										downScale,
19440b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener										srcPlane);
19450b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
19460b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	// Find area to process.
19470b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
19480b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	dng_rect bounds = dstImage.Bounds ();
19490b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
19500b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	// Do the interpolation.
19510b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
19520b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	host.PerformAreaTask (interpolator,
19530b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						  bounds);
19540b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
19550b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	}
19560b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
19570b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener/*****************************************************************************/
19580b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
19590b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Krienervoid dng_mosaic_info::Interpolate (dng_host &host,
19600b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener								   dng_negative &negative,
19610b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener							  	   const dng_image &srcImage,
19620b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener								   dng_image &dstImage,
19630b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener								   const dng_point &downScale,
19640b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener								   uint32 srcPlane) const
19650b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	{
19660b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
19670b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	if (downScale == dng_point (1, 1))
19680b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		{
19690b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
19700b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		InterpolateGeneric (host,
19710b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener							negative,
19720b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener							srcImage,
19730b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener							dstImage,
19740b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener							srcPlane);
19750b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
19760b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		}
19770b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
19780b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	else
19790b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		{
19800b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
19810b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		InterpolateFast (host,
19820b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						 negative,
19830b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						 srcImage,
19840b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						 dstImage,
19850b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						 downScale,
19860b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener						 srcPlane);
19870b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
19880b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener		}
19890b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
19900b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener	}
19910b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener
19920b098b759cf9a2a8659babaf8c3b74e1b48ca604Florian Kriener/*****************************************************************************/
1993