Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用10位深度的数字图像_C#_Image Processing - Fatal编程技术网

C# 使用10位深度的数字图像

C# 使用10位深度的数字图像,c#,image-processing,C#,Image Processing,在像素深度为10位的情况下,如何使用c#(读取每个像素的值)处理和提取图像数据 此外,图像有4个波段(R、G、B和NIR) 谢谢。 < P> C++中的代码不在C中,所以你需要输入我的代码…< /P> 您应该添加像素组成(每个频带的位数及其顺序) 你写了10位每像素和R,G,B,NIR(我假设近红外)波段 您未指定像素格式 因此,我将创建一个,您必须将其更改为您的案例 bit: |9 8 7 6 5 4 3 2 1 0| band: | R | G | B | NIR | R-2位

在像素深度为10位的情况下,如何使用c#(读取每个像素的值)处理和提取图像数据

此外,图像有4个波段(R、G、B和NIR)

谢谢。

< P> C++中的代码不在C中,所以你需要输入我的代码…< /P> 您应该添加像素组成(每个频带的位数及其顺序)

  • 你写了10位每像素和R,G,B,NIR(我假设近红外)波段
  • 您未指定像素格式
  • 因此,我将创建一个,您必须将其更改为您的案例

     bit: |9 8 7 6 5 4 3 2 1 0|
    band: | R |  G  | B | NIR |
    
  • R-2位

  • G-3位
  • B-2位
  • 近红外-3位
现在如何使用它

  • 我会将其转换为更易于管理的位大小(例如,每个频带4位)
  • 所以我可以使用标准数据类型
  • 完成处理后,只需将其转换回10位像素格式
现在4*10=40和40/8=5,这意味着每4个像素与5个字节对齐(LCM(10,8))

  • 假设这符合你的形象

    int xs,ys; // resolution
    int siz;   // BYTE size of whole image data ... siz = ceil(xs*ys*10/8)
    BYTE *dat=new BYTE[siz+5]; // 10bit image data
    
  • 那么现在如何从5个字节中读取4个像素,并将其转换为更多字节对齐的内容

  • 数据布局如下所示:

    |    0    |    1    |    2     |    3     |    4   | // BYTE
    |rrgggbbn|nn rrgggb|bnnn rrgg|gbbnnn rr|gggbbnnn|
    |      0     |       1    |      2     |     3     | // Pixel
    
    void convert10to16 (BYTE *dst,BYTE *src)
     {
     int i=0,o=0;
     BYTE in,out;
    
     in=scr[i]; i++;    // rrgggbbn
     out =(in>>2)&0x30; // 00rr0000
     out|=(in>>3)&0x07; // 00rr0ggg
     dst[o]=out; o++;
     out =(in<<3)&0x30; // 00bb0000
     out|=(in<<2)&0x04; // 00bb0n00
    
     in=scr[i]; i++;    // nnrrgggb
     out|=(in>>6)&0x03; // 00bb0nnn
     dst[o]=out; o++;
     out =(in   )&0x30; // 00rr0000
     out|=(in>>1)&0x07; // 00rr0ggg
     dst[o]=out; o++;
     out =(in<<5)&0x20; // 00b00000
    
     in=scr[i]; i++;    // bnnnrrgg
     out|=(in>>3)&0x10; // 00bb0000
     out|=(in>>4)&0x07; // 00bb0nnn
     dst[o]=out; o++;
     out =(in<<2)&0x30; // 00rr0000
     out|=(in<<1)&0x06; // 00rr0gg0
    
     in=scr[i]; i++;    // gbbnnnrr
     out|=(in>>7)&0x01; // 00rr0ggg
     dst[o]=out; o++;
     out =(in>>1)&0x30; // 00bb0000
     out|=(in>>2)&0x07; // 00bb0nnn
     dst[o]=out; o++;
     out =(in<<4)&0x30; // 00rr0000
    
     in=scr[i]; i++;    // gggbbnnn
     out|=(in>>5)&0x07; // 00rr0ggg
     dst[o]=out; o++;
     out =(in<<1)&0x30; // 00bb0000
     out|=(in   )&0x07; // 00bb0nnn
     dst[o]=out; o++;
     }
    
  • 首先选择与字节对齐的新像素格式

     bit: |15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0|
    band: |      R     |    G    |    B  |  NIR  | // all bands are 4 bits
    
  • 我会像这样转换像素格式:

    |    0    |    1    |    2     |    3     |    4   | // BYTE
    |rrgggbbn|nn rrgggb|bnnn rrgg|gbbnnn rr|gggbbnnn|
    |      0     |       1    |      2     |     3     | // Pixel
    
    void convert10to16 (BYTE *dst,BYTE *src)
     {
     int i=0,o=0;
     BYTE in,out;
    
     in=scr[i]; i++;    // rrgggbbn
     out =(in>>2)&0x30; // 00rr0000
     out|=(in>>3)&0x07; // 00rr0ggg
     dst[o]=out; o++;
     out =(in<<3)&0x30; // 00bb0000
     out|=(in<<2)&0x04; // 00bb0n00
    
     in=scr[i]; i++;    // nnrrgggb
     out|=(in>>6)&0x03; // 00bb0nnn
     dst[o]=out; o++;
     out =(in   )&0x30; // 00rr0000
     out|=(in>>1)&0x07; // 00rr0ggg
     dst[o]=out; o++;
     out =(in<<5)&0x20; // 00b00000
    
     in=scr[i]; i++;    // bnnnrrgg
     out|=(in>>3)&0x10; // 00bb0000
     out|=(in>>4)&0x07; // 00bb0nnn
     dst[o]=out; o++;
     out =(in<<2)&0x30; // 00rr0000
     out|=(in<<1)&0x06; // 00rr0gg0
    
     in=scr[i]; i++;    // gbbnnnrr
     out|=(in>>7)&0x01; // 00rr0ggg
     dst[o]=out; o++;
     out =(in>>1)&0x30; // 00bb0000
     out|=(in>>2)&0x07; // 00bb0nnn
     dst[o]=out; o++;
     out =(in<<4)&0x30; // 00rr0000
    
     in=scr[i]; i++;    // gggbbnnn
     out|=(in>>5)&0x07; // 00rr0ggg
     dst[o]=out; o++;
     out =(in<<1)&0x30; // 00bb0000
     out|=(in   )&0x07; // 00bb0nnn
     dst[o]=out; o++;
     }
    
    void convert10to16(字节*dst,字节*src)
    {
    int i=0,o=0;
    字节输入,字节输出;
    in=scr[i];i++;//rrgggbbn
    out=(in>>2)&0x30;//00rr0000
    out |=(in>>3)&0x07;//00rr0ggg
    dst[o]=out;o++;
    out=(in1)&0x07;//00rr0ggg
    dst[o]=out;o++;
    out=(in3)&0x10;//00bb0000
    out |=(in>>4)&0x07;//00bb0nnn
    dst[o]=out;o++;
    out=(in1)&0x30;//00bb0000
    out |=(in>>2)&0x07;//00bb0nnn
    dst[o]=out;o++;
    out=(in5)&0x07;//00rr0ggg
    dst[o]=out;o++;
    out=(in我从的代码中得到启发,编写了这个类,根据数组中每个颜色分量的位长度和位位置自动转换颜色:

    /// <summary>
    /// Class to automate the unpacking (and packing/writing) of RGB(A) colours in colour formats with packed bits.
    /// Inspired by https://github.com/scummvm/scummvm/blob/master/graphics/pixelformat.h
    /// This class works slightly differently than the ScummVM version, using 4-entry arrays for all data, with each entry
    /// representing one of the colour components, so the code can easily loop over them and perform the same action on each one.
    /// </summary>
    public class PixelFormatter
    {
        /// <summary>Standard PixelFormatter for .Net's RGBA format.</summary>
        public static PixelFormatter Format32BitArgb = new PixelFormatter(4, 8, 16, 8, 8, 8, 0, 8, 24, true);
    
        /// <summary>Number of bytes to read per pixel.</summary>
        private Byte bytesPerPixel;
        /// <summary>Amount of bits for each component (R,G,B,A)</summary>
        private Byte[] bitsAmounts = new Byte[4];
        /// <summary>Amount of bits to shift for each component (R,G,B,A)</summary>
        private Byte[] shiftAmounts = new Byte[4];
        /// <summary>Masks to limit the amount of bits for each component, derived from the bitsAmounts.</summary>
        private UInt32[] limitMasks = new UInt32[4];
        /// <summary>Multiplier for each component (R,G,B,A). If not explicitly given this can be derived from the number of bits.</summary>
        private Double[] multipliers = new Double[4];
        /// <summary>Defaults for for each component (R,G,B,A)</summary>
        private Byte[] defaults = new Byte[] { 0, 0, 0, 255 };
        /// <summary>True to read the input bytes as little-endian.</summary>
        private Boolean littleEndian;
    
        /// <summary>The colour components. Though most stuff will just loop an int from 0 to 4, this shows the order.</summary>
        private enum ColorComponent
        {
            Red = 0,
            Green = 1,
            Blue = 2,
            Alpha = 3
        }
    
        /// <summary>
        /// Creats a new PixelFormatter, with automatic calculation of colour multipliers using the CalculateMultiplier function.
        /// </summary>
        /// <param name="bytesPerPixel">Amount of bytes to read per pixel</param>
        /// <param name="redBits">Amount of bits to read for the red colour component</param>
        /// <param name="redShift">Amount of bits to shift the data to get to the red colour component</param>
        /// <param name="greenBits">Amount of bits to read for the green colour component</param>
        /// <param name="greenShift">Amount of bits to shift the data to get to the green colour component</param>
        /// <param name="blueBits">Amount of bits to read for the blue colour component</param>
        /// <param name="blueShift">Amount of bits to shift the data to get to the blue colour component</param>
        /// <param name="alphaBits">Amount of bits to read for the alpha colour component</param>
        /// <param name="alphaShift">Amount of bits to shift the data to get to the alpha colour component</param>
        /// <param name="littleEndian">True if the read bytes are interpreted as little-endian.</param>
        public PixelFormatter(Byte bytesPerPixel, Byte redBits, Byte redShift, Byte greenBits, Byte greenShift,
            Byte blueBits, Byte blueShift, Byte alphaBits, Byte alphaShift, Boolean littleEndian)
            : this(bytesPerPixel,
                redBits, redShift, CalculateMultiplier(redBits),
                greenBits, greenShift, CalculateMultiplier(greenBits),
                blueBits, blueShift, CalculateMultiplier(blueBits),
                alphaBits, alphaShift, CalculateMultiplier(alphaBits), littleEndian)
        { }
    
        /// <summary>
        /// Creates a new PixelFormatter.
        /// </summary>
        /// <param name="bytesPerPixel">Amount of bytes to read per pixel</param>
        /// <param name="redBits">Amount of bits to read for the red colour component</param>
        /// <param name="redShift">Amount of bits to shift the data to get to the red colour component</param>
        /// <param name="redMultiplier">Multiplier for the red component's value to adjust it to the normal 0-255 range.</param>
        /// <param name="greenBits">Amount of bits to read for the green colour component</param>
        /// <param name="greenShift">Amount of bits to shift the data to get to the green colour component</param>
        /// <param name="greenMultiplier">Multiplier for the green component's value to adjust it to the normal 0-255 range.</param>
        /// <param name="blueBits">Amount of bits to read for the blue colour component</param>
        /// <param name="blueShift">Amount of bits to shift the data to get to the blue colour component</param>
        /// <param name="blueMultiplier">Multiplier for the blue component's value to adjust it to the normal 0-255 range.</param>
        /// <param name="alphaBits">Amount of bits to read for the alpha colour component</param>
        /// <param name="alphaShift">Amount of bits to shift the data to get to the alpha colour component</param>
        /// <param name="alphaMultiplier">Multiplier for the alpha component's value to adjust it to the normal 0-255 range.</param>
        /// <param name="littleEndian">True if the read bytes are interpreted as little-endian.</param>
        public PixelFormatter(Byte bytesPerPixel, Byte redBits, Byte redShift, Double redMultiplier,
            Byte greenBits, Byte greenShift, Double greenMultiplier,
            Byte blueBits, Byte blueShift, Double blueMultiplier,
            Byte alphaBits, Byte alphaShift, Double alphaMultiplier, Boolean littleEndian)
        {
            this.bytesPerPixel = bytesPerPixel;
            this.littleEndian = littleEndian;
            this.bitsAmounts [(Int32)ColorComponent.Red] = redBits;
            this.shiftAmounts[(Int32)ColorComponent.Red] = redShift;
            this.multipliers [(Int32)ColorComponent.Red] = redMultiplier;
            this.limitMasks[(Int32)ColorComponent.Red] = GetLimitMask(redBits, redShift);
    
            this.bitsAmounts [(Int32)ColorComponent.Green] = greenBits;
            this.shiftAmounts[(Int32)ColorComponent.Green] = greenShift;
            this.multipliers [(Int32)ColorComponent.Green] = greenMultiplier;
            this.limitMasks[(Int32)ColorComponent.Green] = GetLimitMask(greenBits, greenShift);
    
            this.bitsAmounts [(Int32)ColorComponent.Blue] = blueBits;
            this.shiftAmounts[(Int32)ColorComponent.Blue] = blueShift;
            this.multipliers [(Int32)ColorComponent.Blue] = blueMultiplier;
            this.limitMasks[(Int32)ColorComponent.Blue] = GetLimitMask(blueBits, blueShift);
    
            this.bitsAmounts [(Int32)ColorComponent.Alpha] = alphaBits;
            this.shiftAmounts[(Int32)ColorComponent.Alpha] = alphaShift;
            this.multipliers [(Int32)ColorComponent.Alpha] = alphaMultiplier;
            this.limitMasks[(Int32)ColorComponent.Alpha] = GetLimitMask(alphaBits, alphaShift);
        }
    
        private static UInt32 GetLimitMask(Byte bpp, Byte shift)
        {
            return (UInt32)(((1 << bpp) - 1) << shift);
        }
    
        /// <summary>
        /// Using this multiplier instead of a basic int ensures a true uniform distribution of values of this bits length over the 0-255 range.
        /// </summary>
        /// <param name="colorComponentBitLength">Bits length of the color component</param>
        /// <returns>The most correct multiplier to convert colour components of the given bits length to a 0-255 range.</returns>
        public static Double CalculateMultiplier(Byte colorComponentBitLength)
        {
            return 255.0 / ((1 << colorComponentBitLength) - 1);
        }
    
        public Color GetColor(Byte[] data, Int32 offset)
        {
    
            UInt32 value = ArrayUtils.ReadIntFromByteArray(data, offset, this.bytesPerPixel, this.littleEndian);
            return GetColorFromValue(value);
        }
    
    
        public void WriteColor(Byte[] data, Int32 offset, Color color)
        {
            UInt32 value = GetValueFromColor(color);
            ArrayUtils.WriteIntToByteArray(data, offset, this.bytesPerPixel, this.littleEndian, value);
        }
    
        public Color GetColorFromValue(UInt32 readValue)
        {
            Byte[] components = new Byte[4];
            for (Int32 i = 0; i < 4; i++)
            {
                if (bitsAmounts[i] == 0)
                    components[i] = defaults[i];
                else
                    components[i] = GetChannelFromValue(readValue, (ColorComponent)i);
            }
            return Color.FromArgb(components[(Int32)ColorComponent.Alpha],
                                  components[(Int32)ColorComponent.Red],
                                  components[(Int32)ColorComponent.Green],
                                  components[(Int32)ColorComponent.Blue]);
        }
    
        private Byte GetChannelFromValue(UInt32 readValue, ColorComponent type)
        {
            UInt32 val = (UInt32)(readValue & limitMasks[(Int32)type]);
            val = (UInt32)(val >> this.shiftAmounts[(Int32)type]);
            Double valD = (Double)(val * multipliers[(Int32)type]);
            return (Byte)Math.Min(255, Math.Round(valD, MidpointRounding.AwayFromZero));
        }
    
        public UInt32 GetValueFromColor(Color color)
        {
            Byte[] components = new Byte[] { color.R, color.G, color.B, color.A};
            UInt32 val = 0;
            for (Int32 i = 0; i < 4; i++)
            {
                UInt32 mask = (UInt32)((1 << bitsAmounts[i]) - 1);
                Double tempValD = (Double)components[i] / this.multipliers[i];
                UInt32 tempVal = (Byte)Math.Min(mask, Math.Round(tempValD, MidpointRounding.AwayFromZero));
                tempVal = (UInt32)(tempVal << this.shiftAmounts[i]);
                val |= tempVal;
            }
            return val;
        }
    }
    
    不过,现在获取颜色值的实际方法比我在示例解码注释中使用的简单*8更为精确;
    CalculateMultiplier
    函数负责获取0-255范围内的均匀分布值。不过,如果您想使用简单的方法(可能会在转换过程中导致较小的舍入错误)可以使用更复杂的构造函数手动给出所有乘数

    最后的字节然后被插入到新创建的32位映像中,用于访问和写入映像的底层字节

    哦,下面是我的
    ArrayUtils
    类中提到的
    readintfromtearray
    WriteIntToByteArray

    public static UInt32 ReadIntFromByteArray(Byte[] data, Int32 startIndex, Int32 bytes, Boolean littleEndian)
    {
        Int32 lastByte = bytes - 1;
        if (data.Length < startIndex + bytes)
            throw new ArgumentOutOfRangeException("startIndex", "Data array is too small to write a " + bytes + "-byte value at offset" + startIndex + ".");
        UInt32 value = 0;
        for (Int32 index = 0; index < bytes; index++)
        {
            Int32 offs = startIndex + (littleEndian ? index : lastByte - index);
            value += (UInt32)(data[offs] << (8 * index));
        }
        return value;
    }
    
    public static void WriteIntToByteArray(Byte[] data, Int32 startIndex, Int32 bytes, Boolean littleEndian, UInt32 value)
    {
        Int32 lastByte = bytes - 1;
        if (data.Length < startIndex + bytes)
            throw new ArgumentOutOfRangeException("startIndex", "Data array is too small to write a " + bytes + "-byte value at offset" + startIndex + ".");
        for (Int32 index = 0; index < bytes; index++)
        {
            Int32 offs = startIndex + (littleEndian ? index : lastByte - index);
            data[offs] = (Byte)(value >> (8 * index) & 0xFF);
        }
    }
    
    public static UInt32 ReadIntFromByteArray(字节[]数据、Int32 startIndex、Int32字节、布尔littleEndian)
    {
    Int32 lastByte=字节-1;
    if(data.Length(8*索引)和0xFF);
    }
    }
    
    最有可能是这样。如果您的问题实际上是“如何?”,您可能希望解释“处理和提取”的含义,并展示您的尝试。是的,问题应该是“如何”我已经编辑过这篇文章,用于访问MrSID文件?