// Aqsis
// Copyright (c) 1997 - 2001, Paul C. Gregory
//
// Contact: pgregory@aqsis.com
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

/**
 * Copyright (C) 2006-2007  NTT DATA CORPORATION
 * 
 * Version: 1.0.0 2007/04/01
 *  
 */
package net.cellcomputing.himawari.library;

import java.lang.reflect.Method;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map.Entry;

import net.cellcomputing.himawari.accessory.STLArrayList;
import net.cellcomputing.himawari.accessory.STLPriorityQueue;
import net.cellcomputing.himawari.accessory.STLVector;
import net.cellcomputing.himawari.accessory.Valarray;
import net.cellcomputing.himawari.accessory.ValarrayInt;
import net.cellcomputing.himawari.accessory.Vector;
import net.cellcomputing.himawari.accessory.primitive.p_float;
import net.cellcomputing.himawari.library.types.CqColor;
import net.cellcomputing.himawari.library.types.CqRandom;
import net.cellcomputing.himawari.library.types.CqVector2D;
import net.cellcomputing.himawari.library.types.CqVector3D;
import net.cellcomputing.himawari.util.HimawariLogger;

import static net.cellcomputing.himawari.library.RiGlobal.*;
import static net.cellcomputing.himawari.library.types.PublicFunctions.*;
import static net.cellcomputing.himawari.library.Float_h.*;
import static net.cellcomputing.himawari.library.EqDisplayMode.*;


/**
 * 
 * 
 * 
 * @author NTT DATA Corporation
 */
public strictfp class CqBucket implements IqBucket
{
	//************************************************************************//
	//*** コンストラクタの定義
	//************************************************************************//
	
	/**
	 * コンストラクタ
	 */
	public CqBucket()
	{
		 m_bProcessed = false;
	}
	
	/**
	 * コピーコンストラクタ
	 * @param From
	 */
	public CqBucket( final CqBucket From )
    {
		this.assignment(From);
    }
	
	/**　
	 *　デストラクタ
	 * 何もしない
	 */
	public void destract()
	{
		m_aGPrims.clear();
		m_ampgWaiting.clear();
		m_agridWaiting.clear();
	}

	/**
	 * =演算子のオーバーライド
	 * @param From
	 * @return　このバケットを返す
	 */
	public CqBucket assignment(final CqBucket From )
    {
        m_ampgWaiting = From.m_ampgWaiting;
        m_agridWaiting = From.m_agridWaiting;
        m_bProcessed = From.m_bProcessed;

        return ( this );
    }

	// IqBucketからのオーバライド
	//　ゲッターセッター
	public int	Width() 
    {
        return ( m_XSize );
    }
	public 	int	Height()
    {
        return ( m_YSize );
    }
	public int	RealWidth()
    {
        return ( m_RealWidth );
    }
	public 	int	RealHeight() 
    {
        return ( m_RealHeight );
    }
	public 	int	XOrigin() 
    {
        return ( m_XOrigin );
    }
	public 	int	YOrigin() 
    {
        return ( m_YOrigin );
    }
	
	public  static	int	PixelXSamples()
	{
		return m_PixelXSamples; 
	}
	public  static	int	PixelYSamples()
	{
		return m_PixelYSamples; 
	}
	public 	static	float	FilterXWidth()
	{
		return m_FilterXWidth; 
	}
	public  static	float	FilterYWidth()
	{
		return m_FilterYWidth; 
	}
	public	static	int	NumTimeRanges()
	{
		return m_NumTimeRanges; 
	}
	public	static	int	NumDofBounds()
	{
		return m_NumDofBounds; 
	}

	public	static final CqBound DofSubBound(int index)
	{
		assert(index < m_NumDofBounds);
		//return m_DofBounds.get(index);
		return m_DofBounds[index];
	}

//	----------------------------------------------------------------------
	/** サンプルの色を指定されたスクリーンの位置を得てください。
	 * もしポジションがバケットの外なら黒を返す。
	 * @param iXPos サンプルのスクリーンの位置
	 * @param iYPos サンプルのスクリーンの位置
	 */
	public CqColor Color( int iXPos, int iYPos )
	{
//		CqImagePixel pie;
		int pie;
	    pie = ImageElement( iXPos, iYPos );
//	    if( null != m_aieImage.get(pie) )
	    try
	    {
	          return ( m_aieImage.get(pie).Color() );
//	          return ( m_aieImage[pie].Color() );
	    }
	    catch(ArrayIndexOutOfBoundsException e)
	    {
	          return ( gColBlack );
	    }
	}
	
//	----------------------------------------------------------------------
	/** 　指定された位置のサンプルの透明度を取得する。
	 * もしポジションがバケットの外なら黒を返す。
	 * @param iXPos サンプルのスクリーンの位置
	 * @param iYPos サンプルのスクリーンの位置
	 */
	
	public CqColor Opacity( int iXPos, int iYPos )
	{
//		 CqImagePixel pie;
		int pie;
		pie = ImageElement( iXPos, iYPos );
//		if( null != m_aieImage.get(pie) )
		try
		{
			return ( m_aieImage.get(pie).Opacity() );
//			return ( m_aieImage[pie].Opacity() );
		}
		catch(ArrayIndexOutOfBoundsException e)
		{
			return ( gColBlack );
		}
		   
	}
	
//	----------------------------------------------------------------------
	/** 指定されたスクリーンの位置でのサンプルの範囲を取得する。
	 * もし、ポジションがバケットの外なら０を返す。
	 * @param iXPos サンプルのスクリーンの位置
	 * @param iYPos サンプルのスクリーンの位置
	 */
	public float Coverage( int iXPos, int iYPos )
	{
//		  CqImagePixel  pie;
		int pie;
		pie = ImageElement( iXPos, iYPos );
//		if( null != m_aieImage.get(pie) )
		try
		{
		      return ( m_aieImage.get(pie).Coverage() );
//		      return ( m_aieImage[pie].Coverage() );
		}
		catch(ArrayIndexOutOfBoundsException e)
		{
		      return ( 0.0f );
		}
	}
	
//	----------------------------------------------------------------------
	/** 指定されたスクリーンの位置の深度を取得する。
	 * もしポジションがバケットの外ならFLT_MAX（無限大）を返す。
	 * @param iXPos サンプルのスクリーンの位置
	 * @param iYPos サンプルのスクリーンの位置
	 */
	public float Depth( int iXPos, int iYPos )
	{
//		 CqImagePixel pie;
		int pie;
		pie = ImageElement( iXPos, iYPos );
//	    if( null != m_aieImage.get(pie) )
		try
		{
	        return ( m_aieImage.get(pie).Depth() );
//	        return ( m_aieImage[pie].Depth() );
		}
	    catch(ArrayIndexOutOfBoundsException e)
	    {
	        return ( FLT_MAX );
	    }
	}
	
//	----------------------------------------------------------------------
	/** 指定されたスクリーンの位置のサンプルの深度の最大値を返す。
	 * もし、ポジションがバケットの外なら、FLT_MAX（無限大）を返す。
	 * @param iXPos サンプルのスクリーンの位置
	 * @param iYPos サンプルのスクリーンの位置
	 */

	public float MaxDepth( int iXPos, int iYPos )
	{
//		CqImagePixel pie;
		int pie;
	    pie = ImageElement( iXPos, iYPos );
//	    if( null != m_aieImage.get(pie) )
	    try
	    {
	        return ( m_aieImage.get(pie).MaxDepth() );
//	        return ( m_aieImage[pie].MaxDepth() );
	    }
	    catch(ArrayIndexOutOfBoundsException e)
	    {
	        return ( FLT_MAX );
	    }
}
	
//	----------------------------------------------------------------------
	/** サンプルの数を取得する。
	 * もし、バケットの外なら、0を返す。
	 * @param iXPos サンプルのスクリーンの位置
	 * @param iYPos サンプルのスクリーンの位置
	 */
	public int DataSize( int iXPos, int iYPos )
	{
//		CqImagePixel pie;
		int pie;
	    pie = ImageElement( iXPos, iYPos );
//	    if( null != m_aieImage.get(pie) )
	    try
	    {
	        return ( m_aieImage.get(pie).DataSize() );
//	        return ( m_aieImage[pie].DataSize() );
	    }
	    catch(ArrayIndexOutOfBoundsException e)
	    {
	        return ( 0 );
	    }
	}
	
//	----------------------------------------------------------------------
	/** 与えられたピクセルサンプルのポインタを取得する。
	 * もし、ポジションがバケットの外なら、NULLを返す。
	 * @param iXPos サンプルのスクリーンの位置
	 * @param iYPos サンプルのスクリーンの位置
	 */
	public final Valarray Data( int iXPos, int iYPos )
	{
//		CqImagePixel pie;
		int pie;
	    pie = ImageElement( iXPos, iYPos );
//	    if( null != m_aieImage.get(pie) )
	    try
	    {
	        return ( m_aieImage.get(pie).Data() );
//	        return ( m_aieImage[pie].Data() );
	    }
	    catch(ArrayIndexOutOfBoundsException e)
	    {
	        return ( null );
	    }
	}

//	----------------------------------------------------------------------
	/**
	 * 静的なイメージのエリアを初期化する。
	 * 
	 * 
	 * @param xorigin　バケットのXポジション
	 * @param yorigin　バケットのYポジション
	 * @param xsize バケットのXサイズ
	 * @param ysize バケットのYサイズ
	 * @param fJitter 基本的にはtureジッターするかどうか
	 * @param empty　このフラグを立てると、m_aieImageの中を空にする。
	 */
	public static	void	InitialiseBucket( int xorigin, int yorigin, int xsize, int ysize)
	{
		InitialiseBucket( xorigin , yorigin , xsize, ysize, true, false );
	}
	public static	void	InitialiseBucket( int xorigin, int yorigin, int xsize, int ysize, boolean fJitter )
	{
		InitialiseBucket( xorigin , yorigin , xsize, ysize, fJitter, false );
	}
	
	public static	void	InitialiseBucket( int xorigin, int yorigin, int xsize, int ysize, boolean fJitter, boolean empty )
	{
		m_XOrigin = xorigin;
	    m_YOrigin = yorigin;
	    m_XSize = xsize;
	    m_YSize = ysize;
		m_PixelXSamples = m_ImageBuffer.PixelXSamples();
		m_PixelYSamples = m_ImageBuffer.PixelYSamples();
		m_FilterXWidth = m_ImageBuffer.FilterXWidth();
		m_FilterYWidth = m_ImageBuffer.FilterYWidth();
		m_DiscreteShiftX = (int)Math.floor(m_FilterXWidth/2.0f);
		m_DiscreteShiftY = (int)Math.floor(m_FilterYWidth/2.0f);
		m_RealWidth = m_XSize + (m_DiscreteShiftX*2);
		m_RealHeight = m_YSize + (m_DiscreteShiftY*2);

		m_NumTimeRanges = Math.max(4, m_PixelXSamples * m_PixelYSamples);

	    // Allocate the image element storage if this is the first bucket
		if( m_aieImage.isEmpty() )
//		if( m_aieImage == null )
	    {
	        m_aieImage.setSize( m_RealWidth * m_RealHeight );
//			m_aieImage = new CqImagePixel[ m_RealWidth * m_RealHeight ];
//			for(int i = 0 ; i< m_RealWidth * m_RealHeight ; i++)
//			{
//				m_aieImage[i] = new CqImagePixel();
//			}
			m_aSamplePositions.setSize( m_RealWidth * m_RealHeight );
	      	        
			CalculateDofBounds();

	        // Initialise the samples for this bucket.
	        int which = 0;
	        for ( int i = 0; i < m_RealHeight; i++ )
	        {
	            for ( int j = 0; j < m_RealWidth; j++ )
	            {
	                m_aieImage.get(which).Clear();
	                m_aieImage.get(which).AllocateSamples( m_PixelXSamples, m_PixelYSamples );
	                m_aieImage.get(which).InitialiseSamples( m_aSamplePositions.get(which), fJitter );
					m_aieImage.get(which).ShuffleSamples();
					
//					m_aieImage[which].Clear();
//	                m_aieImage[which].AllocateSamples( m_PixelXSamples, m_PixelYSamples );
//	                m_aieImage[which].InitialiseSamples( m_aSamplePositions.get(which), fJitter );
//					m_aieImage[which].ShuffleSamples();

	                which++;
	            }
	        }
	    }
		
		//:TODO: AGG, sort out sample shuffling.
		// now shuffle the pixels around and add in the pixel offset to the position.
//		std::random_shuffle(m_aieImage.begin(), m_aieImage.end());
//		Collections.shuffle(m_aieImage); //2005/12/20 渡辺 Random
		
		//buti高速化******************************::***********復活してね
		Collections.shuffle(m_aieImage,rand);
		
		
		int which = 0;
//		int numPixels = m_RealWidth*m_RealHeight;
		for ( int i = 0; i < m_RealHeight; i++ )
		{
			for ( int j = 0; j < m_RealWidth; j++ )
			{
				CqVector2D bPos2 = new CqVector2D( m_XOrigin, m_YOrigin );
				bPos2.assignAdd( new CqVector2D( ( j - m_DiscreteShiftX ), ( i - m_DiscreteShiftY ) ) );
//				bPos2.assignAdd(  ( j - m_DiscreteShiftX ), ( i - m_DiscreteShiftY ) );
				
				if(!empty)
					m_aieImage.get( which ).Clear();
//					m_aieImage[ which ].Clear();

				m_aieImage.get( which ).OffsetSamples( bPos2, m_aSamplePositions.get(which) );
//				m_aieImage[ which ].OffsetSamples( bPos2, m_aSamplePositions.get(which) );
//				m_aieImage.get( which ).OffsetSamples( bPos2, m_aSamplePositions[which] );

				which++;
			}
		}
	}
	
	/**
	 * 被写界深度を計算する。（Depth of field）
	 * 
	 * 
	 */
	public static	void	CalculateDofBounds()
	{
		m_NumDofBounds = m_PixelXSamples * m_PixelYSamples;
		//m_DofBounds.setSize(m_NumDofBounds);
		m_DofBounds = new CqBound[m_NumDofBounds];
		for(int i=0;i<m_NumDofBounds;i++)
		{
			m_DofBounds[i] = new CqBound();
		}
		
		float dx = 2.0f / m_PixelXSamples;
		float dy = 2.0f / m_PixelYSamples;

		// I know this is far from an optimal way of calculating this,
		// but it's only done once so I don't care.
		// Calculate the bounding boxes that the dof offset positions fall into.
		float minX = -1.0f;
		float minY = -1.0f;
		int which = 0;
		for(int j = 0; j < m_PixelYSamples; ++j)
		{
			for(int i = 0; i < m_PixelXSamples; ++i)
			{
				CqVector2D topLeft = new CqVector2D(minX, minY);
				CqVector2D topRight = new CqVector2D(minX + dx, minY);
				CqVector2D bottomLeft = new CqVector2D(minX, minY + dy);
				CqVector2D bottomRight = new CqVector2D(minX + dx, minY + dy);

				CqImagePixel.ProjectToCircle(topLeft);
				CqImagePixel.ProjectToCircle(topRight);
				CqImagePixel.ProjectToCircle(bottomLeft);
				CqImagePixel.ProjectToCircle(bottomRight);

				// if the bound straddles x=0 or y=0 then just using the corners
				// will give too small a bound, so we enlarge it by including the
				// non-projected coords.
				if((topLeft.y > 0.0 && bottomLeft.y < 0.0) ||
					(topLeft.y < 0.0 && bottomLeft.y > 0.0))
				{
					topLeft.x(minX);
					bottomLeft.x(minX);
					topRight.x(minX + dx);
					bottomRight.x(minX + dx);
				}
				if((topLeft.x > 0.0 && topRight.x < 0.0) ||
					(topLeft.x < 0.0 && topRight.x > 0.0))
				{
					topLeft.y(minY);
					bottomLeft.y(minY + dy);
					topRight.y(minY);
					bottomRight.y(minY + dy);
				}

//				m_DofBounds[which].vecMin().assignment( new CqVector3D(topLeft) );
//				m_DofBounds[which].vecMax().assignment( new CqVector3D(topLeft) );
				m_DofBounds[which].vecMin().assignment( topLeft );
				m_DofBounds[which].vecMax().assignment( topLeft );
				m_DofBounds[which].Encapsulate(topRight);
				m_DofBounds[which].Encapsulate(bottomLeft);
				m_DofBounds[which].Encapsulate(bottomRight);

//				m_DofBounds.get(which).vecMin() = topLeft;
//				m_DofBounds.get(which).vecMax() = topLeft;
//				m_DofBounds.get(which).Encapsulate(topRight);
//				m_DofBounds.get(which).Encapsulate(bottomLeft);
//				m_DofBounds.get(which).Encapsulate(bottomRight);

				which++;
				minX += dx;
			}
			minX = -1.0f;
			minY += dy;
		}
	}
//	----------------------------------------------------------------------
	/** Initialise the static filter values.
	 * スタティックフィルターの値を初期化します。
	 */
	static boolean FirstInitialiseFilterValues = true;
	public static	void	InitialiseFilterValues()
	{
//		if( !m_aFilterValues.isEmpty() )
//	        return;
		if( m_aFilterValues != null )
	        return;
		
	    // Allocate and fill in the filter values array for each pixel.
	    int numsubpixels = ( PixelXSamples() * PixelYSamples() );
	    int numperpixel = numsubpixels * numsubpixels;

	    int numvalues = (int)( ( ( Math.ceil(FilterXWidth()) + 1 ) * ( Math.ceil(FilterYWidth()) + 1 ) ) * ( numperpixel ) );

//	    m_aFilterValues.setSize( numvalues );
	    if(FirstInitialiseFilterValues)
	    {
		    m_aFilterValues = new p_float[ numvalues ];
		    for(int i = 0;i<numvalues;i++)
		    	m_aFilterValues[i] = new p_float();
		    FirstInitialiseFilterValues = false;
	    }

//	    RtFilterFunc pFilter;
//	    pFilter = QGetRenderContext().optCurrent().funcFilter();
	    
	    Method pFilter;
	    pFilter = QGetRenderContext().optCurrent().funcFilter();
	    
	    // Sanity check
	    if( null == pFilter )
			try {
				pFilter = RendermanInterface.class.getMethod("RiBoxFilter",float.class,float.class,float.class,float.class);
			} catch (Exception e) {
				HimawariLogger.outputException( e );
			} 

	    float xmax = m_DiscreteShiftX;
	    float ymax = m_DiscreteShiftY;
	    float xfwo2 = (float)Math.ceil(FilterXWidth()) * 0.5f;
	    float yfwo2 = (float)Math.ceil(FilterYWidth()) * 0.5f;
	    float xfw = (float)Math.ceil(FilterXWidth());

	    float subcellwidth = 1.0f / numsubpixels;
	    float subcellcentre = subcellwidth * 0.5f;

	    // Go over every pixel touched by the filter
	    int px, py;
	    for ( py = (int)( -ymax ); py <= (int)( ymax ); py++ )
	    {
	        for( px = (int)( -xmax ); px <= (int)( xmax ); px++ )
	        {
	            // Get the index of the pixel in the array.
	            int index = (int)( ( ( ( py + ymax ) * xfw ) + ( px + xmax ) ) * numperpixel );
	            float pfx = px - 0.5f;
	            float pfy = py - 0.5f;
	            // Go over every subpixel in the pixel.
	            int sx, sy;
	            for ( sy = 0; sy < PixelYSamples(); sy++ )
	            {
	                for ( sx = 0; sx < PixelXSamples(); sx++ )
	                {
	                    // Get the index of the subpixel in the array
	                    int sindex = index + ( ( ( sy * PixelXSamples() ) + sx ) * numsubpixels );
	                    float sfx = (float)( sx ) / PixelXSamples();
	                    float sfy = (float)( sy ) / PixelYSamples();
	                    // Go over each subcell in the subpixel
	                    int cx, cy;
	                    for ( cy = 0; cy < PixelXSamples(); cy++ )
	                    {
	                        for ( cx = 0; cx < PixelYSamples(); cx++ )
	                        {
	                            // Get the index of the subpixel in the array
	                            int cindex = sindex + ( ( cy * PixelYSamples() ) + cx );
	                            float fx = ( cx * subcellwidth ) + sfx + pfx + subcellcentre;
	                            float fy = ( cy * subcellwidth ) + sfy + pfy + subcellcentre;
	                            float w = 0.0f;
	                            if ( fx >= -xfwo2 && fy >= -yfwo2 && fx <= xfwo2 && fy <= yfwo2 )
									try {
										w = (Float)pFilter.invoke( null, (float)fx, (float)fy, (float)Math.ceil(FilterXWidth()),(float)Math.ceil(FilterYWidth()));
									} catch (Exception e) {
										HimawariLogger.outputException( e );
									} 
//	                            m_aFilterValues.[ cindex ] = w;
//	                            m_aFilterValues.get( cindex ).value = w;
	                            m_aFilterValues[ cindex ].value = w;
	                        }
	                    }
	                }
	            }
	        }
	    }
	}
	

	/**
	 * 指定されたXとYの位置の画素の位置を返す関数
	 * m_aieImage.get( i );のような感じで使う。
	 * @param iXPos Xの位置
	 * @param iYPos Yの位置
	 * @return XとYの位置からの場所を求める
	 */
//	public static void	ImageElement( int iXPos, int iYPos, CqImagePixel pie )
	public static int	ImageElement( int iXPos, int iYPos )
	{
		iXPos -= m_XOrigin;
		iYPos -= m_YOrigin;

		// Check within renderable range
		//assert( iXPos < -m_XMax && iXPos < m_XSize + m_XMax &&
		//		iYPos < -m_YMax && iYPos < m_YSize + m_YMax );

		int i = ( ( iYPos + m_DiscreteShiftY ) * ( m_RealWidth ) ) + ( iXPos + m_DiscreteShiftX );
//		pie = m_aieImage.get( i );
		return i;
	}

//	----------------------------------------------------------------------
	/**
	 * 透明な画素の時にm_aieImageの中に格納されているデータを結合して。色を決定する作業をする。
	 * 実際にはCqImagePixelのCombineを呼び出しているだけ
	 */
	public    static	void	CombineElements()
	{
		for ( CqImagePixel CIP : m_aieImage )
			CIP.Combine();       
	}
	
//	----------------------------------------------------------------------
	/**
	 * フィルターの種類とサンプリングの大きさによってフィルターをかける。
	 * イメージシェーダなどが呼ばれていればそれを使用する。
	 * @param empty　このバケットが空であるかどうかを外から取得する。そのことで無駄な計算を省いている。
	 */
	static boolean FirstFilterBucket = true;
	public void FilterBucket(boolean empty)
	{
	    int pie;

	    int datasize = QGetRenderContext().GetOutputDataTotalSize();
	    //buti 高速化
	    //m_aDatas.resize( datasize * RealWidth() * RealHeight() );
	    if(FirstFilterBucket)
	    {
		    m_aDatas = new p_float[datasize * RealWidth() * RealHeight()];
		    for(int i=0;i<m_aDatas.length;i++)
		    	m_aDatas[i] = new p_float();
		    	
		    m_aCoverages = new p_float[ RealWidth() * RealHeight() ];
		    for(int i=0;i<m_aCoverages.length;i++)
		    	m_aCoverages[i] = new p_float();
		    FirstFilterBucket = false;
	    }
//	    for(int i=0;i<m_aCoverages.length;i++)
//	    	m_aCoverages[i] = new p_float();
	    
	    int xmax = m_DiscreteShiftX;
	    int ymax = m_DiscreteShiftY;
	    float xfwo2 = (float)Math.ceil(FilterXWidth()) * 0.5f;
	    float yfwo2 = (float)Math.ceil(FilterYWidth()) * 0.5f;
	    int numsubpixels = ( PixelXSamples() * PixelYSamples() );

	    int numperpixel = numsubpixels * numsubpixels;
	    int	xlen = RealWidth();

	    int SampleCount = 0;
	    CqColor imager;//C++ではnewされてます new shaderテスト時にバグとして見つかるかも2005/12/13 渡辺

	    int x, y;
	    int i = 0;

	    boolean fImager = false;
	    String[] systemOptions ;
	    if( ( systemOptions = QGetRenderContext().optCurrent().GetStringOption( "System", "Imager" ) ) != null )
	    	if( systemOptions[0].compareTo("null") != 0 )
			fImager = true;

	    int endy = YOrigin() + Height();
	    int endx = XOrigin() + Width();

		boolean useSeperable = true;


		if(!empty)
		{
			// non-seperable is faster for very small filter widths.
			// 分割されていない物は小さなフィルタよりも早い
			//フィルターが1x1の時false　それ以外のときはtrue
			if(FilterXWidth() <= 1.0 || FilterYWidth() <= 1.0)
				useSeperable = false;

			if(useSeperable)
			{
				// seperable filter. filtering by fx,fy is equivalent to filtering
				// by fx,1 followed by 1,fy.
				

				int size = Width() * RealHeight() * PixelYSamples();
				Valarray intermediateSamples = new Valarray( 0.0f, size * datasize);
				ValarrayInt sampleCounts = new ValarrayInt(0, size);
				
				//変数宣言スペース
				{
					float xcent,ycent;
					float g;
					for ( y = YOrigin() - ymax; y < endy + ymax ; y++ )
					{
						ycent = y + 0.5f;
						int pixelRow = (y-(YOrigin()-ymax)) * PixelYSamples();
						for ( x = XOrigin(); x < endx ; x++ )
						{
							xcent = x + 0.5f;
	
							// Get the element at the left side of the filter area.
							// フィルタエリアの左側における要素を手に入れてください。
							
							 pie = ImageElement( x - xmax, y );
	
							int pixelIndex = pixelRow*Width() + x-XOrigin();
	
							// filter just in x first
							// フィルターをｘからかける
							//buti 高速化
							//for ( int sy = 0; sy < PixelYSamples(); sy++ )
							for ( int sy = 0; sy < m_PixelYSamples; sy++ )
							{
								float gTot = 0.0f;
								SampleCount = 0;
								Valarray samples = new Valarray( 0.0f, datasize);
	
								int pie2 = pie;
								for ( int fx = -xmax; fx <= xmax; fx++ )
								{
									int index = (int)(( ( ymax * Math.ceil(FilterXWidth()) ) + ( fx + xmax ) ) * numperpixel);
									// Now go over each subsample within the pixel
									// 今は、画素の中の各「サブ-サンプル」を調べてください。
									int sampleIndex = sy * PixelXSamples();
									int sindex = index + ( sy * PixelXSamples() * numsubpixels );
	
									//for ( int sx = 0; sx < PixelXSamples(); sx++ )
									for ( int sx = 0; sx < m_PixelXSamples; sx++ )
									{
										SqSampleData sampleData = aieImage( pie2 ).SampleData( sampleIndex );
										//buti 高速化
//										CqVector2D vecS = new CqVector2D( sampleData.m_Position );
//										vecS.assignSub( new  CqVector2D( xcent, ycent ) );
										CqVector2D vecS = new CqVector2D( sampleData.m_Position.x - xcent,sampleData.m_Position.y -ycent);
										if ( vecS.x >= -xfwo2 && vecS.y >= -yfwo2 && vecS.x <= xfwo2 && vecS.y <= yfwo2 )
										{
											int cindex = sindex + sampleData.m_SubCellIndex;
//											g = m_aFilterValues.get( cindex ).value;
											g = m_aFilterValues[ cindex ].value;
											gTot += g;
											if ( (aieImage( pie2 ).OpaqueValues( sampleIndex ).m_flags & SqImageSample.Flag_Valid )!= 0)
											{
												SqImageSample pSample = aieImage( pie2 ).OpaqueValues( sampleIndex );
												for ( int k = 0; k < datasize; ++k )
													//samples[k] += pSample.m_Data[k] * g;
													samples.setValueAt( k , samples.valueAt(k) + pSample.m_Data.valueAt(k) * g);
												//sampleCounts[pixelIndex]++;
												sampleCounts.setValueAt(pixelIndex,sampleCounts.valueAt(pixelIndex)+1 );
												
											}
										}
										sampleIndex++;
										sindex += numsubpixels;
									}
									pie2++;
								}
	
								// store the intermediate result
								for ( int k = 0; k < datasize; k ++)
									//intermediateSamples[pixelIndex*datasize + k] = samples[k] / gTot;
									intermediateSamples.setValueAt(pixelIndex*datasize + k ,  samples.valueAt(k) / gTot);
									
								pixelIndex += Width();
							}
						}
					}
				}
				// now filter in y.
				// yのフィルタをする
				for ( y = YOrigin(); y < endy ; y++ )
				{
					float ycent = y + 0.5f;
					for ( x = XOrigin(); x < endx ; x++ )
					{
						float xcent = x + 0.5f;
						float gTot = 0.0f;
						SampleCount = 0;
						Valarray samples = new Valarray( 0.0f, datasize);

						// Get the element at the top of the filter area.
						pie = ImageElement( x, y - ymax );
						for ( int fy = -ymax; fy <= ymax; fy++ )
						{
							int pie2 = pie;

							int index = (int)(( ( ( fy + ymax ) * Math.ceil(FilterXWidth()) ) + xmax ) * numperpixel);
							// Now go over each y subsample within the pixel
							int sx = PixelXSamples() / 2; // use the samples in the centre of the pixel.
							int sy = 0;
							int sampleIndex = sx;
							int pixelRow = (y + fy - (YOrigin()-ymax)) * PixelYSamples();
							int pixelIndex = pixelRow*Width() + x-XOrigin();

							//for ( sy = 0; sy < PixelYSamples(); sy++ )
							for ( sy = 0; sy < m_PixelYSamples; sy++ )
							{
								int sindex = index + ( ( ( sy * PixelXSamples() ) + sx ) * numsubpixels );
								SqSampleData sampleData = aieImage( pie2 ).SampleData( sampleIndex );
//								CqVector2D vecS = new CqVector2D( sampleData.m_Position );
//								vecS.assignSub( new CqVector2D( xcent, ycent ) );
								CqVector2D vecS = new CqVector2D( sampleData.m_Position.x - xcent,sampleData.m_Position.y -ycent );
								
								if ( vecS.x >= -xfwo2 && vecS.y >= -yfwo2 && vecS.x <= xfwo2 && vecS.y <= yfwo2 )
								{
									int cindex = sindex + sampleData.m_SubCellIndex;
//									float g = m_aFilterValues.get( cindex ).value;
									float g = m_aFilterValues[ cindex ].value;
									gTot += g;
									if(sampleCounts.valueAt( pixelIndex ) > 0)
									{
										SampleCount += sampleCounts.valueAt( pixelIndex );
										for ( int k = 0; k < datasize; k++)
											//samples[k] += intermediateSamples[pixelIndex * datasize + k] * g;
											samples.setValueAt( k, samples.valueAt(k) + intermediateSamples.valueAt(pixelIndex * datasize + k) * g );
									}
								}
								sampleIndex += PixelXSamples();
								pixelIndex += Width();
							}

							pie += xlen;
						}

						// Set depth to infinity if no samples.
						// サンプルがなければ深度を無限大に設定する。
						if ( SampleCount == 0 )
						{
							//memset(&m_aDatas[i*datasize], 0, datasize * sizeof(float));
							//buti 高速化
//							for(int k = 0 ;k < datasize ;k++)
//								m_aDatas.get( i*datasize + k ).value = 0.0f ;
//							m_aDatas.get( i*datasize + 6 ).value = FLT_MAX;
							for(int k = 0 ;k < datasize ;k++)
								m_aDatas[ i*datasize + k ].value = 0.0f ;
							m_aDatas[ i*datasize + 6 ].value = FLT_MAX;
								
							m_aCoverages[i].value = 0.0f;
						}
						else
						{
							float oneOverGTot = (float) (1.0 / gTot);
//							buti 高速化
//							for ( int k = 0; k < datasize; k ++)
//								m_aDatas.get( i*datasize + k ).value = samples.valueAt(k) * oneOverGTot;
							for ( int k = 0; k < datasize; k ++)
								m_aDatas[ i*datasize + k ].value = samples.valueAt(k) * oneOverGTot;

							
							if ( SampleCount >= numsubpixels)
								m_aCoverages[ i ].value = 1.0f;
							else
								m_aCoverages[ i ].value = ( float ) SampleCount / ( float ) (numsubpixels );
						}

						i++;
					}
				}
				
			}
			else
			{
				// non-seperable filter
				// 非分割フィルタ
				for ( y = YOrigin(); y < endy ; y++ )
				{
					float ycent = y + 0.5f;
					for ( x = XOrigin(); x < endx ; x++ )
					{
						float xcent = x + 0.5f;
						float gTot = 0.0f;
						SampleCount = 0;
						Valarray samples = new Valarray( 0.0f, datasize);

						int fx, fy;
						// Get the element at the upper left corner of the filter area.
						// フィルタ部の左上隅で要素を手に入れてください。
						pie = ImageElement( x - xmax, y - ymax );
						for ( fy = -ymax; fy <= ymax; fy++ )
						{
							int pie2 = pie;
							for ( fx = -xmax; fx <= xmax; fx++ )
							{
								int index = (int) (( ( ( fy + ymax ) * Math.ceil(FilterXWidth()) ) + ( fx + xmax ) ) * numperpixel);
								// Now go over each subsample within the pixel
								// 今度は、画素の中の各「サブ-サンプル」を調べてください。
								int sx, sy;
								int sampleIndex = 0;
								//for ( sy = 0; sy < PixelYSamples(); sy++ )
								for ( sy = 0; sy < m_PixelYSamples; sy++ )
								{
									//for ( sx = 0; sx < PixelXSamples(); sx++ )
									for ( sx = 0; sx < m_PixelXSamples; sx++ )
									{
										int sindex = index + ( ( ( sy * PixelXSamples() ) + sx ) * numsubpixels );
										SqSampleData sampleData = aieImage( pie2 ).SampleData( sampleIndex );
										CqVector2D vecS = new CqVector2D( sampleData.m_Position );
										vecS.assignSub( new CqVector2D( xcent, ycent ) );
										if ( vecS.x >= -xfwo2 && vecS.y >= -yfwo2 && vecS.x <= xfwo2 && vecS.y <= yfwo2 )
										{
											int cindex = sindex + sampleData.m_SubCellIndex;
//											float g = m_aFilterValues.get( cindex ).value;
											float g = m_aFilterValues[ cindex ].value;
											gTot += g;
											if ( (aieImage( pie2 ).OpaqueValues( sampleIndex ).m_flags & SqImageSample.Flag_Valid )!= 0 )
											{
												SqImageSample pSample = aieImage( pie2 ).OpaqueValues( sampleIndex );
												for ( int k = 0; k < datasize; ++k )
													samples.setValueAt(k ,samples.valueAt(k) + pSample.m_Data.valueAt(k) * g );
												SampleCount++;
											}
										}
										sampleIndex++;
									}
								}
								pie2++;
							}
							pie += xlen;
						}


						// Set depth to infinity if no samples.
						// もし、サンプルが空であれば無限に設定する。
						if ( SampleCount == 0 )
						{
							//memset(&m_aDatas[i*datasize], 0, datasize * sizeof(float));
							//buti 高速化
//							for(int k = 0 ;k < datasize ;k++)
//								m_aDatas.get( i*datasize +k ).value = 0.0f ;
//							m_aDatas.get( i*datasize+6 ).value = FLT_MAX;
							for(int k = 0 ;k < datasize ;k++)
								m_aDatas[ i*datasize +k ].value = 0.0f ;
							m_aDatas[ i*datasize+6 ].value = FLT_MAX;
							
							m_aCoverages[ i ].value = 0.0f;
						}
						else
						{
							float oneOverGTot = (float) (1.0 / gTot);
//							buti 高速化
//							for ( int k = 0; k < datasize; k ++)
//								m_aDatas.get( i*datasize + k ).value = samples.valueAt(k) * oneOverGTot;
							for ( int k = 0; k < datasize; k ++)
								m_aDatas[ i*datasize + k ].value = samples.valueAt(k) * oneOverGTot;

							if ( SampleCount >= numsubpixels)
								m_aCoverages[ i ].value = 1.0f;
							else
								m_aCoverages[ i ].value = ( float ) SampleCount / ( float ) (numsubpixels );
						}

						i++;
					}
				}
			}
		}
		else
		{
			// empty bucket.
			// bucketが空の時
			int size = Width()*Height();
			//memset(&m_aDatas[0], 0, size * datasize * sizeof(float));
			//memset(&m_aCoverages[0], 0, size * sizeof(float));
			
			for(int k = i*datasize;k < size * datasize ;k++)
				//buti 高速化
				//m_aDatas.get( i*datasize + k).value = 0.0f ;
				m_aDatas[ i*datasize + k].value = 0.0f ;
			
			for(int k = i*datasize;k < size ;k++)
//				m_aCoverages.get( i*datasize + k).value = 0.0f ;
				m_aCoverages[ i*datasize + k].value = 0.0f ;

			for(i = 0; i<size; ++i)
			{
				// Set the depth to infinity.
				// 深度を無限に設定する
//				buti 高速化
//				m_aDatas.get( i*datasize+6 ).value = FLT_MAX;
				m_aDatas[ i*datasize+6 ].value = FLT_MAX;
			}
		}

	    i = 0;
	    pie = ImageElement( XOrigin(), YOrigin() );
	    endy = Height();
	    endx = Width();

		// Set the coverage and alpha values for the pixel.
		// 画素に適用範囲とα値を設定してください。
	    for ( y = 0; y < endy; y++ )
	    {
	        int pie2 = pie;
	        for ( x = 0; x < endx; x++ )
	        {
	            SqImageSample spl = aieImage( pie2 ).GetPixelSample();
				for (int k=0; k < datasize; k++)
					//biti　高速化
	                //spl.m_Data.setValueAt( k, m_aDatas.get( i * datasize + k ).value );
					spl.m_Data.setValueAt( k, m_aDatas[ i * datasize + k ].value );
//	            spl.SetCoverage( m_aCoverages.get( i++ ).value );
	            spl.SetCoverage( m_aCoverages[ i++ ].value );
		
				// Calculate the alpha as the combination of the opacity and the coverage.
				// α値を透明度と、適用範囲の組み合わせとして計算してください。
				float a = ( spl.Os().fRed() + spl.Os().fGreen() + spl.Os().fBlue() ) / 3.0f;
				aieImage( pie2 ).SetAlpha(a * spl.Coverage());

				//--Himawari Add
				aieImage(pie2).setfColor(null);
				//--
	            
				pie2++;
	        }
	        pie += xlen;
	    }

	    endy = YOrigin() + Height();
	    endx = XOrigin() + Width();

	    if ( null != QGetRenderContext().optCurrent().pshadImager() && null != QGetRenderContext().optCurrent().pshadImager().pShader() )
	    {
	        QGetRenderContext().Stats().MakeFilterBucket().Stop();
	        // Init & Execute the imager shader
			// 実行されたイメージシェーダを初期化してください。

	        QGetRenderContext().optCurrent().InitialiseColorImager( this );

	        if ( fImager )
	        {
	            i = 0;
	            pie = ImageElement( XOrigin(), YOrigin() );
	            for ( y = YOrigin(); y < endy ; y++ )
	            {
	                int pie2 = pie;
	                for ( x = XOrigin(); x < endx ; x++ )
	                {
	                    imager = QGetRenderContext().optCurrent().GetColorImager( x , y );
	                    // Normal case will be to poke the alpha from the image shader and
	                    // multiply imager color with it... but after investigation alpha is always
	                    // == 1 after a call to imager shader in 3delight and BMRT.
	                    // Therefore I did not ask for alpha value and set directly the pCols[i]
	                    // with imager value. see imagers.cpp
	                    aieImage( pie2 ).SetColor( imager );
	                    imager = QGetRenderContext().optCurrent().GetOpacityImager( x , y );
	                    aieImage( pie2 ).SetOpacity( imager );
	                    pie2++;
	                    i++;
	                }
	                pie += xlen;
	            }
	        }
	        QGetRenderContext().Stats().MakeFilterBucket().Start();
	    }

	}

//	----------------------------------------------------------------------
	/** 
	 * 指定されたゲイン（明るさ）とガンマ設定に従って、このバケツの中のサンプルを露出を変えてください。
	 * 暗い画像を明るめに表示させるための機能
	 */

	public    void	ExposeBucket()
	{
	    if ( QGetRenderContext().optCurrent().GetFloatOptionIndex( "System", "Exposure" , 0 ).value == 1.0 &&
	            QGetRenderContext().optCurrent().GetFloatOptionIndex( "System", "Exposure" , 1 ).value == 1.0 )
	        return ;
	    else
	    {
//	        CqImagePixel pie;
	    	int pie;
	        pie = ImageElement( XOrigin(), YOrigin() );
	        int x, y;
	        float exposegain = QGetRenderContext().optCurrent().GetFloatOptionIndex( "System", "Exposure" , 0 ).value;
	        float exposegamma = QGetRenderContext().optCurrent().GetFloatOptionIndex( "System", "Exposure" , 1 ).value;
	        float oneovergamma = 1.0f / exposegamma;
	        float endx, endy;
	        int   nextx;
	        endy = Height();
	        endx = Width();
	        nextx = RealWidth();

	        for ( y = 0; y < endy; y++ )
	        {
//	            CqImagePixel pie2 = pie;
	        	int pie2 = pie;
	            for ( x = 0; x < endx; x++ )
	            {
	                // color=(color*gain)^1/gamma
	                if ( exposegain != 1.0 )
	                    m_aieImage.get(pie2).SetColor( m_aieImage.get(pie2).Color().mul( exposegain ) );
//	                	m_aieImage[pie2].SetColor( m_aieImage[pie2].Color().mul( exposegain ) );

	                if ( exposegamma != 1.0 )
	                {
	                    CqColor col = m_aieImage.get(pie2).Color();
//	                    CqColor col = m_aieImage[pie2].Color();
	                    col.SetfRed ( (float)Math.pow( col.fRed (), oneovergamma ) );
	                    col.SetfGreen( (float)Math.pow( col.fGreen(), oneovergamma ) );
	                    col.SetfBlue ( (float)Math.pow( col.fBlue (), oneovergamma ) );
	                    m_aieImage.get(pie2).SetColor( col );
//	                    m_aieImage[pie2].SetColor( col );
	                }
	                pie2++;
	            }
	            pie += nextx;
	        }
	    }
	}
	
//	----------------------------------------------------------------------
	/** Quantize the samples in this bucket according to type.
	 * バケットの中のサンプルされているものを量子化するメソッド。
	 */
	public static CqRandom random = new CqRandom( 61 );
	public    void	QuantizeBucket()
	{
	    // Initiliaze the random with a value based on the X,Y coordinate
		// Xに基づく値、Y座標がある無作為の初期化
//	    static CqRandom random( 61 );
	    float endx, endy;
	    int   nextx;
	    endy = Height();
	    endx = Width();
	    nextx = RealWidth();


	    if ( ( QGetRenderContext().optCurrent().GetIntegerOptionIndex( "System", "DisplayMode" , 0 ).value & ModeRGB )!= 0)
	    {
	        float[] pQuant = QGetRenderContext().optCurrent().GetFloatOption( "Quantize", "Color" );
	        int one = (int)( pQuant [ 0 ] );
	        int min = (int)( pQuant [ 1 ] );
	        int max = (int)( pQuant [ 2 ] );
	        double ditheramplitude = pQuant [ 3 ];

	        // If settings are 0,0,0,0 then leave as floating point and we will save an FP tiff.
	        if ( one == 0 && min == 0 && max == 0 )
	            return ;

//	        CqImagePixel pie;
	        int pie;
	        pie = ImageElement( XOrigin(), YOrigin() );
	        int x, y;

	        for ( y = 0; y < endy; y++ )
	        {
//	            CqImagePixel pie2 = pie;
	        	int pie2 = pie;
	            for ( x = 0; x < endx; x++ )
	            {
	                double r, g, b, a;
	                double _or, _og, _ob;
	                double s = random.RandomFloat();
	                CqColor col = m_aieImage.get(pie2).Color();
	                CqColor opa = m_aieImage.get(pie2).Opacity();
					float alpha = m_aieImage.get(pie2).Alpha();
	                
//					CqColor col = m_aieImage[pie2].Color();
//		            CqColor opa = m_aieImage[pie2].Opacity();
//					float alpha = m_aieImage[pie2].Alpha();
						
					//---Himawari add 量子化前のカラー情報を設定する
	                m_aieImage.get(pie2).setfColor( new CqColor(col) );
//	                m_aieImage[pie2].setfColor( new CqColor(col) );
	                //---Himawari end
	                
					//四捨五入をしている。javaでは違いそうなので、下の用に書く
//	                if ( modf( one * col.fRed () + ditheramplitude * s, r ) > 0.5 ) r += 1;
//	                if ( modf( one * col.fGreen() + ditheramplitude * s, g ) > 0.5 ) g += 1;
//	                if ( modf( one * col.fBlue () + ditheramplitude * s, b ) > 0.5 ) b += 1;
//	                if ( modf( one * opa.fRed () + ditheramplitude * s, _or ) > 0.5 ) _or += 1;
//	                if ( modf( one * opa.fGreen() + ditheramplitude * s, _og ) > 0.5 ) _og += 1;
//	                if ( modf( one * opa.fBlue () + ditheramplitude * s, _ob ) > 0.5 ) _ob += 1;
//	                if ( modf( one * alpha + ditheramplitude * s, a ) > 0.5 ) a += 1;
	                r = Math.round( one * col.fRed () + ditheramplitude * s);
	                g = Math.round( one * col.fGreen() + ditheramplitude * s);
	                b = Math.round( one * col.fBlue() + ditheramplitude * s);
	                _or = Math.round( one * opa.fRed () + ditheramplitude * s );
	                _og = Math.round( one * opa.fGreen() + ditheramplitude * s);
	                _ob = Math.round(one * opa.fBlue () + ditheramplitude * s);
	                a = Math.round( one * alpha + ditheramplitude * s );
	                
					r = CLAMP( (float)r, (float)min, (float)max );
	                g = CLAMP( (float)g, (float)min, (float)max );
	                b = CLAMP( (float)b, (float)min, (float)max );
	                _or = CLAMP( (float)_or, (float)min, (float)max );
	                _og = CLAMP( (float)_og, (float)min, (float)max );
	                _ob = CLAMP( (float)_ob, (float)min, (float)max );
	                a = CLAMP( (float)a, (float)min, (float)max );

	                col.SetfRed ( (float)r );
	                col.SetfGreen( (float)g );
	                col.SetfBlue ( (float)b );
	                opa.SetfRed ( (float)_or );
	                opa.SetfGreen( (float)_og );
	                opa.SetfBlue ( (float)_ob );

	                m_aieImage.get(pie2).SetColor( col );
	                m_aieImage.get(pie2).SetOpacity( opa );
	                m_aieImage.get(pie2).SetAlpha( (float)a );
//	                m_aieImage[pie2].SetColor( col );
//	                m_aieImage[pie2].SetOpacity( opa );
//	                m_aieImage[pie2].SetAlpha( (float)a );
	                pie2++;
	            }
	            pie += nextx;
	        }
	    }

	    if ( ( QGetRenderContext().optCurrent().GetIntegerOptionIndex( "System", "DisplayMode" , 0 ).value & ModeZ ) != 0 )
	    {
	        float[] pQuant = QGetRenderContext().optCurrent().GetFloatOption( "Quantize", "Depth" );
	        int one = (int)( pQuant [ 0 ] );
	        int min = (int)( pQuant [ 1 ] );
	        int max = (int)( pQuant [ 2 ] );
	        double ditheramplitude = pQuant [ 3 ];
	        if( ditheramplitude == 0.0f && one == 0 && min == 0 && max == 0 )
	            return;

//	        CqImagePixel pie;
	        int pie; 
	        pie = ImageElement( XOrigin(), YOrigin() );
	        int x, y;
	        for ( y = 0; y < endy; y++ )
	        {
//	            CqImagePixel pie2 = pie;
	            int pie2 = pie;
	            for ( x = 0; x < endx; x++ )
	            {
	                double d;
//	                if ( modf( one * m_aieImage.get(pie2).Depth() + ditheramplitude * random.RandomFloat(), &d ) > 0.5 ) d += 1;
	                d = Math.round(one * m_aieImage.get(pie2).Depth() + ditheramplitude * random.RandomFloat());
//	                d = Math.round(one * m_aieImage[pie2].Depth() + ditheramplitude * random.RandomFloat());
	                d = CLAMP( (float)d, (float)min, (float)max );
	                m_aieImage.get(pie2).SetDepth( (float)d );
//	                m_aieImage[pie2].SetDepth( (float)d );
	                pie2++;
	            }
	            pie += nextx;
	        }
	    }

	    // Now go through the other AOV's and quantize those if necessary.
//	    std::map<std::string, CqRenderer::SqOutputDataEntry>& DataMap = QGetRenderContext()->GetMapOfOutputDataEntries();
//	    std::map<std::string, CqRenderer::SqOutputDataEntry>::iterator entry;
	    
	    HashMap<String, CqRenderer.SqOutputDataEntry> DataMap = QGetRenderContext().GetMapOfOutputDataEntries();
	    
	    	    
//	    for( entry = DataMap.begin(); entry != DataMap.end(); entry++ )
	    for(Entry<String, CqRenderer.SqOutputDataEntry> entry : DataMap.entrySet() )
	    {
	        float[] pQuant = QGetRenderContext().optCurrent().GetFloatOption( "Quantize", entry.getKey() );
	        if( null != pQuant )
	        {
	            int startindex = entry.getValue().m_Offset;
	            int endindex = startindex + entry.getValue().m_NumSamples;
	            int one = (int)( pQuant [ 0 ] );
	            int min = (int)( pQuant [ 1 ] );
	            int max = (int)( pQuant [ 2 ] );
	            double ditheramplitude = pQuant [ 3 ];

//	            CqImagePixel pie;
	            int pie;
	            pie = ImageElement( XOrigin(), YOrigin() );
	            int x, y;
	            for ( y = 0; y < endy; y++ )
	            {
//	                CqImagePixel pie2 = pie;
	            	int pie2 = pie;
	                for ( x = 0; x < endx; x++ )
	                {
	                    int sampleindex;
	                    for( sampleindex = startindex; sampleindex < endindex; sampleindex++ )
	                    {
	                        double d;
//	                        if ( modf( one * m_aieImage.get(pie2).GetPixelSample().m_Data.valueAt( sampleindex ) + ditheramplitude * random.RandomFloat(), d ) > 0.5 ) d += 1.0f;
	                        d = Math.round(one * m_aieImage.get(pie2).GetPixelSample().m_Data.valueAt( sampleindex ) + ditheramplitude * random.RandomFloat());
//	                        d = Math.round(one * m_aieImage[pie2].GetPixelSample().m_Data.valueAt( sampleindex ) + ditheramplitude * random.RandomFloat());
	                        d = CLAMP( (float)d,(float) min,(float) max );
	                        m_aieImage.get(pie2).GetPixelSample().m_Data.setValueAt( sampleindex , (float)d);
//	                        m_aieImage[pie2].GetPixelSample().m_Data.setValueAt( sampleindex , (float)d);
	                    }
	                    pie2++;
	                }
	                pie += nextx;
	            }
	        }
	    }
	}

//	----------------------------------------------------------------------
	/** 
	 * バケットの中身をクリアする。
	 */
	public    static	void	ShutdownBucket()
	{
		//buti 高速化
	    m_aieImage.clear();
//	    m_aFilterValues.clear();
//		m_aCoverages.clear();
//		m_aDatas.clear();
		
//	    for(int i=0;i<m_aieImage.length;i++)
//	    	m_aieImage[i]=null;
//	    m_aieImage=null;

	    for(int i=0;i<m_aFilterValues.length;i++)
	    	m_aFilterValues[i]=null;
	    m_aFilterValues = null;
	    FirstInitialiseFilterValues = true;
	    
	    for(int i=0;i<m_aCoverages.length;i++)
	    	m_aCoverages[i]=null;
	    m_aCoverages = null;
	
		for(int i=0;i<m_aDatas.length;i++)
			m_aDatas[i]=null;
		m_aDatas = null;
		FirstFilterBucket = true;
		
//		javaだと必要ない
//		for(STLVector<CqVector2D> i : m_aSamplePositions )
//		{
//			i.clear();
//			i = null;
//		}
		m_aSamplePositions.clear();
//		for(int i=0;i<m_aSamplePositions.length;i++)
//			m_aSamplePositions[i]=null;
//		m_aSamplePositions = null;
	}
	

	    /** 
	     * 伸ばされたGprimsのスタックへGprimを追加する。
		 * @parame pGprim 追加するpGPrim
	     */
	public void	AddGPrim( final CqBasicSurface pGPrim )
	{
		m_aGPrims.add(pGPrim);
	}

	    /** 
	     * MPGを延長されたMPGｓのリストに追加する。
	     */
	public void	AddMPG( CqMicroPolygon pmpgNew )
	    {
//	#ifdef _DEBUG
//	        std::vector<CqMicroPolygon*>::iterator end = m_ampgWaiting.end();
//	        for (std::vector<CqMicroPolygon*>::iterator i = m_ampgWaiting.begin(); i != end; i++)
//	            if ((*i) == pmpgNew)
//	                assert( TqFalse );
//	#endif
	        m_ampgWaiting.add( pmpgNew );
	    }
	    /** 
	     * Micropoly gridを延長されたgridsのリストに追加する。
	     */
	public void	AddGrid( CqMicroPolyGridBase pgridNew )
	    {
//	#ifdef _DEBUG
//	        std::vector<CqMicroPolyGridBase*>::iterator end = m_agridWaiting.end();
//	        for (std::vector<CqMicroPolyGridBase*>::iterator i = m_agridWaiting.begin(); i != end; i++)
//	            if ((*i) == pgridNew)
//	                assert( TqFalse );
//	#endif
			
	        m_agridWaiting.add( pgridNew );
	    }
	
	    /** 
	     * GprimsのスタックのTopのGprimのポインタを取得する
	     */
	public  CqBasicSurface pTopSurface()
    {
		if (!m_aGPrims.isEmpty())
		{
		    return m_aGPrims.peek();
		}
		else
		{
		    return null;// boost::shared_ptr<CqBasicSurface>();
		}
    }
    /** 
     * GprimsのスタックのGprimをPOPする
     */
	public    void popSurface()
    {
		m_aGPrims.poll();
    }
    /**
     * Gprimsの数を取得する。
     */
	public    int cGPrims()
    {
		return ( m_aGPrims.size() );
    }
    /** 
     * MPGｓのベクタの参照を取得する。
     */
	public STLVector<CqMicroPolygon> aMPGs()
    {
        return ( m_ampgWaiting );
    }
    /**
     * girdsのヴェクターの参照を取得する。 
     */
    public STLVector<CqMicroPolyGridBase> aGrids()
    {
        return ( m_agridWaiting );
    }
    /** 
     * バケツがまだ処理されているか同かを示すフラグを取得する。
     */
    public boolean IsProcessed()
    {
        return( m_bProcessed );
    }

    /** 
     * このバケットが処理中であることをマークする。
     */
    public void SetProcessed()
    {
        SetProcessed(true);
    }
    public void SetProcessed( boolean bProc )
    {
        m_bProcessed = bProc;
    }
    /**
     * イメージバッファのポインタをセットする。 
     */
    public static void SetImageBuffer( CqImageBuffer pBuffer )
    {
        m_ImageBuffer = pBuffer;
    }


	
	private		static	int	m_XOrigin;		///< Origin in discrete coordinates of this bucket.
	private    	static	int	m_YOrigin;		///< Origin in discrete coordinates of this bucket.
	private    	static	int	m_XSize;		///< Size of the rendered area of this bucket in discrete coordinates.
	private    	static	int	m_YSize;		///< Size of the rendered area of this bucket in discrete coordinates.
	private		static	int	m_RealWidth;	///< Actual size of the data for this bucket including filter overlap.
	private		static	int	m_RealHeight;	///< Actual size of the data for this bucket including filter overlap.
	private		static	int	m_DiscreteShiftX;	///< 
	private		static	int	m_DiscreteShiftY;
	private		static	int	m_PixelXSamples;
	private		static	int	m_PixelYSamples;
	private		static	float	m_FilterXWidth;
	private		static	float	m_FilterYWidth;
	private		static	int	m_NumTimeRanges;
	private		static	int	m_NumDofBounds;
	//private		static	STLVector<CqBound>		m_DofBounds = new STLVector<CqBound>( CqBound.class );
	private		static	CqBound[] m_DofBounds;
	
	private    	static	STLVector<CqImagePixel>	m_aieImage = new STLVector<CqImagePixel>( CqImagePixel.class );
	//private    	static CqImagePixel[] m_aieImage;
	
	private    	static	STLVector<STLVector<CqVector2D>>	m_aSamplePositions = new STLVector<STLVector<CqVector2D>>( 2, CqVector2D.class );///< Vector of vectors of jittered sample positions precalculated.
	//private    	static	CqVector2D[][]	m_aSamplePositions ;

	//buti 高速化
	//private    	static	STLVector<p_float>	m_aFilterValues = new STLVector<p_float>( p_float.class );				///< Vector of filter weights precalculated.
	//private    	static	STLVector<p_float>	m_aDatas = new STLVector<p_float>( p_float.class );
	//private    	static	STLVector<p_float>	m_aCoverages = new STLVector<p_float>( p_float.class );
	private    	static	p_float[]	m_aFilterValues;
	private    	static	p_float[]	m_aDatas;
	private    	static	p_float[]	m_aCoverages;
	
	private		static	CqImageBuffer	m_ImageBuffer;	///< Pointer to the image buffer this bucket belongs to.

		// this is a compare functor for sorting surfaces in order of depth.
	private	class closest_surface implements Comparator<CqBasicSurface>
	{
		
		public int compare(CqBasicSurface s1, CqBasicSurface s2) 
		{
			
			if ( s1.fCachedBound() && s2.fCachedBound() )
	        {
				  if( s1.GetCachedRasterBound().vecMin().z > s2.GetCachedRasterBound().vecMin().z )
					  return 1;		//priority_queueの仕様がC++とは逆で最小の値がトップに来るので逆に返している。
				  else if( s1.GetCachedRasterBound().vecMin().z < s2.GetCachedRasterBound().vecMin().z )
					  return -1;
				  else
					  return 0;
	        }
			else
			{
				// don't have bounds for the surface(s). I suspect we should assert here.
				return -1;
			}	
			
		}
		
	};

	private    STLVector<CqMicroPolygon> m_ampgWaiting = new STLVector<CqMicroPolygon>(CqMicroPolygon.class);			///< Vector of vectors of waiting micropolygons in this bucket
	private    STLVector<CqMicroPolyGridBase> m_agridWaiting = new STLVector<CqMicroPolyGridBase>(CqMicroPolyGridBase.class);		///< Vector of vectors of waiting micropolygrids in this bucket

/// A sorted list of primitives for this bucket
//	private	std::priority_queue<boost::shared_ptr<CqBasicSurface>, std::deque<boost::shared_ptr<CqBasicSurface> >, closest_surface> m_aGPrims;

	private STLPriorityQueue<CqBasicSurface> m_aGPrims = new STLPriorityQueue<CqBasicSurface> (1,new closest_surface());
	private	boolean	m_bProcessed;	///< Flag indicating if this bucket has been processed yet.
	/**
	 * 
	 * 
	 * 
	 * @param pie2
	 * @return
	 */
	public static CqImagePixel aieImage(int i) {
		return m_aieImage.get(i);
//		return m_aieImage[i];
	}
	
	/** 
	 * 指定されたスクリーンの位置の量子化前の色情報を取得する。
	 * 量子化前の情報がnullであったならば、黒を返す
	 * もしポジションがバケットの外なら黒を返す。
	 * @param iXPos サンプルのスクリーンの位置
	 * @param iYPos サンプルのスクリーンの位置
	 */
	public CqColor getFColor( int iXPos, int iYPos )
	{
//		CqImagePixel pie;
		int pie;
	    pie = ImageElement( iXPos, iYPos );
//	    if( null != m_aieImage.get(pie) )
	    try
	    {
	    	CqColor col = m_aieImage.get(pie).getFColor();
//	    	CqColor col = m_aieImage[pie].getFColor();
	    	if(col != null)
	          return ( col );
	    	else
	    		return  gColBlack;
	    }
	    catch(ArrayIndexOutOfBoundsException e)
	    {
	          return ( gColBlack );
	    }
	}

}

/////////////////

/**
 * 
 * 
 * 
 * @author NTT DATA Corporation
 */
//public class CqBucket implements IqBucket
//{
//	//************************************************************************//
//	//*** コンストラクタの定義
//	//************************************************************************//
//	
//	/**
//	 * コンストラクタ
//	 */
//	public CqBucket()
//	{
//		 m_bProcessed = false;
//	}
//	
//	/**
//	 * コピーコンストラクタ
//	 * @param From
//	 */
//	public CqBucket( final CqBucket From )
//    {
//		this.assignment(From);
//    }
//	
//	/**　
//	 *　デストラクタ
//	 * 何もしない
//	 */
//	public void destract()
//	{}
//
//	/**
//	 * =演算子のオーバーライド
//	 * @param From
//	 * @return　このバケットを返す
//	 */
//	public CqBucket assignment(final CqBucket From )
//    {
//        m_ampgWaiting = From.m_ampgWaiting;
//        m_agridWaiting = From.m_agridWaiting;
//        m_bProcessed = From.m_bProcessed;
//
//        return ( this );
//    }
//
//	// IqBucketからのオーバライド
//	//　ゲッターセッター
//	public int	Width() 
//    {
//        return ( m_XSize );
//    }
//	public 	int	Height()
//    {
//        return ( m_YSize );
//    }
//	public int	RealWidth()
//    {
//        return ( m_RealWidth );
//    }
//	public 	int	RealHeight() 
//    {
//        return ( m_RealHeight );
//    }
//	public 	int	XOrigin() 
//    {
//        return ( m_XOrigin );
//    }
//	public 	int	YOrigin() 
//    {
//        return ( m_YOrigin );
//    }
//	
//	public  static	int	PixelXSamples()
//	{
//		return m_PixelXSamples; 
//	}
//	public  static	int	PixelYSamples()
//	{
//		return m_PixelYSamples; 
//	}
//	public 	static	float	FilterXWidth()
//	{
//		return m_FilterXWidth; 
//	}
//	public  static	float	FilterYWidth()
//	{
//		return m_FilterYWidth; 
//	}
//	public	static	int	NumTimeRanges()
//	{
//		return m_NumTimeRanges; 
//	}
//	public	static	int	NumDofBounds()
//	{
//		return m_NumDofBounds; 
//	}
//
//	public	static final CqBound DofSubBound(int index)
//	{
//		assert(index < m_NumDofBounds);
//		return m_DofBounds.get(index);
//	}
//
////	----------------------------------------------------------------------
//	/** サンプルの色を指定されたスクリーンの位置を得てください。
//	 * もしポジションがバケットの外なら黒を返す。
//	 * @param iXPos サンプルのスクリーンの位置
//	 * @param iYPos サンプルのスクリーンの位置
//	 */
//	public CqColor Color( int iXPos, int iYPos )
//	{
////		CqImagePixel pie;
//		int pie;
//	    pie = ImageElement( iXPos, iYPos );
////	    if( null != m_aieImage.get(pie) )
//	    try
//	    {
//	          return ( m_aieImage.get(pie).Color() );
//	    }
//	    catch(ArrayIndexOutOfBoundsException e)
//	    {
//	          return ( gColBlack );
//	    }
//	}
//	
////	----------------------------------------------------------------------
//	/** 　指定された位置のサンプルの透明度を取得する。
//	 * もしポジションがバケットの外なら黒を返す。
//	 * @param iXPos サンプルのスクリーンの位置
//	 * @param iYPos サンプルのスクリーンの位置
//	 */
//	
//	public CqColor Opacity( int iXPos, int iYPos )
//	{
////		 CqImagePixel pie;
//		int pie;
//		pie = ImageElement( iXPos, iYPos );
////		if( null != m_aieImage.get(pie) )
//		try
//		{
//			return ( m_aieImage.get(pie).Opacity() );
//		}
//		catch(ArrayIndexOutOfBoundsException e)
//		{
//			return ( gColBlack );
//		}
//		   
//	}
//	
////	----------------------------------------------------------------------
//	/** 指定されたスクリーンの位置でのサンプルの範囲を取得する。
//	 * もし、ポジションがバケットの外なら０を返す。
//	 * @param iXPos サンプルのスクリーンの位置
//	 * @param iYPos サンプルのスクリーンの位置
//	 */
//	public float Coverage( int iXPos, int iYPos )
//	{
////		  CqImagePixel  pie;
//		int pie;
//		pie = ImageElement( iXPos, iYPos );
////		if( null != m_aieImage.get(pie) )
//		try
//		{
//		      return ( m_aieImage.get(pie).Coverage() );
//		}
//		catch(ArrayIndexOutOfBoundsException e)
//		{
//		      return ( 0.0f );
//		}
//	}
//	
////	----------------------------------------------------------------------
//	/** 指定されたスクリーンの位置の深度を取得する。
//	 * もしポジションがバケットの外ならFLT_MAX（無限大）を返す。
//	 * @param iXPos サンプルのスクリーンの位置
//	 * @param iYPos サンプルのスクリーンの位置
//	 */
//	public float Depth( int iXPos, int iYPos )
//	{
////		 CqImagePixel pie;
//		int pie;
//		pie = ImageElement( iXPos, iYPos );
////	    if( null != m_aieImage.get(pie) )
//		try
//		{
//	        return ( m_aieImage.get(pie).Depth() );
//		}
//	    catch(ArrayIndexOutOfBoundsException e)
//	    {
//	        return ( FLT_MAX );
//	    }
//	}
//	
////	----------------------------------------------------------------------
//	/** 指定されたスクリーンの位置のサンプルの深度の最大値を返す。
//	 * もし、ポジションがバケットの外なら、FLT_MAX（無限大）を返す。
//	 * @param iXPos サンプルのスクリーンの位置
//	 * @param iYPos サンプルのスクリーンの位置
//	 */
//
//	public float MaxDepth( int iXPos, int iYPos )
//	{
////		CqImagePixel pie;
//		int pie;
//	    pie = ImageElement( iXPos, iYPos );
////	    if( null != m_aieImage.get(pie) )
//	    try
//	    {
//	        return ( m_aieImage.get(pie).MaxDepth() );
//	    }
//	    catch(ArrayIndexOutOfBoundsException e)
//	    {
//	        return ( FLT_MAX );
//	    }
//}
//	
////	----------------------------------------------------------------------
//	/** サンプルの数を取得する。
//	 * もし、バケットの外なら、0を返す。
//	 * @param iXPos サンプルのスクリーンの位置
//	 * @param iYPos サンプルのスクリーンの位置
//	 */
//	public int DataSize( int iXPos, int iYPos )
//	{
////		CqImagePixel pie;
//		int pie;
//	    pie = ImageElement( iXPos, iYPos );
////	    if( null != m_aieImage.get(pie) )
//	    try
//	    {
//	        return ( m_aieImage.get(pie).DataSize() );
//	    }
//	    catch(ArrayIndexOutOfBoundsException e)
//	    {
//	        return ( 0 );
//	    }
//	}
//	
////	----------------------------------------------------------------------
//	/** 与えられたピクセルサンプルのポインタを取得する。
//	 * もし、ポジションがバケットの外なら、NULLを返す。
//	 * @param iXPos サンプルのスクリーンの位置
//	 * @param iYPos サンプルのスクリーンの位置
//	 */
//	public final Valarray Data( int iXPos, int iYPos )
//	{
////		CqImagePixel pie;
//		int pie;
//	    pie = ImageElement( iXPos, iYPos );
////	    if( null != m_aieImage.get(pie) )
//	    try
//	    {
//	        return ( m_aieImage.get(pie).Data() );
//	    }
//	    catch(ArrayIndexOutOfBoundsException e)
//	    {
//	        return ( null );
//	    }
//	}
//
////	----------------------------------------------------------------------
//	/**
//	 * 静的なイメージのエリアを初期化する。
//	 * 
//	 * 
//	 * @param xorigin　バケットのXポジション
//	 * @param yorigin　バケットのYポジション
//	 * @param xsize バケットのXサイズ
//	 * @param ysize バケットのYサイズ
//	 * @param fJitter 基本的にはtureジッターするかどうか
//	 * @param empty　このフラグを立てると、m_aieImageの中を空にする。
//	 */
//	public static	void	InitialiseBucket( int xorigin, int yorigin, int xsize, int ysize)
//	{
//		InitialiseBucket( xorigin , yorigin , xsize, ysize, true, false );
//	}
//	public static	void	InitialiseBucket( int xorigin, int yorigin, int xsize, int ysize, boolean fJitter )
//	{
//		InitialiseBucket( xorigin , yorigin , xsize, ysize, fJitter, false );
//	}
//	
//	public static	void	InitialiseBucket( int xorigin, int yorigin, int xsize, int ysize, boolean fJitter, boolean empty )
//	{
//		m_XOrigin = xorigin;
//	    m_YOrigin = yorigin;
//	    m_XSize = xsize;
//	    m_YSize = ysize;
//		m_PixelXSamples = m_ImageBuffer.PixelXSamples();
//		m_PixelYSamples = m_ImageBuffer.PixelYSamples();
//		m_FilterXWidth = m_ImageBuffer.FilterXWidth();
//		m_FilterYWidth = m_ImageBuffer.FilterYWidth();
//		m_DiscreteShiftX = (int)Math.floor(m_FilterXWidth/2.0f);
//		m_DiscreteShiftY = (int)Math.floor(m_FilterYWidth/2.0f);
//		m_RealWidth = m_XSize + (m_DiscreteShiftX*2);
//		m_RealHeight = m_YSize + (m_DiscreteShiftY*2);
//
//		m_NumTimeRanges = Math.max(4, m_PixelXSamples * m_PixelYSamples);
//
//	    // Allocate the image element storage if this is the first bucket
////	    if( m_aieImage.empty() )
//		if( m_aieImage.isEmpty() )
//	    {
//	        m_aieImage.setSize( m_RealWidth * m_RealHeight );
//			m_aSamplePositions.setSize( m_RealWidth * m_RealHeight );
//
//			CalculateDofBounds();
//
//	        // Initialise the samples for this bucket.
//	        int which = 0;
//	        for ( int i = 0; i < m_RealHeight; i++ )
//	        {
//	            for ( int j = 0; j < m_RealWidth; j++ )
//	            {
//	                m_aieImage.get(which).Clear();
//	                m_aieImage.get(which).AllocateSamples( m_PixelXSamples, m_PixelYSamples );
//	                m_aieImage.get(which).InitialiseSamples( m_aSamplePositions.get(which), fJitter );
//					m_aieImage.get(which).ShuffleSamples();
//
//	                which++;
//	            }
//	        }
//	    }
//
//		//:TODO: AGG, sort out sample shuffling.
//		// now shuffle the pixels around and add in the pixel offset to the position.
////		std::random_shuffle(m_aieImage.begin(), m_aieImage.end());
////		Collections.shuffle(m_aieImage); //2005/12/20 渡辺 Random
//		Collections.shuffle(m_aieImage,rand);
//		int which = 0;
////		int numPixels = m_RealWidth*m_RealHeight;
//		for ( int i = 0; i < m_RealHeight; i++ )
//		{
//			for ( int j = 0; j < m_RealWidth; j++ )
//			{
//				CqVector2D bPos2 = new CqVector2D( m_XOrigin, m_YOrigin );
//				bPos2.assignAdd( new CqVector2D( ( j - m_DiscreteShiftX ), ( i - m_DiscreteShiftY ) ) );
//
//				if(!empty)
//					m_aieImage.get( which ).Clear();
//
//				m_aieImage.get( which ).OffsetSamples( bPos2, m_aSamplePositions.get(which) );
//
//				which++;
//			}
//		}
//	}
//	
//	/**
//	 * 被写界深度を計算する。（Depth of field）
//	 * 
//	 * 
//	 */
//	public static	void	CalculateDofBounds()
//	{
//		m_NumDofBounds = m_PixelXSamples * m_PixelYSamples;
//		m_DofBounds.setSize(m_NumDofBounds);
//
//		float dx = 2.0f / m_PixelXSamples;
//		float dy = 2.0f / m_PixelYSamples;
//
//		// I know this is far from an optimal way of calculating this,
//		// but it's only done once so I don't care.
//		// Calculate the bounding boxes that the dof offset positions fall into.
//		float minX = -1.0f;
//		float minY = -1.0f;
//		int which = 0;
//		for(int j = 0; j < m_PixelYSamples; ++j)
//		{
//			for(int i = 0; i < m_PixelXSamples; ++i)
//			{
//				CqVector2D topLeft = new CqVector2D(minX, minY);
//				CqVector2D topRight = new CqVector2D(minX + dx, minY);
//				CqVector2D bottomLeft = new CqVector2D(minX, minY + dy);
//				CqVector2D bottomRight = new CqVector2D(minX + dx, minY + dy);
//
//				CqImagePixel.ProjectToCircle(topLeft);
//				CqImagePixel.ProjectToCircle(topRight);
//				CqImagePixel.ProjectToCircle(bottomLeft);
//				CqImagePixel.ProjectToCircle(bottomRight);
//
//				// if the bound straddles x=0 or y=0 then just using the corners
//				// will give too small a bound, so we enlarge it by including the
//				// non-projected coords.
//				if((topLeft.y > 0.0 && bottomLeft.y < 0.0) ||
//					(topLeft.y < 0.0 && bottomLeft.y > 0.0))
//				{
//					topLeft.x(minX);
//					bottomLeft.x(minX);
//					topRight.x(minX + dx);
//					bottomRight.x(minX + dx);
//				}
//				if((topLeft.x > 0.0 && topRight.x < 0.0) ||
//					(topLeft.x < 0.0 && topRight.x > 0.0))
//				{
//					topLeft.y(minY);
//					bottomLeft.y(minY + dy);
//					topRight.y(minY);
//					bottomRight.y(minY + dy);
//				}
//
//				m_DofBounds.get(which).vecMin().assignment( new CqVector3D(topLeft) );
//				m_DofBounds.get(which).vecMax().assignment( new CqVector3D(topLeft) );
//				m_DofBounds.get(which).Encapsulate(topRight);
//				m_DofBounds.get(which).Encapsulate(bottomLeft);
//				m_DofBounds.get(which).Encapsulate(bottomRight);
//
////				m_DofBounds.get(which).vecMin() = topLeft;
////				m_DofBounds.get(which).vecMax() = topLeft;
////				m_DofBounds.get(which).Encapsulate(topRight);
////				m_DofBounds.get(which).Encapsulate(bottomLeft);
////				m_DofBounds.get(which).Encapsulate(bottomRight);
//
//				which++;
//				minX += dx;
//			}
//			minX = -1.0f;
//			minY += dy;
//		}
//	}
////	----------------------------------------------------------------------
//	/** Initialise the static filter values.
//	 * スタティックフィルターの値を初期化します。
//	 */
//	public static	void	InitialiseFilterValues()
//	{
//		if( !m_aFilterValues.isEmpty() )
//	        return;
//
//	    // Allocate and fill in the filter values array for each pixel.
//	    int numsubpixels = ( PixelXSamples() * PixelYSamples() );
//	    int numperpixel = numsubpixels * numsubpixels;
//
//	    int numvalues = (int)( ( ( Math.ceil(FilterXWidth()) + 1 ) * ( Math.ceil(FilterYWidth()) + 1 ) ) * ( numperpixel ) );
//
//	    m_aFilterValues.setSize( numvalues );
//
////	    RtFilterFunc pFilter;
////	    pFilter = QGetRenderContext().optCurrent().funcFilter();
//	    
//	    Method pFilter;
//	    pFilter = QGetRenderContext().optCurrent().funcFilter();
//	    
//	    // Sanity check
//	    if( null == pFilter )
//			try {
//				pFilter = RendermanInterface.class.getMethod("RiBoxFilter",float.class,float.class,float.class,float.class);
//			} catch (Exception e) {
//				HimawariLogger.outputException( e );
//			} 
//
//	    float xmax = m_DiscreteShiftX;
//	    float ymax = m_DiscreteShiftY;
//	    float xfwo2 = (float)Math.ceil(FilterXWidth()) * 0.5f;
//	    float yfwo2 = (float)Math.ceil(FilterYWidth()) * 0.5f;
//	    float xfw = (float)Math.ceil(FilterXWidth());
//
//	    float subcellwidth = 1.0f / numsubpixels;
//	    float subcellcentre = subcellwidth * 0.5f;
//
//	    // Go over every pixel touched by the filter
//	    int px, py;
//	    for ( py = (int)( -ymax ); py <= (int)( ymax ); py++ )
//	    {
//	        for( px = (int)( -xmax ); px <= (int)( xmax ); px++ )
//	        {
//	            // Get the index of the pixel in the array.
//	            int index = (int)( ( ( ( py + ymax ) * xfw ) + ( px + xmax ) ) * numperpixel );
//	            float pfx = px - 0.5f;
//	            float pfy = py - 0.5f;
//	            // Go over every subpixel in the pixel.
//	            int sx, sy;
//	            for ( sy = 0; sy < PixelYSamples(); sy++ )
//	            {
//	                for ( sx = 0; sx < PixelXSamples(); sx++ )
//	                {
//	                    // Get the index of the subpixel in the array
//	                    int sindex = index + ( ( ( sy * PixelXSamples() ) + sx ) * numsubpixels );
//	                    float sfx = (float)( sx ) / PixelXSamples();
//	                    float sfy = (float)( sy ) / PixelYSamples();
//	                    // Go over each subcell in the subpixel
//	                    int cx, cy;
//	                    for ( cy = 0; cy < PixelXSamples(); cy++ )
//	                    {
//	                        for ( cx = 0; cx < PixelYSamples(); cx++ )
//	                        {
//	                            // Get the index of the subpixel in the array
//	                            int cindex = sindex + ( ( cy * PixelYSamples() ) + cx );
//	                            float fx = ( cx * subcellwidth ) + sfx + pfx + subcellcentre;
//	                            float fy = ( cy * subcellwidth ) + sfy + pfy + subcellcentre;
//	                            float w = 0.0f;
//	                            if ( fx >= -xfwo2 && fy >= -yfwo2 && fx <= xfwo2 && fy <= yfwo2 )
//									try {
//										w = (Float)pFilter.invoke( null, (float)fx, (float)fy, (float)Math.ceil(FilterXWidth()),(float)Math.ceil(FilterYWidth()));
//									} catch (Exception e) {
//										HimawariLogger.outputException( e );
//									} 
////	                            m_aFilterValues.[ cindex ] = w;
//	                            m_aFilterValues.get( cindex ).value = w;
//	                        }
//	                    }
//	                }
//	            }
//	        }
//	    }
//	}
//	
//
//	/**
//	 * 指定されたXとYの位置の画素の位置を返す関数
//	 * m_aieImage.get( i );のような感じで使う。
//	 * @param iXPos Xの位置
//	 * @param iYPos Yの位置
//	 * @return XとYの位置からの場所を求める
//	 */
////	public static void	ImageElement( int iXPos, int iYPos, CqImagePixel pie )
//	public static int	ImageElement( int iXPos, int iYPos )
//	{
//		iXPos -= m_XOrigin;
//		iYPos -= m_YOrigin;
//
//		// Check within renderable range
//		//assert( iXPos < -m_XMax && iXPos < m_XSize + m_XMax &&
//		//		iYPos < -m_YMax && iYPos < m_YSize + m_YMax );
//
//		int i = ( ( iYPos + m_DiscreteShiftY ) * ( m_RealWidth ) ) + ( iXPos + m_DiscreteShiftX );
////		pie = m_aieImage.get( i );
//		return i;
//	}
//
////	----------------------------------------------------------------------
//	/**
//	 * 透明な画素の時にm_aieImageの中に格納されているデータを結合して。色を決定する作業をする。
//	 * 実際にはCqImagePixelのCombineを呼び出しているだけ
//	 */
//	public    static	void	CombineElements()
//	{
//		for ( CqImagePixel CIP : m_aieImage )
//			CIP.Combine();       
//	}
//	
////	----------------------------------------------------------------------
//	/**
//	 * フィルターの種類とサンプリングの大きさによってフィルターをかける。
//	 * イメージシェーダなどが呼ばれていればそれを使用する。
//	 * @param empty　このバケットが空であるかどうかを外から取得する。そのことで無駄な計算を省いている。
//	 */
//	public void FilterBucket(boolean empty)
//	{
//	    int pie;
//
//	    int datasize = QGetRenderContext().GetOutputDataTotalSize();
//	    m_aDatas.resize( datasize * RealWidth() * RealHeight() );
//	    m_aCoverages.resize( RealWidth() * RealHeight() );
//
//	    int xmax = m_DiscreteShiftX;
//	    int ymax = m_DiscreteShiftY;
//	    float xfwo2 = (float)Math.ceil(FilterXWidth()) * 0.5f;
//	    float yfwo2 = (float)Math.ceil(FilterYWidth()) * 0.5f;
//	    int numsubpixels = ( PixelXSamples() * PixelYSamples() );
//
//	    int numperpixel = numsubpixels * numsubpixels;
//	    int	xlen = RealWidth();
//
//	    int SampleCount = 0;
//	    CqColor imager;//C++ではnewされてます new shaderテスト時にバグとして見つかるかも2005/12/13 渡辺
//
//	    int x, y;
//	    int i = 0;
//
//	    boolean fImager = false;
//	    String[] systemOptions ;
//	    if( ( systemOptions = QGetRenderContext().optCurrent().GetStringOption( "System", "Imager" ) ) != null )
//	    	if( systemOptions[0].compareTo("null") != 0 )
//			fImager = true;
//
//	    int endy = YOrigin() + Height();
//	    int endx = XOrigin() + Width();
//
//		boolean useSeperable = true;
//
//
//		if(!empty)
//		{
//			// non-seperable is faster for very small filter widths.
//			// 分割されていない物は小さなフィルタよりも早い
//			//フィルターが1x1の時false　それ以外のときはtrue
//			if(FilterXWidth() <= 1.0 || FilterYWidth() <= 1.0)
//				useSeperable = false;
//
//			if(useSeperable)
//			{
//				// seperable filter. filtering by fx,fy is equivalent to filtering
//				// by fx,1 followed by 1,fy.
//				
//
//				int size = Width() * RealHeight() * PixelYSamples();
//				Valarray intermediateSamples = new Valarray( 0.0f, size * datasize);
//				ValarrayInt sampleCounts = new ValarrayInt(0, size);
//				for ( y = YOrigin() - ymax; y < endy + ymax ; y++ )
//				{
//					float ycent = y + 0.5f;
//					int pixelRow = (y-(YOrigin()-ymax)) * PixelYSamples();
//					for ( x = XOrigin(); x < endx ; x++ )
//					{
//						float xcent = x + 0.5f;
//
//						// Get the element at the left side of the filter area.
//						// フィルタエリアの左側における要素を手に入れてください。
//						
//						pie = ImageElement( x - xmax, y );
//
//						int pixelIndex = pixelRow*Width() + x-XOrigin();
//
//						// filter just in x first
//						// フィルターをｘからかける
//						for ( int sy = 0; sy < PixelYSamples(); sy++ )
//						{
//							float gTot = 0.0f;
//							SampleCount = 0;
//							Valarray samples = new Valarray( 0.0f, datasize);
//
//							int pie2 = pie;
//							for ( int fx = -xmax; fx <= xmax; fx++ )
//							{
//								int index = (int)(( ( ymax * Math.ceil(FilterXWidth()) ) + ( fx + xmax ) ) * numperpixel);
//								// Now go over each subsample within the pixel
//								// 今は、画素の中の各「サブ-サンプル」を調べてください。
//								int sampleIndex = sy * PixelXSamples();
//								int sindex = index + ( sy * PixelXSamples() * numsubpixels );
//
//								for ( int sx = 0; sx < PixelXSamples(); sx++ )
//								{
//									SqSampleData sampleData = aieImage( pie2 ).SampleData( sampleIndex );
//									CqVector2D vecS = new CqVector2D( sampleData.m_Position );
//									vecS.assignSub( new  CqVector2D( xcent, ycent ) );
//									if ( vecS.x >= -xfwo2 && vecS.y >= -yfwo2 && vecS.x <= xfwo2 && vecS.y <= yfwo2 )
//									{
//										int cindex = sindex + sampleData.m_SubCellIndex;
//										float g = m_aFilterValues.get( cindex ).value;
//										gTot += g;
//										if ( (aieImage( pie2 ).OpaqueValues( sampleIndex ).m_flags & SqImageSample.Flag_Valid )!= 0)
//										{
//											SqImageSample pSample = aieImage( pie2 ).OpaqueValues( sampleIndex );
//											for ( int k = 0; k < datasize; ++k )
//												//samples[k] += pSample.m_Data[k] * g;
//												samples.setValueAt( k , samples.valueAt(k) + pSample.m_Data.valueAt(k) * g);
//											//sampleCounts[pixelIndex]++;
//											sampleCounts.setValueAt(pixelIndex,sampleCounts.valueAt(pixelIndex)+1 );
//											
//										}
//									}
//									sampleIndex++;
//									sindex += numsubpixels;
//								}
//								pie2++;
//							}
//
//							// store the intermediate result
//							for ( int k = 0; k < datasize; k ++)
//								//intermediateSamples[pixelIndex*datasize + k] = samples[k] / gTot;
//								intermediateSamples.setValueAt(pixelIndex*datasize + k ,  samples.valueAt(k) / gTot);
//								
//							pixelIndex += Width();
//						}
//					}
//				}
//
//				// now filter in y.
//				// yのフィルタをする
//				for ( y = YOrigin(); y < endy ; y++ )
//				{
//					float ycent = y + 0.5f;
//					for ( x = XOrigin(); x < endx ; x++ )
//					{
//						float xcent = x + 0.5f;
//						float gTot = 0.0f;
//						SampleCount = 0;
//						Valarray samples = new Valarray( 0.0f, datasize);
//
//						int fy;
//						// Get the element at the top of the filter area.
//						pie = ImageElement( x, y - ymax );
//						for ( fy = -ymax; fy <= ymax; fy++ )
//						{
//							int pie2 = pie;
//
//							int index = (int)(( ( ( fy + ymax ) * Math.ceil(FilterXWidth()) ) + xmax ) * numperpixel);
//							// Now go over each y subsample within the pixel
//							int sx = PixelXSamples() / 2; // use the samples in the centre of the pixel.
//							int sy = 0;
//							int sampleIndex = sx;
//							int pixelRow = (y + fy - (YOrigin()-ymax)) * PixelYSamples();
//							int pixelIndex = pixelRow*Width() + x-XOrigin();
//
//							for ( sy = 0; sy < PixelYSamples(); sy++ )
//							{
//								int sindex = index + ( ( ( sy * PixelXSamples() ) + sx ) * numsubpixels );
//								SqSampleData sampleData = aieImage( pie2 ).SampleData( sampleIndex );
//								CqVector2D vecS = new CqVector2D( sampleData.m_Position );
//								vecS.assignSub( new CqVector2D( xcent, ycent ) );
//								if ( vecS.x >= -xfwo2 && vecS.y >= -yfwo2 && vecS.x <= xfwo2 && vecS.y <= yfwo2 )
//								{
//									int cindex = sindex + sampleData.m_SubCellIndex;
//									float g = m_aFilterValues.get( cindex ).value;
//									gTot += g;
//									if(sampleCounts.valueAt( pixelIndex ) > 0)
//									{
//										SampleCount += sampleCounts.valueAt( pixelIndex );
//										for ( int k = 0; k < datasize; k++)
//											//samples[k] += intermediateSamples[pixelIndex * datasize + k] * g;
//											samples.setValueAt( k, samples.valueAt(k) + intermediateSamples.valueAt(pixelIndex * datasize + k) * g );
//									}
//								}
//								sampleIndex += PixelXSamples();
//								pixelIndex += Width();
//							}
//
//							pie += xlen;
//						}
//
//						// Set depth to infinity if no samples.
//						// サンプルがなければ深度を無限大に設定する。
//						if ( SampleCount == 0 )
//						{
//							//memset(&m_aDatas[i*datasize], 0, datasize * sizeof(float));
//							for(int k = 0 ;k < datasize ;k++)
//								m_aDatas.get( i*datasize + k ).value = 0.0f ;
//							m_aDatas.get( i*datasize + 6 ).value = FLT_MAX;
//								
//							m_aCoverages.get(i).value = 0.0f;
//						}
//						else
//						{
//							float oneOverGTot = (float) (1.0 / gTot);
//							for ( int k = 0; k < datasize; k ++)
//								m_aDatas.get( i*datasize + k ).value = samples.valueAt(k) * oneOverGTot;
//
//							
//							if ( SampleCount >= numsubpixels)
//								m_aCoverages.get( i ).value = 1.0f;
//							else
//								m_aCoverages.get( i ).value = ( float ) SampleCount / ( float ) (numsubpixels );
//						}
//
//						i++;
//					}
//				}
//			}
//			else
//			{
//				// non-seperable filter
//				// 非分割フィルタ
//				for ( y = YOrigin(); y < endy ; y++ )
//				{
//					float ycent = y + 0.5f;
//					for ( x = XOrigin(); x < endx ; x++ )
//					{
//						float xcent = x + 0.5f;
//						float gTot = 0.0f;
//						SampleCount = 0;
//						Valarray samples = new Valarray( 0.0f, datasize);
//
//						int fx, fy;
//						// Get the element at the upper left corner of the filter area.
//						// フィルタ部の左上隅で要素を手に入れてください。
//						pie = ImageElement( x - xmax, y - ymax );
//						for ( fy = -ymax; fy <= ymax; fy++ )
//						{
//							int pie2 = pie;
//							for ( fx = -xmax; fx <= xmax; fx++ )
//							{
//								int index = (int) (( ( ( fy + ymax ) * Math.ceil(FilterXWidth()) ) + ( fx + xmax ) ) * numperpixel);
//								// Now go over each subsample within the pixel
//								// 今度は、画素の中の各「サブ-サンプル」を調べてください。
//								int sx, sy;
//								int sampleIndex = 0;
//								for ( sy = 0; sy < PixelYSamples(); sy++ )
//								{
//									for ( sx = 0; sx < PixelXSamples(); sx++ )
//									{
//										int sindex = index + ( ( ( sy * PixelXSamples() ) + sx ) * numsubpixels );
//										SqSampleData sampleData = aieImage( pie2 ).SampleData( sampleIndex );
//										CqVector2D vecS = new CqVector2D( sampleData.m_Position );
//										vecS.assignSub( new CqVector2D( xcent, ycent ) );
//										if ( vecS.x >= -xfwo2 && vecS.y >= -yfwo2 && vecS.x <= xfwo2 && vecS.y <= yfwo2 )
//										{
//											int cindex = sindex + sampleData.m_SubCellIndex;
//											float g = m_aFilterValues.get( cindex ).value;
//											gTot += g;
//											if ( (aieImage( pie2 ).OpaqueValues( sampleIndex ).m_flags & SqImageSample.Flag_Valid )!= 0 )
//											{
//												SqImageSample pSample = aieImage( pie2 ).OpaqueValues( sampleIndex );
//												for ( int k = 0; k < datasize; ++k )
//													samples.setValueAt(k ,samples.valueAt(k) + pSample.m_Data.valueAt(k) * g );
//												SampleCount++;
//											}
//										}
//										sampleIndex++;
//									}
//								}
//								pie2++;
//							}
//							pie += xlen;
//						}
//
//
//						// Set depth to infinity if no samples.
//						// もし、サンプルが空であれば無限に設定する。
//						if ( SampleCount == 0 )
//						{
//							//memset(&m_aDatas[i*datasize], 0, datasize * sizeof(float));
//							for(int k = 0 ;k < datasize ;k++)
//								m_aDatas.get( i*datasize +k ).value = 0.0f ;
//							m_aDatas.get( i*datasize+6 ).value = FLT_MAX;
//							
//							m_aCoverages.get(i).value = 0.0f;
//						}
//						else
//						{
//							float oneOverGTot = (float) (1.0 / gTot);
//							for ( int k = 0; k < datasize; k ++)
//								m_aDatas.get( i*datasize + k ).value = samples.valueAt(k) * oneOverGTot;
//
//							if ( SampleCount >= numsubpixels)
//								m_aCoverages.get( i ).value = 1.0f;
//							else
//								m_aCoverages.get( i ).value = ( float ) SampleCount / ( float ) (numsubpixels );
//						}
//
//						i++;
//					}
//				}
//			}
//		}
//		else
//		{
//			// empty bucket.
//			// bucketが空の時
//			int size = Width()*Height();
//			//memset(&m_aDatas[0], 0, size * datasize * sizeof(float));
//			//memset(&m_aCoverages[0], 0, size * sizeof(float));
//			
//			for(int k = i*datasize;k < size * datasize ;k++)
//				m_aDatas.get( i*datasize + k).value = 0.0f ;
//			
//			for(int k = i*datasize;k < size ;k++)
//				m_aCoverages.get( i*datasize + k).value = 0.0f ;
//
//			for(i = 0; i<size; ++i)
//			{
//				// Set the depth to infinity.
//				// 深度を無限に設定する
//				m_aDatas.get( i*datasize+6 ).value = FLT_MAX;
//			}
//		}
//
//	    i = 0;
//	    pie = ImageElement( XOrigin(), YOrigin() );
//	    endy = Height();
//	    endx = Width();
//
//		// Set the coverage and alpha values for the pixel.
//		// 画素に適用範囲とα値を設定してください。
//	    for ( y = 0; y < endy; y++ )
//	    {
//	        int pie2 = pie;
//	        for ( x = 0; x < endx; x++ )
//	        {
//	            SqImageSample spl = aieImage( pie2 ).GetPixelSample();
//				for (int k=0; k < datasize; k++)
//	                spl.m_Data.setValueAt( k, m_aDatas.get( i * datasize + k ).value );
//	            spl.SetCoverage( m_aCoverages.get( i++ ).value );
//		
//				// Calculate the alpha as the combination of the opacity and the coverage.
//				// α値を透明度と、適用範囲の組み合わせとして計算してください。
//				float a = ( spl.Os().fRed() + spl.Os().fGreen() + spl.Os().fBlue() ) / 3.0f;
//				aieImage( pie2 ).SetAlpha(a * spl.Coverage());
//
//				//--Himawari Add
//				aieImage(pie2).setfColor(null);
//				//--
//	            
//				pie2++;
//	        }
//	        pie += xlen;
//	    }
//
//	    endy = YOrigin() + Height();
//	    endx = XOrigin() + Width();
//
//	    if ( null != QGetRenderContext().optCurrent().pshadImager() && null != QGetRenderContext().optCurrent().pshadImager().pShader() )
//	    {
//	        QGetRenderContext().Stats().MakeFilterBucket().Stop();
//	        // Init & Execute the imager shader
//			// 実行されたイメージシェーダを初期化してください。
//
//	        QGetRenderContext().optCurrent().InitialiseColorImager( this );
//
//	        if ( fImager )
//	        {
//	            i = 0;
//	            pie = ImageElement( XOrigin(), YOrigin() );
//	            for ( y = YOrigin(); y < endy ; y++ )
//	            {
//	                int pie2 = pie;
//	                for ( x = XOrigin(); x < endx ; x++ )
//	                {
//	                    imager = QGetRenderContext().optCurrent().GetColorImager( x , y );
//	                    // Normal case will be to poke the alpha from the image shader and
//	                    // multiply imager color with it... but after investigation alpha is always
//	                    // == 1 after a call to imager shader in 3delight and BMRT.
//	                    // Therefore I did not ask for alpha value and set directly the pCols[i]
//	                    // with imager value. see imagers.cpp
//	                    aieImage( pie2 ).SetColor( imager );
//	                    imager = QGetRenderContext().optCurrent().GetOpacityImager( x , y );
//	                    aieImage( pie2 ).SetOpacity( imager );
//	                    pie2++;
//	                    i++;
//	                }
//	                pie += xlen;
//	            }
//	        }
//	        QGetRenderContext().Stats().MakeFilterBucket().Start();
//	    }
//	}
//
////	----------------------------------------------------------------------
//	/** 
//	 * 指定されたゲイン（明るさ）とガンマ設定に従って、このバケツの中のサンプルを露出を変えてください。
//	 * 暗い画像を明るめに表示させるための機能
//	 */
//
//	public    void	ExposeBucket()
//	{
//	    if ( QGetRenderContext().optCurrent().GetFloatOption( "System", "Exposure" ) [ 0 ] == 1.0 &&
//	            QGetRenderContext().optCurrent().GetFloatOption( "System", "Exposure" ) [ 1 ] == 1.0 )
//	        return ;
//	    else
//	    {
////	        CqImagePixel pie;
//	    	int pie;
//	        pie = ImageElement( XOrigin(), YOrigin() );
//	        int x, y;
//	        float exposegain = QGetRenderContext().optCurrent().GetFloatOption( "System", "Exposure" ) [ 0 ];
//	        float exposegamma = QGetRenderContext().optCurrent().GetFloatOption( "System", "Exposure" ) [ 1 ];
//	        float oneovergamma = 1.0f / exposegamma;
//	        float endx, endy;
//	        int   nextx;
//	        endy = Height();
//	        endx = Width();
//	        nextx = RealWidth();
//
//	        for ( y = 0; y < endy; y++ )
//	        {
////	            CqImagePixel pie2 = pie;
//	        	int pie2 = pie;
//	            for ( x = 0; x < endx; x++ )
//	            {
//	                // color=(color*gain)^1/gamma
//	                if ( exposegain != 1.0 )
//	                    m_aieImage.get(pie2).SetColor( m_aieImage.get(pie2).Color().mul( exposegain ) );
//
//	                if ( exposegamma != 1.0 )
//	                {
//	                    CqColor col = m_aieImage.get(pie2).Color();
//	                    col.SetfRed ( (float)Math.pow( col.fRed (), oneovergamma ) );
//	                    col.SetfGreen( (float)Math.pow( col.fGreen(), oneovergamma ) );
//	                    col.SetfBlue ( (float)Math.pow( col.fBlue (), oneovergamma ) );
//	                    m_aieImage.get(pie2).SetColor( col );
//	                }
//	                pie2++;
//	            }
//	            pie += nextx;
//	        }
//	    }
//	}
//	
////	----------------------------------------------------------------------
//	/** Quantize the samples in this bucket according to type.
//	 * バケットの中のサンプルされているものを量子化するメソッド。
//	 */
//	static CqRandom random = new CqRandom( 61 );
//	public    void	QuantizeBucket()
//	{
//	    // Initiliaze the random with a value based on the X,Y coordinate
//		// Xに基づく値、Y座標がある無作為の初期化
////	    static CqRandom random( 61 );
//	    float endx, endy;
//	    int   nextx;
//	    endy = Height();
//	    endx = Width();
//	    nextx = RealWidth();
//
//
//	    if ( ( QGetRenderContext().optCurrent().GetIntegerOption( "System", "DisplayMode" ) [ 0 ] & ModeRGB )!= 0)
//	    {
//	        float[] pQuant = QGetRenderContext().optCurrent().GetFloatOption( "Quantize", "Color" );
//	        int one = (int)( pQuant [ 0 ] );
//	        int min = (int)( pQuant [ 1 ] );
//	        int max = (int)( pQuant [ 2 ] );
//	        double ditheramplitude = pQuant [ 3 ];
//
//	        // If settings are 0,0,0,0 then leave as floating point and we will save an FP tiff.
//	        if ( one == 0 && min == 0 && max == 0 )
//	            return ;
//
////	        CqImagePixel pie;
//	        int pie;
//	        pie = ImageElement( XOrigin(), YOrigin() );
//	        int x, y;
//
//	        for ( y = 0; y < endy; y++ )
//	        {
////	            CqImagePixel pie2 = pie;
//	        	int pie2 = pie;
//	            for ( x = 0; x < endx; x++ )
//	            {
//	                double r, g, b, a;
//	                double _or, _og, _ob;
//	                double s = random.RandomFloat();
//	                CqColor col = m_aieImage.get(pie2).Color();
//	                CqColor opa = m_aieImage.get(pie2).Opacity();
//					float alpha = m_aieImage.get(pie2).Alpha();
//	                
//					//---Himawari add 量子化前のカラー情報を設定する
//	                m_aieImage.get(pie2).setfColor( new CqColor(col) );
//	                //---Himawari end
//	                
//					//四捨五入をしている。javaでは違いそうなので、下の用に書く
////	                if ( modf( one * col.fRed () + ditheramplitude * s, r ) > 0.5 ) r += 1;
////	                if ( modf( one * col.fGreen() + ditheramplitude * s, g ) > 0.5 ) g += 1;
////	                if ( modf( one * col.fBlue () + ditheramplitude * s, b ) > 0.5 ) b += 1;
////	                if ( modf( one * opa.fRed () + ditheramplitude * s, _or ) > 0.5 ) _or += 1;
////	                if ( modf( one * opa.fGreen() + ditheramplitude * s, _og ) > 0.5 ) _og += 1;
////	                if ( modf( one * opa.fBlue () + ditheramplitude * s, _ob ) > 0.5 ) _ob += 1;
////	                if ( modf( one * alpha + ditheramplitude * s, a ) > 0.5 ) a += 1;
//	                r = Math.round( one * col.fRed () + ditheramplitude * s);
//	                g = Math.round( one * col.fGreen() + ditheramplitude * s);
//	                b = Math.round( one * col.fBlue() + ditheramplitude * s);
//	                _or = Math.round( one * opa.fRed () + ditheramplitude * s );
//	                _og = Math.round( one * opa.fGreen() + ditheramplitude * s);
//	                _ob = Math.round(one * opa.fBlue () + ditheramplitude * s);
//	                a = Math.round( one * alpha + ditheramplitude * s );
//	                
//					r = CLAMP( (float)r, (float)min, (float)max );
//	                g = CLAMP( (float)g, (float)min, (float)max );
//	                b = CLAMP( (float)b, (float)min, (float)max );
//	                _or = CLAMP( (float)_or, (float)min, (float)max );
//	                _og = CLAMP( (float)_og, (float)min, (float)max );
//	                _ob = CLAMP( (float)_ob, (float)min, (float)max );
//	                a = CLAMP( (float)a, (float)min, (float)max );
//
//	                col.SetfRed ( (float)r );
//	                col.SetfGreen( (float)g );
//	                col.SetfBlue ( (float)b );
//	                opa.SetfRed ( (float)_or );
//	                opa.SetfGreen( (float)_og );
//	                opa.SetfBlue ( (float)_ob );
//
//	                m_aieImage.get(pie2).SetColor( col );
//	                m_aieImage.get(pie2).SetOpacity( opa );
//	                m_aieImage.get(pie2).SetAlpha( (float)a );
//	                pie2++;
//	            }
//	            pie += nextx;
//	        }
//	    }
//
//	    if ( ( QGetRenderContext().optCurrent().GetIntegerOption( "System", "DisplayMode" ) [ 0 ] & ModeZ ) != 0 )
//	    {
//	        float[] pQuant = QGetRenderContext().optCurrent().GetFloatOption( "Quantize", "Depth" );
//	        int one = (int)( pQuant [ 0 ] );
//	        int min = (int)( pQuant [ 1 ] );
//	        int max = (int)( pQuant [ 2 ] );
//	        double ditheramplitude = pQuant [ 3 ];
//	        if( ditheramplitude == 0.0f && one == 0 && min == 0 && max == 0 )
//	            return;
//
////	        CqImagePixel pie;
//	        int pie; 
//	        pie = ImageElement( XOrigin(), YOrigin() );
//	        int x, y;
//	        for ( y = 0; y < endy; y++ )
//	        {
////	            CqImagePixel pie2 = pie;
//	            int pie2 = pie;
//	            for ( x = 0; x < endx; x++ )
//	            {
//	                double d;
////	                if ( modf( one * m_aieImage.get(pie2).Depth() + ditheramplitude * random.RandomFloat(), &d ) > 0.5 ) d += 1;
//	                d = Math.round(one * m_aieImage.get(pie2).Depth() + ditheramplitude * random.RandomFloat());
//	                d = CLAMP( (float)d, (float)min, (float)max );
//	                m_aieImage.get(pie2).SetDepth( (float)d );
//	                pie2++;
//	            }
//	            pie += nextx;
//	        }
//	    }
//
//	    // Now go through the other AOV's and quantize those if necessary.
////	    std::map<std::string, CqRenderer::SqOutputDataEntry>& DataMap = QGetRenderContext()->GetMapOfOutputDataEntries();
////	    std::map<std::string, CqRenderer::SqOutputDataEntry>::iterator entry;
//	    
//	    HashMap<String, CqRenderer.SqOutputDataEntry> DataMap = QGetRenderContext().GetMapOfOutputDataEntries();
//	    
//	    	    
////	    for( entry = DataMap.begin(); entry != DataMap.end(); entry++ )
//	    for(Entry<String, CqRenderer.SqOutputDataEntry> entry : DataMap.entrySet() )
//	    {
//	        float[] pQuant = QGetRenderContext().optCurrent().GetFloatOption( "Quantize", entry.getKey() );
//	        if( null != pQuant )
//	        {
//	            int startindex = entry.getValue().m_Offset;
//	            int endindex = startindex + entry.getValue().m_NumSamples;
//	            int one = (int)( pQuant [ 0 ] );
//	            int min = (int)( pQuant [ 1 ] );
//	            int max = (int)( pQuant [ 2 ] );
//	            double ditheramplitude = pQuant [ 3 ];
//
////	            CqImagePixel pie;
//	            int pie;
//	            pie = ImageElement( XOrigin(), YOrigin() );
//	            int x, y;
//	            for ( y = 0; y < endy; y++ )
//	            {
////	                CqImagePixel pie2 = pie;
//	            	int pie2 = pie;
//	                for ( x = 0; x < endx; x++ )
//	                {
//	                    int sampleindex;
//	                    for( sampleindex = startindex; sampleindex < endindex; sampleindex++ )
//	                    {
//	                        double d;
////	                        if ( modf( one * m_aieImage.get(pie2).GetPixelSample().m_Data.valueAt( sampleindex ) + ditheramplitude * random.RandomFloat(), d ) > 0.5 ) d += 1.0f;
//	                        d = Math.round(one * m_aieImage.get(pie2).GetPixelSample().m_Data.valueAt( sampleindex ) + ditheramplitude * random.RandomFloat());
//	                        d = CLAMP( (float)d,(float) min,(float) max );
//	                        m_aieImage.get(pie2).GetPixelSample().m_Data.setValueAt( sampleindex , (float)d);
//	                    }
//	                    pie2++;
//	                }
//	                pie += nextx;
//	            }
//	        }
//	    }
//	}
//
////	----------------------------------------------------------------------
//	/** 
//	 * バケットの中身をクリアする。
//	 */
//	public    static	void	ShutdownBucket()
//	{
//	    m_aieImage.clear();
//	    m_aFilterValues.clear();
//		m_aCoverages.clear();
//		m_aDatas.clear();
//		
////		javaだと必要ない
////		for(STLVector<CqVector2D> i : m_aSamplePositions )
////		{
////			i.clear();
////			i = null;
////		}
//		m_aSamplePositions.clear();
//	}
//	
//
//	    /** 
//	     * 伸ばされたGprimsのスタックへGprimを追加する。
//		 * @parame pGprim 追加するpGPrim
//	     */
//	public void	AddGPrim( final CqBasicSurface pGPrim )
//	{
//		m_aGPrims.add(pGPrim);
//	}
//
//	    /** 
//	     * MPGを延長されたMPGｓのリストに追加する。
//	     */
//	public void	AddMPG( CqMicroPolygon pmpgNew )
//	    {
////	#ifdef _DEBUG
////	        std::vector<CqMicroPolygon*>::iterator end = m_ampgWaiting.end();
////	        for (std::vector<CqMicroPolygon*>::iterator i = m_ampgWaiting.begin(); i != end; i++)
////	            if ((*i) == pmpgNew)
////	                assert( TqFalse );
////	#endif
//	        m_ampgWaiting.add( pmpgNew );
//	    }
//	    /** 
//	     * Micropoly gridを延長されたgridsのリストに追加する。
//	     */
//	public void	AddGrid( CqMicroPolyGridBase pgridNew )
//	    {
////	#ifdef _DEBUG
////	        std::vector<CqMicroPolyGridBase*>::iterator end = m_agridWaiting.end();
////	        for (std::vector<CqMicroPolyGridBase*>::iterator i = m_agridWaiting.begin(); i != end; i++)
////	            if ((*i) == pgridNew)
////	                assert( TqFalse );
////	#endif
//			
//	        m_agridWaiting.add( pgridNew );
//	    }
//	
//	    /** 
//	     * GprimsのスタックのTopのGprimのポインタを取得する
//	     */
//	public  CqBasicSurface pTopSurface()
//    {
//		if (!m_aGPrims.isEmpty())
//		{
//		    return m_aGPrims.peek();
//		}
//		else
//		{
//		    return null;// boost::shared_ptr<CqBasicSurface>();
//		}
//    }
//    /** 
//     * GprimsのスタックのGprimをPOPする
//     */
//	public    void popSurface()
//    {
//		m_aGPrims.poll();
//    }
//    /**
//     * Gprimsの数を取得する。
//     */
//	public    int cGPrims()
//    {
//		return ( m_aGPrims.size() );
//    }
//    /** 
//     * MPGｓのベクタの参照を取得する。
//     */
//	public STLVector<CqMicroPolygon> aMPGs()
//    {
//        return ( m_ampgWaiting );
//    }
//    /**
//     * girdsのヴェクターの参照を取得する。 
//     */
//    public STLVector<CqMicroPolyGridBase> aGrids()
//    {
//        return ( m_agridWaiting );
//    }
//    /** 
//     * バケツがまだ処理されているか同かを示すフラグを取得する。
//     */
//    public boolean IsProcessed()
//    {
//        return( m_bProcessed );
//    }
//
//    /** 
//     * このバケットが処理中であることをマークする。
//     */
//    public void SetProcessed()
//    {
//        SetProcessed(true);
//    }
//    public void SetProcessed( boolean bProc )
//    {
//        m_bProcessed = bProc;
//    }
//    /**
//     * イメージバッファのポインタをセットする。 
//     */
//    public static void SetImageBuffer( CqImageBuffer pBuffer )
//    {
//        m_ImageBuffer = pBuffer;
//    }
//
//
//	
//	private		static	int	m_XOrigin;		///< Origin in discrete coordinates of this bucket.
//	private    	static	int	m_YOrigin;		///< Origin in discrete coordinates of this bucket.
//	private    	static	int	m_XSize;		///< Size of the rendered area of this bucket in discrete coordinates.
//	private    	static	int	m_YSize;		///< Size of the rendered area of this bucket in discrete coordinates.
//	private		static	int	m_RealWidth;	///< Actual size of the data for this bucket including filter overlap.
//	private		static	int	m_RealHeight;	///< Actual size of the data for this bucket including filter overlap.
//	private		static	int	m_DiscreteShiftX;	///< 
//	private		static	int	m_DiscreteShiftY;
//	private		static	int	m_PixelXSamples;
//	private		static	int	m_PixelYSamples;
//	private		static	float	m_FilterXWidth;
//	private		static	float	m_FilterYWidth;
//	private		static	int	m_NumTimeRanges;
//	private		static	int	m_NumDofBounds;
//	private		static	STLVector<CqBound>		m_DofBounds = new STLVector<CqBound>( CqBound.class );
//	private    	static	STLVector<CqImagePixel>	m_aieImage = new STLVector<CqImagePixel>( CqImagePixel.class );
//	private    	static	STLVector<STLVector<CqVector2D>>	m_aSamplePositions = new STLVector<STLVector<CqVector2D>>( 2, CqVector2D.class );///< Vector of vectors of jittered sample positions precalculated.
//	private    	static	STLVector<p_float>	m_aFilterValues = new STLVector<p_float>( p_float.class );				///< Vector of filter weights precalculated.
//	private    	static	STLVector<p_float>	m_aDatas = new STLVector<p_float>( p_float.class );
//	private    	static	STLVector<p_float>	m_aCoverages = new STLVector<p_float>( p_float.class );
//	private		static	CqImageBuffer	m_ImageBuffer;	///< Pointer to the image buffer this bucket belongs to.
//
//		// this is a compare functor for sorting surfaces in order of depth.
//	private	class closest_surface implements Comparator<CqBasicSurface>
//	{
//		
//		public int compare(CqBasicSurface s1, CqBasicSurface s2) 
//		{
//			
//			if ( s1.fCachedBound() && s2.fCachedBound() )
//	        {
//				  if( s1.GetCachedRasterBound().vecMin().z > s2.GetCachedRasterBound().vecMin().z )
//					  return 1;		//priority_queueの仕様がC++とは逆で最小の値がトップに来るので逆に返している。
//				  else if( s1.GetCachedRasterBound().vecMin().z < s2.GetCachedRasterBound().vecMin().z )
//					  return -1;
//				  else
//					  return 0;
//	        }
//			else
//			{
//				// don't have bounds for the surface(s). I suspect we should assert here.
//				return -1;
//			}	
//			
//		}
//		
//	};
//
//	private    STLVector<CqMicroPolygon> m_ampgWaiting = new STLVector<CqMicroPolygon>(CqMicroPolygon.class);			///< Vector of vectors of waiting micropolygons in this bucket
//	private    STLVector<CqMicroPolyGridBase> m_agridWaiting = new STLVector<CqMicroPolyGridBase>(CqMicroPolyGridBase.class);		///< Vector of vectors of waiting micropolygrids in this bucket
//
///// A sorted list of primitives for this bucket
////	private	std::priority_queue<boost::shared_ptr<CqBasicSurface>, std::deque<boost::shared_ptr<CqBasicSurface> >, closest_surface> m_aGPrims;
//
//	private STLPriorityQueue<CqBasicSurface> m_aGPrims = new STLPriorityQueue<CqBasicSurface> (1,new closest_surface());
//	private	boolean	m_bProcessed;	///< Flag indicating if this bucket has been processed yet.
//	/**
//	 * 
//	 * 
//	 * 
//	 * @param pie2
//	 * @return
//	 */
//	public static CqImagePixel aieImage(int i) {
//		return m_aieImage.get(i);
//	}
//	
//	/** 
//	 * 指定されたスクリーンの位置の量子化前の色情報を取得する。
//	 * 量子化前の情報がnullであったならば、黒を返す
//	 * もしポジションがバケットの外なら黒を返す。
//	 * @param iXPos サンプルのスクリーンの位置
//	 * @param iYPos サンプルのスクリーンの位置
//	 */
//	public CqColor getFColor( int iXPos, int iYPos )
//	{
////		CqImagePixel pie;
//		int pie;
//	    pie = ImageElement( iXPos, iYPos );
////	    if( null != m_aieImage.get(pie) )
//	    try
//	    {
//	    	CqColor col = m_aieImage.get(pie).getFColor();
//	    	if(col != null)
//	          return ( col );
//	    	else
//	    		return  gColBlack;
//	    }
//	    catch(ArrayIndexOutOfBoundsException e)
//	    {
//	          return ( gColBlack );
//	    }
//	}
//
//}

