通过最近邻居缩放图像字节阵列
本文关键字:图像 字节 阵列 缩放 邻居 最近 | 更新日期: 2023-09-27 18:22:03
我正在尝试使用字节数组缩放图像。我的计划是使用最近的邻居来找到新字节数组的像素数据,但在转换图像的源数据时遇到了一些问题。srcImage的类型是Image,我能够成功地将其转换为字节数组并将其转换回图像,但我在使用其字节数组缩放图像时遇到了问题。我使用MemoryStream(在我的byteArrayToImage方法中)将trgData转换回Image,但我收到一个ArgumentException,告诉我"new 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;
}
您在这里做了一件非常奇怪的事情:
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,即它水平和垂直地复制每个字节scale
次。修改BPP大于1并不困难。
这是一个演示,说明了这两种算法(评论第一行以查看算法的行为)