public Bitmap Resample(Bitmap image, int width, int height)
    {
        ResamplingService resamplingService = new ResamplingService();

        resamplingService.Filter = ResamplingFilters.Lanczos3;
        ushort[][,] input        = ResamplingFilter.ConvertBitmapToArray((Bitmap)image);
        ushort[][,] output       = resamplingService.Resample(input, width, height);
        Bitmap result = (Bitmap)ResamplingFilter.ConvertArrayToBitmap(output);

        return(result);
    }
    public void Resample(ResamplingFilters filter, int newWidth, int newHeight)
    {
        if (Disposed)
        {
            return;
        }
        ResamplingService resamplingService = new ResamplingService();

        resamplingService.Filter = filter;
        var array  = ResamplingFilter.ConvertByteArrayToArray((byte *)this.Bytes.ToPointer(), this.Width, this.Height);
        var result = resamplingService.Resample(array, newWidth, newHeight);

        this.InternalResize(newWidth, newHeight);
        ResamplingFilter.ConvertArrayToByteArray(result, (byte *)this.Bytes.ToPointer());
    }
		public void colorAlphaFromSplat(int splat_control_tex_idx) {
			ReliefTerrain _target=(ReliefTerrain)target;
			Color[] cols;
			
			if (!_target.ColorGlobal) return;
			_target.prepare_tmpTexture(true);
			if (!_target.ColorGlobal) return;
			if ((_target.ColorGlobal.format!=TextureFormat.Alpha8) && (_target.ColorGlobal.format!=TextureFormat.ARGB32)) {
				try { 
					_target.ColorGlobal.GetPixels(0,0,4,4,0);
				} catch (Exception e) {
					Debug.LogError("Global ColorMap has to be marked as isReadable...");
					Debug.LogError(e.Message);
				}
				Texture2D tmp_globalColorMap;
				if (_target.ColorGlobal.format==TextureFormat.Alpha8) {
					tmp_globalColorMap=new Texture2D(_target.ColorGlobal.width, _target.ColorGlobal.height, TextureFormat.Alpha8, true); 
				} else {
					tmp_globalColorMap=new Texture2D(_target.ColorGlobal.width, _target.ColorGlobal.height, TextureFormat.ARGB32, true); 
				}
				cols=_target.ColorGlobal.GetPixels();
				_target.ColorGlobal=tmp_globalColorMap;
			} else {
				cols=_target.ColorGlobal.GetPixels();
			}
			
			if (splat_control_tex_idx<_target.globalSettingsHolder.numLayers) {
				
				Texture2D splatA=_target.controlA;
				Texture2D splatB=(_target.globalSettingsHolder.numLayers<=8) ? _target.controlB : _target.controlC;
				float[,] blured_sum=new float[_target.ColorGlobal.width, _target.ColorGlobal.height];
				int idx;
				
				if (splatA.width!=_target.ColorGlobal.width || splatA.height!=_target.ColorGlobal.height) {
					ResamplingService resamplingService = new ResamplingService();
					resamplingService.Filter = ResamplingFilters.Quadratic;
					ushort[][,] input = ConvertTextureToArray((Texture2D)splatA);
					ushort[][,] output = resamplingService.Resample(input, _target.ColorGlobal.width, _target.ColorGlobal.height);
					for(int i=0; i<_target.ColorGlobal.width; i++) {
						for(int j=0; j<_target.ColorGlobal.height; j++) {
							blured_sum[i,j]=(output[0][i,j]+output[1][i,j]+output[2][i,j]+output[3][i,j])/255.0f;
						}
					}
				} else {
					Color32[] cols_splat=splatA.GetPixels32();
					idx=0;
					for(int i=0; i<_target.ColorGlobal.width; i++) {
						for(int j=0; j<_target.ColorGlobal.height; j++) {
							blured_sum[i,j]=(cols_splat[idx].r+cols_splat[idx].g+cols_splat[idx].b+cols_splat[idx].a)/255.0f;
							idx++;
						}
					}
				}
				if (splatB.width!=_target.ColorGlobal.width || splatB.height!=_target.ColorGlobal.height) {
					ResamplingService resamplingService = new ResamplingService();
					resamplingService.Filter = ResamplingFilters.Quadratic;
					ushort[][,] input = ConvertTextureToArray((Texture2D)splatB);
					ushort[][,] output = resamplingService.Resample(input, _target.ColorGlobal.width, _target.ColorGlobal.height);
					for(int i=0; i<_target.ColorGlobal.width; i++) {
						for(int j=0; j<_target.ColorGlobal.height; j++) {
							blured_sum[i,j]=Mathf.Max(blured_sum[i,j], (output[0][i,j]+output[1][i,j]+output[2][i,j]+output[3][i,j])/255.0f);
						}
					}
				} else {
					Color32[] cols_splat=splatB.GetPixels32();
					idx=0;
					for(int i=0; i<_target.ColorGlobal.width; i++) {
						for(int j=0; j<_target.ColorGlobal.height; j++) {
							blured_sum[i,j]=Mathf.Max(blured_sum[i,j], (cols_splat[idx].r+cols_splat[idx].g+cols_splat[idx].b+cols_splat[idx].a)/255.0f);
							idx++;
						}
					}
				}
				for(int i=0; i<_target.ColorGlobal.width; i++) {
					for(int j=0; j<_target.ColorGlobal.height; j++) {
						if (blured_sum[i,j]>1) blured_sum[i,j]=1; else blured_sum[i,j]=blured_sum[i,j];
					}
				}
				
				float[,] blured_sum2=new float[_target.ColorGlobal.width, _target.ColorGlobal.height];
				float[,] tmp_blured_sum;
				for(int blur_cnt=0; blur_cnt<4; blur_cnt++) {
					for(int i=1; i<_target.ColorGlobal.width-1; i++) {
						for(int j=1; j<_target.ColorGlobal.height-1; j++) {
							blured_sum2[i,j]=0.7f*(blured_sum[i+1,j]+blured_sum[i-1,j]+blured_sum[i,j+1]+blured_sum[i,j-1]);
							blured_sum2[i,j]+=0.3f*(blured_sum[i+1,j+1]+blured_sum[i+1,j-1]+blured_sum[i-1,j+1]+blured_sum[i-1,j-1]);
							blured_sum2[i,j]*=0.25f;
						}
					}
					tmp_blured_sum=blured_sum;
					blured_sum=blured_sum2;
					blured_sum2=tmp_blured_sum;
				}
				idx=0;
				for(int i=0; i<_target.ColorGlobal.width; i++) {
					for(int j=0; j<_target.ColorGlobal.height; j++) {
						cols[idx].a=blured_sum[i,j];
						cols[idx].a*=cols[idx].a;
						cols[idx].a*=cols[idx].a;
						if (cols[idx].a<0.008f) cols[idx].a=0.008f;
						idx++;
					}
				}
				
				_target.ColorGlobal.SetPixels(cols);
				_target.ColorGlobal.Apply(true,false);
			}
		}
		private Texture2D PadTex(Texture2D splat, int padding, bool updateMips=true) {
			int size=splat.width;
			int size_padded=size-padding*2;
			
			ResamplingService resamplingService = new ResamplingService();
			resamplingService.Filter = ResamplingFilters.Lanczos3;
			ushort[][,] input = ConvertTextureToArray((Texture2D)splat);
			ushort[][,] output = resamplingService.Resample(input, size_padded, size_padded);
			for(int c=0; c<4; c++) {
				for(int i=0; i<size_padded; i++) {
					for(int j=0; j<size_padded; j++) {
						if (output[c][i,j]>255) output[c][i,j]=255;
					}
				}
			}
			
			Color32[] cols=new Color32[size*size];
			for(int j=0; j<size; j++) {
				int j_idx1=j*size;
				int j_idx2=((j+size_padded-padding)%size_padded);
				for(int i=0; i<size; i++) {
					int i2=(i+size_padded-padding)%size_padded;
					cols[j_idx1].r=(byte)output[0][i2, j_idx2];
					cols[j_idx1].g=(byte)output[1][i2, j_idx2];
					cols[j_idx1].b=(byte)output[2][i2, j_idx2];
					cols[j_idx1].a=(byte)output[3][i2, j_idx2];
					j_idx1++;
				}
			}
			if (updateMips) {
				Texture2D tex=new Texture2D(size,size,TextureFormat.ARGB32,true);
				tex.SetPixels32(cols);
				tex.Apply(true,false);
				return tex;
			} else {
				Texture2D tex=new Texture2D(size,size,TextureFormat.ARGB32,false);
				tex.SetPixels32(cols);
				tex.Apply(false,false);
				return tex;
			}
		}