调整图像大小并保存图像,同时保留元数据
我正在尝试调整图像大小并保存图像,这相当简单(例如,查看此示例外部示例不再有效)。
但是,使用此代码会从图像中剥离元数据信息。我似乎不太清楚如何保留 jpeg 图像的元数据。
编辑:示例代码
public static void ResizeMethodThree(string sourceFile, string targetFile)
{
byte[] baSource = File.ReadAllBytes(sourceFile);
PropertyItem[] propertyItems = new Bitmap(sourceFile).PropertyItems;
using (Stream streamPhoto = new MemoryStream(baSource))
{
BitmapFrame bfPhoto = ReadBitmapFrame(streamPhoto);
BitmapMetadata metaData = (BitmapMetadata)bfPhoto.Metadata;
int nNewPictureSize = 200;
int nWidth = 0;
int nHeight = 0;
if (bfPhoto.Width > bfPhoto.Height)
{
nWidth = nNewPictureSize;
nHeight = (int)(bfPhoto.Height * nNewPictureSize / bfPhoto.Width);
}
else
{
nHeight = nNewPictureSize;
nWidth = (int)(bfPhoto.Width * nNewPictureSize / bfPhoto.Height);
}
BitmapFrame bfResize = ResizeHelper(bfPhoto, nWidth, nHeight, BitmapScalingMode.HighQuality);
byte[] baResize = ToByteArray(bfResize);
File.WriteAllBytes(targetFile, baResize);
Image targetImage = new Bitmap(targetFile);
foreach (var propertyItem in propertyItems)
{
targetImage.SetPropertyItem(propertyItem);
}
targetImage.Save(targetFile);
}
}
public static BitmapFrame ResizeHelper(BitmapFrame photo, int width,
int height, BitmapScalingMode scalingMode)
{
var group = new DrawingGroup();
RenderOptions.SetBitmapScalingMode(
group, scalingMode);
group.Children.Add(
new ImageDrawing(photo,
new Rect(0, 0, width, height)));
var targetVisual = new DrawingVisual();
var targetContext = targetVisual.RenderOpen();
targetContext.DrawDrawing(group);
var target = new RenderTargetBitmap(
width, height, 96, 96, PixelFormats.Default);
targetContext.Close();
target.Render(targetVisual);
var targetFrame = BitmapFrame.Create(target);
return targetFrame;
}
private static byte[] ToByteArray(BitmapFrame bfResize)
{
using (MemoryStream msStream = new MemoryStream())
{
JpegBitmapEncoder jpgEncoder = new JpegBitmapEncoder();
jpgEncoder.Frames.Add(bfResize);
jpgEncoder.Save(msStream);
return msStream.ToArray();
}
}
private static BitmapFrame ReadBitmapFrame(Stream streamPhoto)
{
BitmapDecoder bdDecoder =
BitmapDecoder.Create(streamPhoto, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.None);
return bdDecoder.Frames[0];
}
I am attempting to resize and save an image, which is fairly easy (for instance, see this example external example no longer valid).
However, using this code strips the metadata information from the image. I can't quite seem to figure out how to preserve the metadata for a jpeg image.
EDIT: Example Code
public static void ResizeMethodThree(string sourceFile, string targetFile)
{
byte[] baSource = File.ReadAllBytes(sourceFile);
PropertyItem[] propertyItems = new Bitmap(sourceFile).PropertyItems;
using (Stream streamPhoto = new MemoryStream(baSource))
{
BitmapFrame bfPhoto = ReadBitmapFrame(streamPhoto);
BitmapMetadata metaData = (BitmapMetadata)bfPhoto.Metadata;
int nNewPictureSize = 200;
int nWidth = 0;
int nHeight = 0;
if (bfPhoto.Width > bfPhoto.Height)
{
nWidth = nNewPictureSize;
nHeight = (int)(bfPhoto.Height * nNewPictureSize / bfPhoto.Width);
}
else
{
nHeight = nNewPictureSize;
nWidth = (int)(bfPhoto.Width * nNewPictureSize / bfPhoto.Height);
}
BitmapFrame bfResize = ResizeHelper(bfPhoto, nWidth, nHeight, BitmapScalingMode.HighQuality);
byte[] baResize = ToByteArray(bfResize);
File.WriteAllBytes(targetFile, baResize);
Image targetImage = new Bitmap(targetFile);
foreach (var propertyItem in propertyItems)
{
targetImage.SetPropertyItem(propertyItem);
}
targetImage.Save(targetFile);
}
}
public static BitmapFrame ResizeHelper(BitmapFrame photo, int width,
int height, BitmapScalingMode scalingMode)
{
var group = new DrawingGroup();
RenderOptions.SetBitmapScalingMode(
group, scalingMode);
group.Children.Add(
new ImageDrawing(photo,
new Rect(0, 0, width, height)));
var targetVisual = new DrawingVisual();
var targetContext = targetVisual.RenderOpen();
targetContext.DrawDrawing(group);
var target = new RenderTargetBitmap(
width, height, 96, 96, PixelFormats.Default);
targetContext.Close();
target.Render(targetVisual);
var targetFrame = BitmapFrame.Create(target);
return targetFrame;
}
private static byte[] ToByteArray(BitmapFrame bfResize)
{
using (MemoryStream msStream = new MemoryStream())
{
JpegBitmapEncoder jpgEncoder = new JpegBitmapEncoder();
jpgEncoder.Frames.Add(bfResize);
jpgEncoder.Save(msStream);
return msStream.ToArray();
}
}
private static BitmapFrame ReadBitmapFrame(Stream streamPhoto)
{
BitmapDecoder bdDecoder =
BitmapDecoder.Create(streamPhoto, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.None);
return bdDecoder.Frames[0];
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
使用源图像上的 Image.PropertyItems 属性来获取元数据项的列表。循环列表,在目标图像上调用 Image.SetPropertyItem。通常应避免调整 jpeg 图像的大小和重新压缩,使用未压缩的原始图像最好保持质量并避免伪影。
Use the Image.PropertyItems property on the source image to get the list of metadata items. Loop through the list, calling Image.SetPropertyItem on the destination image. You should normally avoid resizing and re-compressing a jpeg image, working from an uncompressed original is best to maintain quality and avoid artifacts.