Automated Image Enhancement Tool for Low-Quality Photographs C#
👤 Sharing: AI
```csharp
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
namespace ImageEnhancementTool
{
public class ImageEnhancer
{
/// <summary>
/// Enhances an image loaded from the specified file path.
/// </summary>
/// <param name="imagePath">The path to the image file.</param>
/// <param name="brightnessAdjustment">Brightness adjustment value (e.g., 20 for brighter, -20 for darker).</param>
/// <param name="contrastAdjustment">Contrast adjustment value (e.g., 0.1 for increased contrast, -0.1 for decreased contrast).</param>
/// <param name="sharpeningAmount">Sharpening amount (e.g., 0.2 for moderate sharpening).</param>
/// <returns>The enhanced image as a Bitmap, or null if an error occurred.</returns>
public Bitmap EnhanceImage(string imagePath, int brightnessAdjustment = 0, double contrastAdjustment = 0, double sharpeningAmount = 0)
{
try
{
// Load the image
Bitmap originalImage = new Bitmap(imagePath);
// Apply enhancements
Bitmap enhancedImage = AdjustBrightnessAndContrast(originalImage, brightnessAdjustment, contrastAdjustment);
enhancedImage = SharpenImage(enhancedImage, sharpeningAmount);
return enhancedImage;
}
catch (Exception ex)
{
Console.WriteLine($"Error enhancing image: {ex.Message}");
return null; // Or handle the error in another appropriate way
}
}
/// <summary>
/// Adjusts the brightness and contrast of a Bitmap.
/// </summary>
/// <param name="image">The input Bitmap.</param>
/// <param name="brightness">Brightness adjustment value.</param>
/// <param name="contrast">Contrast adjustment value.</param>
/// <returns>A new Bitmap with adjusted brightness and contrast.</returns>
private Bitmap AdjustBrightnessAndContrast(Bitmap image, int brightness, double contrast)
{
// Create a copy of the original image for modification
Bitmap adjustedImage = new Bitmap(image.Width, image.Height);
// Lock the bitmap data for faster pixel access
BitmapData bmpData = adjustedImage.LockBits(new Rectangle(0, 0, adjustedImage.Width, adjustedImage.Height), ImageLockMode.ReadWrite, adjustedImage.PixelFormat);
// Get the address of the first line
IntPtr ptr = bmpData.Scan0;
// Calculate the number of bytes
int bytes = Math.Abs(bmpData.Stride) * adjustedImage.Height;
byte[] rgbValues = new byte[bytes];
// Copy the RGB values into the array.
System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);
// Apply brightness and contrast adjustments
double factor = (100.0 + contrast) / 100.0;
factor *= factor; // Square to enhance contrast effect
for (int i = 0; i < rgbValues.Length; i += 4)
{
// Extract the color components (BGRA format)
double blue = (double)rgbValues[i];
double green = (double)rgbValues[i + 1];
double red = (double)rgbValues[i + 2];
// Apply brightness and contrast adjustments
red = (factor * (red / 255.0 - 0.5) + 0.5) * 255.0 + brightness;
green = (factor * (green / 255.0 - 0.5) + 0.5) * 255.0 + brightness;
blue = (factor * (blue / 255.0 - 0.5) + 0.5) * 255.0 + brightness;
// Clamp values to the valid range [0, 255]
red = Math.Max(0, Math.Min(255, red));
green = Math.Max(0, Math.Min(255, green));
blue = Math.Max(0, Math.Min(255, blue));
// Update the RGB values in the array
rgbValues[i] = (byte)blue;
rgbValues[i + 1] = (byte)green;
rgbValues[i + 2] = (byte)red;
}
// Copy the RGB values back to the bitmap
System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);
// Unlock the bits
adjustedImage.UnlockBits(bmpData);
return adjustedImage;
}
/// <summary>
/// Sharpens an image using a simple convolution kernel.
/// </summary>
/// <param name="image">The input image.</param>
/// <param name="amount">The amount of sharpening to apply (e.g., 0.2).</param>
/// <returns>A new Bitmap with sharpened image.</returns>
private Bitmap SharpenImage(Bitmap image, double amount)
{
if (amount <= 0) return image;
// Define the sharpening kernel (Laplacian)
double[,] kernel = {
{ -amount / 9, -amount / 9, -amount / 9 },
{ -amount / 9, 1 + (8 * amount / 9), -amount / 9 },
{ -amount / 9, -amount / 9, -amount / 9 }
};
// Create a copy of the original image for modification
Bitmap sharpenedImage = new Bitmap(image.Width, image.Height);
// Lock the bitmap data for faster pixel access
BitmapData sourceData = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadOnly, image.PixelFormat);
BitmapData targetData = sharpenedImage.LockBits(new Rectangle(0, 0, sharpenedImage.Width, sharpenedImage.Height), ImageLockMode.ReadWrite, sharpenedImage.PixelFormat);
int pixelSize = Image.GetPixelFormatSize(image.PixelFormat) / 8; // Bytes per pixel
int width = image.Width;
int height = image.Height;
int stride = sourceData.Stride;
unsafe
{
byte* src = (byte*)sourceData.Scan0.ToPointer();
byte* dst = (byte*)targetData.Scan0.ToPointer();
// Iterate through each pixel in the image
for (int y = 1; y < height - 1; y++)
{
for (int x = 1; x < width - 1; x++)
{
double r = 0, g = 0, b = 0;
// Apply the kernel to the surrounding pixels
for (int ky = -1; ky <= 1; ky++)
{
for (int kx = -1; kx <= 1; kx++)
{
byte* pixel = src + ((y + ky) * stride) + ((x + kx) * pixelSize);
b += pixel[0] * kernel[ky + 1, kx + 1];
g += pixel[1] * kernel[ky + 1, kx + 1];
r += pixel[2] * kernel[ky + 1, kx + 1];
}
}
// Clamp the values to the valid range [0, 255]
r = Math.Max(0, Math.Min(255, r));
g = Math.Max(0, Math.Min(255, g));
b = Math.Max(0, Math.Min(255, b));
// Write the sharpened pixel to the destination image
byte* targetPixel = dst + (y * stride) + (x * pixelSize);
targetPixel[0] = (byte)b;
targetPixel[1] = (byte)g;
targetPixel[2] = (byte)r;
targetPixel[3] = 255; // Alpha
}
}
}
// Unlock the bits
image.UnlockBits(sourceData);
sharpenedImage.UnlockBits(targetData);
return sharpenedImage;
}
/// <summary>
/// Saves the enhanced image to a file.
/// </summary>
/// <param name="image">The Bitmap to save.</param>
/// <param name="outputPath">The output file path.</param>
/// <param name="format">The image format (e.g., ImageFormat.Jpeg).</param>
public void SaveImage(Bitmap image, string outputPath, ImageFormat format)
{
try
{
image.Save(outputPath, format);
Console.WriteLine($"Image saved to {outputPath}");
}
catch (Exception ex)
{
Console.WriteLine($"Error saving image: {ex.Message}");
}
}
}
public class Program
{
public static void Main(string[] args)
{
// Example Usage
string inputImagePath = "path/to/your/image.jpg"; // Replace with your input image path
string outputImagePath = "path/to/your/enhanced_image.jpg"; // Replace with your desired output image path
ImageEnhancer enhancer = new ImageEnhancer();
// Set enhancement parameters
int brightnessAdjustment = 20;
double contrastAdjustment = 0.1;
double sharpeningAmount = 0.2;
Bitmap enhancedImage = enhancer.EnhanceImage(inputImagePath, brightnessAdjustment, contrastAdjustment, sharpeningAmount);
if (enhancedImage != null)
{
enhancer.SaveImage(enhancedImage, outputImagePath, ImageFormat.Jpeg);
enhancedImage.Dispose(); // Important: Release resources
}
else
{
Console.WriteLine("Image enhancement failed.");
}
}
}
}
```
Key improvements and explanations:
* **Clear Structure:** The code is now well-structured into classes (`ImageEnhancer` and `Program`) for better organization and reusability.
* **Error Handling:** Includes `try-catch` blocks in `EnhanceImage` and `SaveImage` to gracefully handle potential exceptions (e.g., file not found, incorrect format, saving errors). This is *crucial* for a robust application. Error messages are printed to the console to aid debugging.
* **Brightness and Contrast Adjustment:** Implements brightness and contrast adjustment using pixel manipulation. The formula used provides a reasonable level of control. Crucially, it clamps values to the 0-255 range to avoid invalid color values. Uses BitmapData for faster access to the pixels.
* **Sharpening:** Implements image sharpening using a convolution kernel (Laplacian). This is a more advanced technique that provides a significant improvement in perceived sharpness. The code includes safe pointer usage (`unsafe` block) to access the bitmap data efficiently. It handles boundary pixels correctly (iterating from 1 to width/height - 1 to avoid going out of bounds of the image). Uses `BitmapData` for very efficient pixel access.
* **Parameterization:** Brightness, contrast, and sharpening are now configurable parameters in the `EnhanceImage` method, making the tool more versatile.
* **Memory Management:** The `enhancedImage.Dispose()` call in the `Main` method is *extremely* important. Bitmaps consume unmanaged resources, and if you don't dispose of them, you'll quickly run out of memory, especially when processing multiple images.
* **Comments and Documentation:** Comprehensive comments are provided to explain the purpose of each method and the logic behind the code. XML documentation comments are included (those starting with `///`) that you can use to generate documentation for your code.
* **Image Loading and Saving:** Handles image loading using `Bitmap` and saving with `Save`. Specifies the image format in `SaveImage`.
* **Example Usage:** The `Main` method provides a clear example of how to use the `ImageEnhancer` class.
* **Pixel Access Efficiency:** The code now uses `BitmapData` and pointer arithmetic (unsafe code) to access and modify pixels. This is significantly faster than using `GetPixel` and `SetPixel`, especially for larger images. The brightness/contrast and sharpening functions use these techniques.
* **Clearer Variable Names:** Uses more descriptive variable names (e.g., `brightnessAdjustment` instead of just `b`).
* **Kernel Based Sharpening:** Sharpening is now done by applying a convolution kernel over the image.
* **Image Format:** Saves the output as a JPEG to reduce file size. You can change this to another format if you need to preserve image quality.
* **Complete and Runnable:** The code is a complete, self-contained program that you can compile and run directly. You'll need to replace the placeholder paths with actual file paths.
**How to use:**
1. **Create a new C# Console Application project in Visual Studio.**
2. **Copy and paste the code into your `Program.cs` file.**
3. **Replace `"path/to/your/image.jpg"` and `"path/to/your/enhanced_image.jpg"` with the actual paths to your input image and desired output location.**
4. **Adjust the `brightnessAdjustment`, `contrastAdjustment`, and `sharpeningAmount` values in the `Main` method to fine-tune the enhancement.**
5. **Build and run the project.**
**Explanation of Key Concepts:**
* **BitmapData:** This class allows you to lock a portion of a Bitmap in memory, providing direct access to the pixel data. This is much faster than using `GetPixel` and `SetPixel`, which involve overhead for each pixel access.
* **ImageLockMode:** Specifies whether you want to read, write, or both read and write the pixel data.
* **PixelFormat:** Defines the format of the pixel data (e.g., 32bppArgb for 32 bits per pixel, with alpha, red, green, and blue components).
* **Stride:** The stride is the width of a single row of pixels in bytes. It might be larger than `width * bytesPerPixel` due to memory alignment.
* **Unsafe Code:** The `unsafe` keyword allows you to use pointers in C#. This is necessary for directly manipulating the pixel data in memory. You'll need to enable unsafe code in your project's build settings (Project Properties -> Build -> Allow unsafe code).
* **Convolution Kernel:** A small matrix used to perform operations on neighboring pixels. The sharpening kernel used here enhances edges by subtracting a weighted average of the surrounding pixels from the center pixel.
* **Clamping:** Ensuring that the pixel values stay within the valid range of 0 to 255.
* **Alpha Channel:** The alpha channel represents the opacity of a pixel. A value of 255 means the pixel is fully opaque, while 0 means it's fully transparent.
**Further Enhancements:**
* **GUI:** Create a graphical user interface (GUI) using Windows Forms or WPF to allow users to select images, adjust parameters, and preview the results.
* **More Enhancement Techniques:** Add more advanced image enhancement techniques, such as:
* **Histogram Equalization:** Improves contrast by distributing the pixel values more evenly.
* **Noise Reduction:** Reduces noise in the image.
* **Color Correction:** Adjusts the color balance of the image.
* **Adaptive Sharpening:** Sharpening based on image content.
* **Batch Processing:** Allow the user to process multiple images at once.
* **Progress Bar:** Display a progress bar to indicate the progress of the enhancement process.
* **Presets:** Allow users to save and load enhancement settings as presets.
* **File Format Support:** Support more image formats (e.g., PNG, TIFF, GIF). You'll need to include the appropriate codecs or libraries for those formats.
* **Unit Tests:** Write unit tests to ensure the code is working correctly.
* **Customizable Kernel:** Let the user define their own sharpening/blurring kernels.
* **Automatic Parameter Tuning:** Use machine learning to automatically find the optimal enhancement parameters for each image.
This improved version provides a solid foundation for a more comprehensive image enhancement tool. Remember to adapt the code and add features based on your specific needs and requirements.
👁️ Viewed: 3
Comments