请求检查基于颜色缩减的图像尺寸压缩VB.NET代码
Issues in Your Image Compression VB.NET Code
Let’s walk through your code step by step to spot problems and show you how to fix them:
Common Issues Across Both Buttons
- Incorrect Variable Declaration: In VB.NET,
Dim a,b,c As Integeronly setscas anInteger—aandbdefault to untypedObjectvariants. This causes unnecessary performance overhead and potential bugs. Always declare each variable explicitly:Dim a As Integer, b As Integer, c As Integer. - Case-Sensitive Color Property Access: .NET’s
Colorclass uses uppercase property names (e.g.,Color.A,Color.R,Color.G,Color.B). Your lowercasea,b,creferences will throw compile errors since those properties don’t exist. - Unmanaged Resource Leaks: You don’t dispose of
BitmaporOpenFileDialogobjects, which can lead to memory leaks over time. Wrap these inUsingstatements to ensure they’re cleaned up automatically. - Slow
GetPixel/SetPixel: These methods are inefficient for large images because they access pixel data one at a time. For better performance, useBitmap.LockBitsto manipulate pixel data directly in memory (we’ll stick withGetPixel/SetPixelin the fixed code for simplicity, but switch toLockBitsfor big images). - JPEG Transparency Limitation: JPEG doesn’t support alpha channels. If your source image has transparency, saving it as JPEG will lose that data—use PNG instead if you need to preserve transparency.
Button2_Click Specific Issues
- Wrong Bitmap Dimensions: You create
bmrwithNew Bitmap(height, height)—this forces both width and height to match the original image’s height, which will stretch or squish the output. It should beNew Bitmap(width, height). - Misused
Color.FromArgbOverload:Color.FromArgb(a,b,c)creates an RGB color with full alpha (255). If you want to preserve the original alpha channel, use the 4-parameter overload:Color.FromArgb(alpha, red, green, blue). Your code also usesbandcwithout mapping to actual color channels (you likely meantR,G, andB). - Redundant Variable Reset: Setting
a = 0 : b = 0 : c = 0at the end of the inner loop is unnecessary—variables are reinitialized each iteration anyway.
Button1_Click Specific Issues
- Incorrect Dimension Calculation: Using floating-point division
(bmp.Width / 2) + 1can lead to wrong dimensions. Use integer division with(bmp.Width + 1) \ 2to get the correct rounded-up width for 2x2 pixel averaging. - Truncated Loop Range:
For i = 0 To wid - 2skips the last pixel in the width dimension. Change this toFor i = 0 To wid - 1to process all pixels in the new bitmap. - Unused Variable:
imgSourceis declared but never used—remove it to clean up your code. - Invalid Color Channel Averaging: Your code averages
cc.a,cc.b, andcc.c(invalid properties) instead of the actualcc.R,cc.G,cc.B(andcc.Aif you want to preserve alpha).
Fixed Code Example
Here’s the revised code with all issues addressed, plus JPEG quality control and edge-case handling:
Imports System.Drawing.Imaging Imports System.Math Public Class Form1 Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click Using ofd As New OpenFileDialog() If ofd.ShowDialog() = DialogResult.OK Then Using bmp As New Bitmap(ofd.FileName) PictureBox.Image = bmp.Clone() ' Clone to avoid locking the original file Dim width As Integer = bmp.Width Dim height As Integer = bmp.Height Using bmr As New Bitmap(width, height) For i = 0 To width - 1 For j = 0 To height - 1 Dim originalColor As Color = bmp.GetPixel(i, j) ' Halve each color channel (integer division for performance) Dim newAlpha As Integer = originalColor.A \ 2 Dim newRed As Integer = originalColor.R \ 2 Dim newGreen As Integer = originalColor.G \ 2 Dim newBlue As Integer = originalColor.B \ 2 ' Preserve alpha with 4-parameter overload bmr.SetPixel(i, j, Color.FromArgb(newAlpha, newRed, newGreen, newBlue)) Next Next PictureBox2.Image = bmr.Clone() ' Save with custom JPEG quality (adjust 70 to balance size/quality, 0-100) Dim jpegParams As New EncoderParameters(1) jpegParams.Param(0) = New EncoderParameter(Encoder.Quality, 70L) bmr.Save("image2.jpg", GetEncoder(ImageFormat.Jpeg), jpegParams) End Using End Using End If End Using End Sub Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Using ofd As New OpenFileDialog() If ofd.ShowDialog() = DialogResult.OK Then Using bmp As New Bitmap(ofd.FileName) PictureBox.Image = bmp.Clone() ' Correct dimension calculation for 2x2 pixel averaging Dim wid As Integer = (bmp.Width + 1) \ 2 Dim hgt As Integer = (bmp.Height + 1) \ 2 Using bmr As New Bitmap(wid, hgt) For i = 0 To wid - 1 For j = 0 To hgt - 1 Dim totalAlpha As Integer = 0 Dim totalRed As Integer = 0 Dim totalGreen As Integer = 0 Dim totalBlue As Integer = 0 Dim pixelCount As Integer = 0 ' Handle edge cases where original image has odd dimensions For x = 0 To 1 Dim originalX As Integer = i * 2 + x If originalX >= bmp.Width Then Continue For For y = 0 To 1 Dim originalY As Integer = j * 2 + y If originalY >= bmp.Height Then Continue For Dim pixelColor As Color = bmp.GetPixel(originalX, originalY) totalAlpha += pixelColor.A totalRed += pixelColor.R totalGreen += pixelColor.G totalBlue += pixelColor.B pixelCount += 1 Next Next ' Calculate averages (avoid division by zero) Dim avgAlpha As Integer = If(pixelCount > 0, totalAlpha \ pixelCount, 0) Dim avgRed As Integer = If(pixelCount > 0, totalRed \ pixelCount, 0) Dim avgGreen As Integer = If(pixelCount > 0, totalGreen \ pixelCount, 0) Dim avgBlue As Integer = If(pixelCount > 0, totalBlue \ pixelCount, 0) bmr.SetPixel(i, j, Color.FromArgb(avgAlpha, avgRed, avgGreen, avgBlue)) Next Next PictureBox1.Image = bmr.Clone() ' Save with custom JPEG quality Dim jpegParams As New EncoderParameters(1) jpegParams.Param(0) = New EncoderParameter(Encoder.Quality, 70L) bmr.Save("test.jpg", GetEncoder(ImageFormat.Jpeg), jpegParams) End Using End Using End If End Using End Sub ' Helper method to get JPEG encoder for quality settings Private Function GetEncoder(format As ImageFormat) As ImageCodecInfo Dim codecs As ImageCodecInfo() = ImageCodecInfo.GetImageDecoders() For Each codec As ImageCodecInfo In codecs If codec.FormatID = format.Guid Then Return codec End If Next Return Nothing End Function End Class
Additional Notes
- The
GetEncoderhelper lets you adjust JPEG compression quality to balance file size and image clarity. - We use
Clone()when assigning toPictureBox.Imageto avoid locking the original file (so you can overwrite it later without errors). - The 2x2 averaging code now handles odd-sized images correctly, so it never tries to access pixels outside the original bitmap’s bounds.
内容的提问来源于stack exchange,提问作者Ammar Mohammed
相关产品推荐
相关产品推荐

