【发布时间】:2016-02-04 03:15:14
【问题描述】:
我正在尝试调整并保存 Page_load 事件中定义的 3 张图像。
在方法ResizeAndSave 中,我正在尝试两种方法:FastResize 和SlowResize。
当我取消注释 FastResize 代码行时:图像 1 和 2 已正确保存并调整大小。然而,IMAGE 3 以 625x441px 的尺寸保存,因此不尊重我希望它调整大小的 200x200 框。
当我改用 SlowResize 代码行时:图像 1 和 2 再次被正确保存和调整大小。但是,图像 3 根本没有保存。
我的代码中没有错误。我将从各种来源导入图像,因此我的代码适用于各种图像格式至关重要。显然 IMAGE 3 有一些特别之处,我不知道它是什么或如何处理它。
这是我的完整代码,您应该可以复制/粘贴并自己测试:
Imports System.Drawing
Imports System.Drawing.Imaging
Imports System.IO
Imports System.Xml
Imports System.Data.SqlClient
Imports System.Net
Imports System.Windows.Media.Imaging
Imports System.Windows.Media
Partial Class importfeeds
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
'IMAGE 1
ResizeAndSave(200, 200, "https://upload.wikimedia.org/wikipedia/commons/8/82/Dell_Logo.png")
'IMAGE 2
ResizeAndSave(200, 200, "https://upload.wikimedia.org/wikipedia/commons/d/d8/Square-1_solved.jpg")
'IMAGE 3
ResizeAndSave(200, 200, "http://cdn2.emobassets.eu/media/catalog/product/1/1/1116220.jpg")
End Sub
Private Sub ResizeAndSave(ByVal maxWidth As Integer, ByVal maxHeight As Integer, ByVal imageURL As String)
Dim imgRequest As WebRequest = WebRequest.Create(imageURL)
Dim imgResponse As WebResponse = imgRequest.GetResponse()
Dim streamPhoto As Stream = imgResponse.GetResponseStream()
Dim memStream As New MemoryStream
streamPhoto.CopyTo(memStream)
memStream.Position = 0
Dim bfPhoto As BitmapFrame = ReadBitmapFrame(memStream)
Dim newWidth, newHeight As Integer
Dim scaleFactor As Double
If bfPhoto.Width > maxWidth Or bfPhoto.Height > maxHeight Then
If bfPhoto.Width > maxWidth Then
scaleFactor = maxWidth / bfPhoto.Width
newWidth = Math.Round(bfPhoto.Width * scaleFactor, 0)
newHeight = Math.Round(bfPhoto.Height * scaleFactor, 0)
End If
If newHeight > maxHeight Then
scaleFactor = maxHeight / newHeight
newWidth = Math.Round(newWidth * scaleFactor, 0)
newHeight = Math.Round(newHeight * scaleFactor, 0)
End If
End If
Dim bfResize As BitmapFrame = FastResize(bfPhoto, newWidth, newHeight)
'Dim bfResize As BitmapFrame = SlowResize(bfPhoto, newWidth, newHeight, BitmapScalingMode.Linear)
Dim baResize As Byte() = ToByteArray(bfResize)
Dim strThumbnail As String = Guid.NewGuid.ToString() + ".png"
Dim saveToPath As String = Server.MapPath(ConfigurationManager.AppSettings("products_photospath")) + "\49\" + strThumbnail
File.WriteAllBytes(saveToPath, baResize)
End Sub
Private Shared Function FastResize(bfPhoto As BitmapFrame, nWidth As Integer, nHeight As Integer) As BitmapFrame
Dim tbBitmap As New TransformedBitmap(bfPhoto, New ScaleTransform(nWidth / bfPhoto.PixelWidth, nHeight / bfPhoto.PixelHeight, 0, 0))
Return BitmapFrame.Create(tbBitmap)
End Function
'http://weblogs.asp.net/bleroy/resizing-images-from-the-server-using-wpf-wic-instead-of-gdi
Public Shared Function SlowResize(photo As BitmapFrame, width As Integer, height As Integer, scalingMode As BitmapScalingMode) As BitmapFrame
Dim group = New DrawingGroup()
RenderOptions.SetBitmapScalingMode(group, scalingMode)
group.Children.Add(New ImageDrawing(photo, New Windows.Rect(0, 0, width, height)))
Dim targetVisual = New DrawingVisual()
Dim targetContext = targetVisual.RenderOpen()
targetContext.DrawDrawing(group)
Dim target = New RenderTargetBitmap(width, height, 96, 96, PixelFormats.[Default])
targetContext.Close()
target.Render(targetVisual)
Dim targetFrame = BitmapFrame.Create(target)
Return targetFrame
End Function
Private Shared Function ToByteArray(bfResize As BitmapFrame) As Byte()
Using msStream As New MemoryStream()
Dim pbdDecoder As New PngBitmapEncoder()
pbdDecoder.Frames.Add(bfResize)
pbdDecoder.Save(msStream)
Return msStream.ToArray()
End Using
End Function
Private Shared Function ReadBitmapFrame(streamPhoto As Stream) As BitmapFrame
Dim bdDecoder As BitmapDecoder = BitmapDecoder.Create(streamPhoto, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.None)
Return bdDecoder.Frames(0)
End Function
End Class
更新 1
@Hans Passant:您对文件命名和 pixelWidth 使用的建议都很准确,并帮助我在 Page_load 事件中的 3 张图像上成功运行了此代码。
我更新了我的原始代码。
但是,当我将此代码作为实际应用程序的一部分运行时,我会从提要中导入大约 100 张图像。新代码在尝试处理 IMAGE 3 时因内存不足异常而失败。FastResize 和 SlowResize 方法都会发生这种情况。我的代码或相关图像中是否有某些内容会导致内存使用量增加,可能是某处泄漏或我使用的调整大小方法效率低?
我的机器上有很多可用内存,所以如果这是问题所在,我会感到非常惊讶,尽管我确实看到我的 Windows 任务管理器中的 System and compressed memory(至 1.1GB)任务大幅增加。尽管如此,如此多的内存使用会让我相信我的代码有问题。
会是什么?
【问题讨论】:
标签: wpf vb.net image-processing image-resizing