通过最近邻扩展图像字节数组

时间:2014-09-16 21:39:00

标签: c# arrays image image-scaling nearest-neighbor

我正在尝试使用字节数组来缩放图像。我的计划是使用最近的邻居来查找新字节数组的像素数据,但是我在转换图像的源数据时遇到了一些问题。 srcImage是Image类型,我能够成功地将其转换为字节数组并将其转换回图像,我遇到了使用其字节数组缩放该图像的问题。我使用MemoryStream(在我的byteArrayToImage方法中)将trgData转换回Image但我收到一个ArguementException告诉我新的MemoryStream(byteArray)'参数无效。

有没有人碰巧知道可能是什么问题或者如何从图像中正确地缩放字节数组?目前,我们可以假设我只是缩放和保存png文件,但我想最终将其扩展为其他图像格式。

以下是我复制和缩放图像数据的代码:

byte[] srcData = ImageToByteArraybyImageConverter(srcImage);

// data transformations here
//
float srcRatio = srcImage.Width / srcImage.Height;
int bitsPerPixel = ((int)srcImage.PixelFormat & 0xff00) >> 8;
int bytesPerPixel = (bitsPerPixel + 7) / 8;
int srcStride = 4 * ((srcImage.Width * bytesPerPixel + 3) / 4);

// find max scale value
int scale = 3; // NOTE: temporary

// create new byte array to store new image
int width = srcImage.Width * scale;
int height = srcImage.Height * scale;
int stride = width;
byte[] trgData = new byte[height * stride];

// update the progress bar
progressBar1.Value = 10;

int i = -1; // index for src data
// copy pixel data 
for (int n = 0; n < trgData.Length; n++)
{
    if (n % stride == 0)
    {
        i++;
    }
    trgData[n] = srcData[i];
}

progressBar1.Value = 60;

// convert the pixel data to image
Image newImage = byteArrayToImage(trgData);
progressBar1.Value = 70;
if (newImage != null)
{
    // save the image to disk
    newImage.Save(newFileName);
    progressBar1.Value = 100;
}

如果您有任何疑问,请告诉我,谢谢!

编辑:以下是加载和保存字节数组的方法

private byte[] ImageToByteArraybyImageConverter(System.Drawing.Image image)
{
    ImageConverter imageConverter = new ImageConverter();
    byte[] imageByte = (byte[])imageConverter.ConvertTo(image, typeof(byte[]));
    return imageByte;
}


private Image byteArrayToImage(byte[] byteArrayIn)
{
    Image returnImage = null;
    using (MemoryStream ms = new MemoryStream(byteArrayIn))
    {
        returnImage = Image.FromStream(ms);
    }
    return returnImage;
}

1 个答案:

答案 0 :(得分:1)

你在这里做了一件非常奇怪的事情:

int i = -1; // index for src data
// copy pixel data 
for (int n = 0; n < trgData.Length; n++)
{
    if (n % stride == 0)
    {
        i++;
    }
    trgData[n] = srcData[i];
}

每次width次迭代后(因为stride == width),您都会增加原始索引。也就是说,新图像的整个第一行将填充原始图像的第一个字节,第二行 - 第二个字节等。

请改为尝试:

int targetIdx = 0;
for (int i = 0; i < height; ++i)
{
    int iUnscaled = i / scale;
    for (int j = 0; j < width; ++j) {
        int jUnscaled = j / scale;
        trgData[targetIdx++] = srcData[iUnscaled * origWidth + jUnscaled];
    }
}

请注意,它假设BPP = 1,即水平和垂直复制evey字节scale次。为BPP修改它不难超过1。

Here is a demo说明了两种算法(注释第一行以了解算法的行为)