gpt4 book ai didi

c# - UWP/C#中的图像哈希,图像缩放和灰化后水平重复

转载 作者:行者123 更新时间:2023-11-30 21:39:03 25 4
gpt4 key购买 nike

我正在关注 this tutorial关于图像哈希。

到目前为止,我已经取得了以下成就:

代码:

    private async Task<ImageSource> ProcessImageAsync(StorageFile ImageFile)
{
if (ImageFile == null)
throw new ArgumentNullException("ImageFile cannot be null.");

//The new size of processed image.
const int side = 300; //300 is for clarity. Should be 8 or 16 px.

//Initialize bitmap transformations to be applied to the image.
var transform = new BitmapTransform() { ScaledWidth = side, ScaledHeight = side, InterpolationMode = BitmapInterpolationMode.Cubic };

//Get image pixels.
var stream = await ImageFile.OpenStreamForReadAsync();
var decoder = await BitmapDecoder.CreateAsync(stream.AsRandomAccessStream());
var pixelData = await decoder.GetPixelDataAsync(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied, transform, ExifOrientationMode.RespectExifOrientation, ColorManagementMode.ColorManageToSRgb);
var pixels = pixelData.DetachPixelData();

//Initialize writable bitmap.
var wBitmap = new WriteableBitmap((int)decoder.PixelWidth, (int)decoder.PixelHeight);
await wBitmap.SetSourceAsync(stream.AsRandomAccessStream());

//Make it gray
var grayBitmapBuffer = await ConvertToGrayAsync(wBitmap);

//Create a software bitmap from the writable bitmap's pixel buffer.
var sBitmap = SoftwareBitmap.CreateCopyFromBuffer(wBitmap.PixelBuffer, BitmapPixelFormat.Bgra8, side, side, BitmapAlphaMode.Premultiplied);

//Create software bitmap source.
var sBitmapSource = new SoftwareBitmapSource();
await sBitmapSource.SetBitmapAsync(sBitmap);

return sBitmapSource;
}

private async Task<IBuffer> ConvertToGrayAsync(WriteableBitmap srcBitmap)
{
// Get the source bitmap pixels
byte[] srcPixels = new byte[4 * srcBitmap.PixelWidth * srcBitmap.PixelHeight];

using (Stream pixelStream = srcBitmap.PixelBuffer.AsStream())
{
await pixelStream.ReadAsync(srcPixels, 0, srcPixels.Length);
}

// Create a destination bitmap and pixels array
WriteableBitmap dstBitmap = new WriteableBitmap(srcBitmap.PixelWidth, srcBitmap.PixelHeight);
byte[] dstPixels = new byte[4 * dstBitmap.PixelWidth * dstBitmap.PixelHeight];


for (int i = 0; i < srcPixels.Length; i += 4)
{
double b = (double)srcPixels[i] / 255.0;
double g = (double)srcPixels[i + 1] / 255.0;
double r = (double)srcPixels[i + 2] / 255.0;

byte a = srcPixels[i + 3];

double e = (0.21 * r + 0.71 * g + 0.07 * b) * 255;
byte f = Convert.ToByte(e);

dstPixels[i] = f;
dstPixels[i + 1] = f;
dstPixels[i + 2] = f;
dstPixels[i + 3] = a;

}

// Move the pixels into the destination bitmap
using (Stream pixelStream = dstBitmap.PixelBuffer.AsStream())
{
await pixelStream.WriteAsync(dstPixels, 0, dstPixels.Length);
}
dstBitmap.Invalidate();

// Display the new bitmap
return dstBitmap.PixelBuffer;
}

这是用户选择的原始图像: Original image

这是我的代码产生的输出: Processed image

它正在缩放和变灰。但是我不明白为什么图像会水平重复??

这是呈现图像的 XAML 代码:

<Image x:Name="myImage" Stretch="None" />

以及设置图片来源的C#代码:

StorageFile userPickedFile = ...; //code ignored.
myImage.Source = await ProcessImageAsync(userPickedFile);

我做错了什么?处理后的图像看起来有些可疑。我从这里迷路了......我应该如何继续进行哈希处理?有帮助吗?

最佳答案

您的 ConvertToGrayAsync 方法应该只返回转换后的 WriteableBitmap。循环内的像素转换代码也可以简化,并且该方法不需要对源缓冲区和目标缓冲区进行操作。它也可以就地操纵像素值。

private async Task<WriteableBitmap> ConvertToGrayAsync(WriteableBitmap srcBitmap)
{
var pixels = srcBitmap.PixelBuffer.ToArray();

for (int i = 0; i < pixels.Length; i += 4)
{
var b = pixels[i];
var g = pixels[i + 1];
var r = pixels[i + 2];
var f = (byte)(0.21 * r + 0.71 * g + 0.07 * b);
pixels[i] = f;
pixels[i + 1] = f;
pixels[i + 2] = f;
}

var dstBitmap = new WriteableBitmap(srcBitmap.PixelWidth, srcBitmap.PixelHeight);

using (var pixelStream = dstBitmap.PixelBuffer.AsStream())
{
await pixelStream.WriteAsync(pixels, 0, pixels.Length);
}

return dstBitmap;
}

以下方法加载具有预定义大小的 WriteableBitmap:

private async Task<WriteableBitmap> LoadWriteableBitmapAsync(
StorageFile file, int width, int height)
{
using (var fileStream = await file.OpenReadAsync())
using (var memoryStream = new InMemoryRandomAccessStream())
{
var decoder = await BitmapDecoder.CreateAsync(fileStream);
var transform = new BitmapTransform
{
ScaledWidth = (uint)width,
ScaledHeight = (uint)height,
InterpolationMode = BitmapInterpolationMode.Cubic
};
var pixelData = await decoder.GetPixelDataAsync(
BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight, transform,
ExifOrientationMode.RespectExifOrientation,
ColorManagementMode.ColorManageToSRgb);
var pixels = pixelData.DetachPixelData();

var encoder = await BitmapEncoder.CreateAsync(
BitmapEncoder.PngEncoderId, memoryStream);

encoder.SetPixelData(
BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight,
(uint)width, (uint)height, 96, 96, pixels);

await encoder.FlushAsync();
memoryStream.Seek(0);

var bitmap = new WriteableBitmap(width, height);
await bitmap.SetSourceAsync(memoryStream);
return bitmap;
}
}

您的 ProcessImageAsync 方法现在看起来像这样:

private async Task<WriteableBitmap> ProcessImageAsync(
StorageFile file, int width, int height)
{
return await ConvertToGrayAsync(
await LoadWriteableBitmapAsync(file, width, height));
}

关于c# - UWP/C#中的图像哈希,图像缩放和灰化后水平重复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45389909/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com