C# 将多波段16位tiff图像转换为8位tiff图像
我从16位(范围0-65535)tif图像中获取了一些像素数据,作为一个整数数组。我使用gdal readraster获得了该值。如何将其转换为8位(0-225)并将其(阵列)转换为8位tif图像 以下是我的一些代码:C# 将多波段16位tiff图像转换为8位tiff图像,c#,arrays,image-processing,tiff,gdal,C#,Arrays,Image Processing,Tiff,Gdal,我从16位(范围0-65535)tif图像中获取了一些像素数据,作为一个整数数组。我使用gdal readraster获得了该值。如何将其转换为8位(0-225)并将其(阵列)转换为8位tif图像 以下是我的一些代码: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using OSGeo.GDAL; using
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OSGeo.GDAL;
using OSGeo.OSR;
namespace ConsoleApplication4
{
class Program
{
static void Main(string[] args)
{
Gdal.AllRegister();
Dataset data1;
int xsize, ysize;
int bandsize;
data1 = Gdal.Open("F:\\po_1473547_bgrn_0000000.tif", Access.GA_ReadOnly);
bandsize = data1.RasterCount;
xsize = data1.RasterXSize; //cols
ysize = data1.RasterYSize; //rows
Console.WriteLine("cols : "+xsize+", rows : "+ysize);
Band[] bands = new Band[bandsize];
for (int i = 0; i < bandsize; i++) {
bands[i] = data1.GetRasterBand(i+1);
}
int[,,] pixel = new int[bandsize,xsize,ysize];
int[] pixtemp = new int[xsize * ysize];
for (int i = 0; i < bandsize; i++)
{
bands[i].ReadRaster(0, 0, xsize, ysize, pixtemp, xsize, ysize, 0, 0);
for (int j = 0; j < xsize; j++)
{
for (int k = 0; k < ysize; k++)
{
pixel[i,j,k] = pixtemp[j + k * xsize];
}
}
}
Console.WriteLine("");
for (int i = 0; i < bandsize; i++)
{
Console.WriteLine("some pixel from band " + (i+1));
for (int j = 0; j < 100; j++)
{
Console.Write(" " + pixel[i,100,j]);
}
Console.WriteLine("\n\n");
}
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
使用OSGeo.GDAL;
使用OSGeo.OSR;
命名空间控制台应用程序4
{
班级计划
{
静态void Main(字符串[]参数)
{
Gdal.AllRegister();
数据集数据1;
int-xsize,ysize;
整数带宽;
data1=Gdal.Open(“F:\\po_1473547_bgrn_0000000.tif”,Access.GA_只读);
带宽=data1.RasterCount;
xsize=data1.RasterXSize;//cols
ysize=data1.RasterYSize;//行
WriteLine(“cols:+xsize+”,行:+ysize);
波段[]波段=新波段[波段大小];
对于(int i=0;i
我在谷歌上搜索如何做到这一点,但我只找到了在数据类型为字节时如何做到这一点。有人请给我一个提示。我不知道GEO Tiff格式,但要将常规的16位Tiff图像文件转换为8位,需要将16位通道值缩放为8位。下面的示例显示了如何为灰度图像实现这一点
public static class TiffConverter
{
private static IEnumerable<BitmapSource> Load16BitTiff(Stream source)
{
var decoder = new TiffBitmapDecoder(source, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
for (int i = 0; i < decoder.Frames.Count; i++)
// return all frames that are present in the input.
yield return decoder.Frames[i];
}
private static BitmapSource NormalizeTiffTo8BitImage(BitmapSource source)
{
// allocate buffer & copy image bytes.
var rawStride = source.PixelWidth * source.Format.BitsPerPixel / 8;
var rawImage = new byte[rawStride * source.PixelHeight];
source.CopyPixels(rawImage, rawStride, 0);
// get both max values of first & second byte of pixel as scaling bounds.
var max1 = 0;
int max2 = 1;
for (int i = 0; i < rawImage.Length; i++)
{
if ((i & 1) == 0)
{
if (rawImage[i] > max1)
max1 = rawImage[i];
}
else if (rawImage[i] > max2)
max2 = rawImage[i];
}
// determine normalization factors.
var normFactor = max2 == 0 ? 0.0d : 128.0d / max2;
var factor = max1 > 0 ? 255.0d / max1 : 0.0d;
max2 = Math.Max(max2, 1);
// normalize each pixel to output buffer.
var buffer8Bit = new byte[rawImage.Length / 2];
for (int src = 0, dst = 0; src < rawImage.Length; dst++)
{
int value16 = rawImage[src++];
double value8 = ((value16 * factor) / max2) - normFactor;
if (rawImage[src] > 0)
{
int b = rawImage[src] << 8;
value8 = ((value16 + b) / max2) - normFactor;
}
buffer8Bit[dst] = (byte)Math.Min(255, Math.Max(value8, 0));
src++;
}
// return new bitmap source.
return BitmapSource.Create(
source.PixelWidth, source.PixelHeight,
source.DpiX, source.DpiY,
PixelFormats.Gray8, BitmapPalettes.Gray256,
buffer8Bit, rawStride / 2);
}
private static void SaveTo(IEnumerable<BitmapSource> src, string fileName)
{
using (var stream = File.Create(fileName))
{
var encoder = new TiffBitmapEncoder();
foreach (var bms in src)
encoder.Frames.Add(BitmapFrame.Create(bms));
encoder.Save(stream);
}
}
public static void Convert(string inputFileName, string outputFileName)
{
using (var inputStream = File.OpenRead(inputFileName))
SaveTo(Load16BitTiff(inputStream).Select(NormalizeTiffTo8BitImage), outputFileName);
}
}
将像素从16位插值到8位,一些重采样方法可以执行 也许会有帮助
//Convert tiff from 16-bit to 8-bit
byte[,,] ConvertBytes(int[,,] pixel, bandsize, xsize, ysize)
{
byte[,,] trgPixel = new byte[bandsize,xsize,ysize];
for (int i = 0; i < bandsize; i++)
{
for (int j = 0; j < xsize; j++)
{
for (int k = 0; k < ysize; k++)
{
//Linear Interpolation
trgPixel[i,j,k] = (byte)((65535-pixel[i,j,k])/65536.0*256);
}
}
}
return trgPixel;
}
//Save 8-bit tiff to file
void SaveBytesToTiff(string destPath, byte[,,] pixel, bandsize, xsize, ysize)
{
string fileformat = "GTiff";
Driver dr = Gdal.getDriverByName(fileformat);
Dataset newDs = dr.Create(destPath, xsize, ysize, bandsize, DateType.GDT_Byte, null);
for(int i=0; i< bandsize;i++)
{
byte[] buffer = new byte[xsize * ysize];
for (int j = 0; j < xsize; j++)
{
for (int k = 0; k < ysize; k++)
{
buffer[j+k*xsize] = pixel[i,j,k];
}
}
newDs.WriteRaster(0, 0, xsize, ysize, buffer, xsize, ysize, i+1, null, 0, 0, 0);
newDs.FlushCache();
}
newDs.Dispose();
}
//将tiff从16位转换为8位
字节[,]转换字节(整数[,]像素,带宽,xsize,ysize)
{
字节[,]trgPixel=新字节[bandsize,xsize,ysize];
对于(int i=0;i
非常感谢:D,它适用于1band图像,但是当我使用4band图像时,图像被破坏了,我必须修改代码的哪一部分来处理4band图像?@SatriaLoka我不确定,但假设这些“频带”在解码器中作为单独的帧出现,这可以通过简单的解码来解决,将它们规格化,并将它们作为转换帧逐个添加到输出图像中。我已经编辑了我的答案来实现这一点。我在一个数组中分离了这些带,但是数据类型是int,我可以从int构建bitmapsource吗?如果我不使用字节数据类型,恐怕这将是一个混乱的图像,因为你的代码使用字节数据类型你不能使用TiffBitmapDecoder
,就像上面的答案一样,使用TiffConverter.Convert(@“F:\po_1473547_bgrn_0000000.tif”,“F:\new_8bit.tif”)代码>?我这样做了,输出是意外的,与前面的代码相同,当我检查“decoder.Frames.Count”时,值仅为1?我在这里遗漏了什么?虽然这段代码可以回答这个问题,但提供关于如何和/或为什么解决问题的额外上下文将提高答案的长期价值。@DonaldDuck有什么让人困惑的地方吗?我想得很清楚,我没说让人困惑。只使用代码的答案质量很低。所以请解释一下你的代码的基本功能,以及为什么你认为它能回答这个问题。我也建议你阅读
//Convert tiff from 16-bit to 8-bit
byte[,,] ConvertBytes(int[,,] pixel, bandsize, xsize, ysize)
{
byte[,,] trgPixel = new byte[bandsize,xsize,ysize];
for (int i = 0; i < bandsize; i++)
{
for (int j = 0; j < xsize; j++)
{
for (int k = 0; k < ysize; k++)
{
//Linear Interpolation
trgPixel[i,j,k] = (byte)((65535-pixel[i,j,k])/65536.0*256);
}
}
}
return trgPixel;
}
//Save 8-bit tiff to file
void SaveBytesToTiff(string destPath, byte[,,] pixel, bandsize, xsize, ysize)
{
string fileformat = "GTiff";
Driver dr = Gdal.getDriverByName(fileformat);
Dataset newDs = dr.Create(destPath, xsize, ysize, bandsize, DateType.GDT_Byte, null);
for(int i=0; i< bandsize;i++)
{
byte[] buffer = new byte[xsize * ysize];
for (int j = 0; j < xsize; j++)
{
for (int k = 0; k < ysize; k++)
{
buffer[j+k*xsize] = pixel[i,j,k];
}
}
newDs.WriteRaster(0, 0, xsize, ysize, buffer, xsize, ysize, i+1, null, 0, 0, 0);
newDs.FlushCache();
}
newDs.Dispose();
}