mirror of
https://github.com/cyanfish/naps2.git
synced 2024-08-17 11:10:23 +03:00
Clean up IMemoryImage/GdiImage/GdiExtensions
This commit is contained in:
parent
9394262da4
commit
7e162d82bd
@ -1,14 +0,0 @@
|
||||
using System.Drawing;
|
||||
|
||||
namespace NAPS2.Images.Gdi;
|
||||
|
||||
public static class BitmapExtensions
|
||||
{
|
||||
public static void SafeSetResolution(this Bitmap image, float xDpi, float yDpi)
|
||||
{
|
||||
if (xDpi > 0 && yDpi > 0)
|
||||
{
|
||||
image.SetResolution(xDpi, yDpi);
|
||||
}
|
||||
}
|
||||
}
|
@ -5,6 +5,14 @@ namespace NAPS2.Images.Gdi;
|
||||
|
||||
public static class GdiExtensions
|
||||
{
|
||||
public static void SafeSetResolution(this Bitmap image, float xDpi, float yDpi)
|
||||
{
|
||||
if (xDpi > 0 && yDpi > 0)
|
||||
{
|
||||
image.SetResolution(xDpi, yDpi);
|
||||
}
|
||||
}
|
||||
|
||||
public static Bitmap AsBitmap(this IMemoryImage image)
|
||||
{
|
||||
var gdiImage = image as GdiImage ?? throw new ArgumentException("Expected a GdiImage", nameof(image));
|
||||
@ -56,4 +64,32 @@ public static class GdiExtensions
|
||||
}
|
||||
throw new ArgumentException("Unsupported pixel format: " + pixelFormat);
|
||||
}
|
||||
|
||||
public static ImagePixelFormat AsImagePixelFormat(this PixelFormat pixelFormat)
|
||||
{
|
||||
switch (pixelFormat)
|
||||
{
|
||||
case PixelFormat.Format24bppRgb:
|
||||
return ImagePixelFormat.RGB24;
|
||||
case PixelFormat.Format32bppArgb:
|
||||
return ImagePixelFormat.ARGB32;
|
||||
case PixelFormat.Format1bppIndexed:
|
||||
return ImagePixelFormat.BW1;
|
||||
default:
|
||||
return ImagePixelFormat.Unsupported;
|
||||
}
|
||||
}
|
||||
|
||||
public static ImageLockMode AsImageLockMode(this LockMode lockMode)
|
||||
{
|
||||
switch (lockMode)
|
||||
{
|
||||
case LockMode.ReadOnly:
|
||||
return ImageLockMode.ReadOnly;
|
||||
case LockMode.WriteOnly:
|
||||
return ImageLockMode.WriteOnly;
|
||||
default:
|
||||
return ImageLockMode.ReadWrite;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,9 @@ public class GdiImage : IMemoryImage
|
||||
Bitmap = bitmap ?? throw new ArgumentNullException(nameof(bitmap));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the underlying System.Drawing.Bitmap object for this image.
|
||||
/// </summary>
|
||||
public Bitmap Bitmap { get; }
|
||||
|
||||
public int Width => Bitmap.Width;
|
||||
@ -25,48 +28,19 @@ public class GdiImage : IMemoryImage
|
||||
|
||||
public void SetResolution(float xDpi, float yDpi) => Bitmap.SafeSetResolution(xDpi, yDpi);
|
||||
|
||||
public ImagePixelFormat PixelFormat
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (Bitmap.PixelFormat)
|
||||
{
|
||||
case System.Drawing.Imaging.PixelFormat.Format24bppRgb:
|
||||
return ImagePixelFormat.RGB24;
|
||||
case System.Drawing.Imaging.PixelFormat.Format32bppArgb:
|
||||
return ImagePixelFormat.ARGB32;
|
||||
case System.Drawing.Imaging.PixelFormat.Format1bppIndexed:
|
||||
return ImagePixelFormat.BW1;
|
||||
default:
|
||||
return ImagePixelFormat.Unsupported;
|
||||
}
|
||||
}
|
||||
}
|
||||
public ImagePixelFormat PixelFormat => Bitmap.PixelFormat.AsImagePixelFormat();
|
||||
|
||||
public ImageFileFormat OriginalFileFormat => Bitmap.RawFormat.AsImageFileFormat();
|
||||
|
||||
public ImageLockState Lock(LockMode lockMode, out IntPtr scan0, out int stride)
|
||||
{
|
||||
var bitmapData = Bitmap.LockBits(new Rectangle(0, 0, Bitmap.Width, Bitmap.Height), GetGdiLockMode(lockMode),
|
||||
var bitmapData = Bitmap.LockBits(new Rectangle(0, 0, Bitmap.Width, Bitmap.Height), lockMode.AsImageLockMode(),
|
||||
Bitmap.PixelFormat);
|
||||
scan0 = bitmapData.Scan0;
|
||||
stride = Math.Abs(bitmapData.Stride);
|
||||
return new GdiImageLockState(Bitmap, bitmapData);
|
||||
}
|
||||
|
||||
private ImageLockMode GetGdiLockMode(LockMode lockMode)
|
||||
{
|
||||
switch (lockMode)
|
||||
{
|
||||
case LockMode.ReadOnly:
|
||||
return ImageLockMode.ReadOnly;
|
||||
case LockMode.WriteOnly:
|
||||
return ImageLockMode.WriteOnly;
|
||||
default:
|
||||
return ImageLockMode.ReadWrite;
|
||||
}
|
||||
}
|
||||
|
||||
public void Save(string path, ImageFileFormat imageFileFormat = ImageFileFormat.Unspecified, int quality = -1)
|
||||
{
|
||||
if (imageFileFormat == ImageFileFormat.Unspecified)
|
||||
@ -75,10 +49,7 @@ public class GdiImage : IMemoryImage
|
||||
}
|
||||
if (imageFileFormat == ImageFileFormat.Jpeg && quality != -1)
|
||||
{
|
||||
quality = Math.Max(Math.Min(quality, 100), 0);
|
||||
var encoder = ImageCodecInfo.GetImageEncoders().First(x => x.FormatID == ImageFormat.Jpeg.Guid);
|
||||
var encoderParams = new EncoderParameters(1);
|
||||
encoderParams.Param[0] = new EncoderParameter(Encoder.Quality, quality);
|
||||
var (encoder, encoderParams) = GetJpegSaveArgs(quality);
|
||||
Bitmap.Save(path, encoder, encoderParams);
|
||||
}
|
||||
else
|
||||
@ -95,10 +66,7 @@ public class GdiImage : IMemoryImage
|
||||
}
|
||||
if (imageFileFormat == ImageFileFormat.Jpeg && quality != -1)
|
||||
{
|
||||
quality = Math.Max(Math.Min(quality, 100), 0);
|
||||
var encoder = ImageCodecInfo.GetImageEncoders().First(x => x.FormatID == ImageFormat.Jpeg.Guid);
|
||||
var encoderParams = new EncoderParameters(1);
|
||||
encoderParams.Param[0] = new EncoderParameter(Encoder.Quality, quality);
|
||||
var (encoder, encoderParams) = GetJpegSaveArgs(quality);
|
||||
Bitmap.Save(stream, encoder, encoderParams);
|
||||
}
|
||||
else
|
||||
@ -107,6 +75,15 @@ public class GdiImage : IMemoryImage
|
||||
}
|
||||
}
|
||||
|
||||
private static (ImageCodecInfo, EncoderParameters) GetJpegSaveArgs(int quality)
|
||||
{
|
||||
quality = Math.Max(Math.Min(quality, 100), 0);
|
||||
var encoder = ImageCodecInfo.GetImageEncoders().First(x => x.FormatID == ImageFormat.Jpeg.Guid);
|
||||
var encoderParams = new EncoderParameters(1);
|
||||
encoderParams.Param[0] = new EncoderParameter(Encoder.Quality, quality);
|
||||
return (encoder, encoderParams);
|
||||
}
|
||||
|
||||
private ImageFileFormat GetFileFormatFromExtension(string path)
|
||||
{
|
||||
return Path.GetExtension(path).ToLowerInvariant() switch
|
||||
@ -118,13 +95,13 @@ public class GdiImage : IMemoryImage
|
||||
};
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Bitmap.Dispose();
|
||||
}
|
||||
|
||||
public IMemoryImage Clone()
|
||||
{
|
||||
return new GdiImage((Bitmap) Bitmap.Clone());
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Bitmap.Dispose();
|
||||
}
|
||||
}
|
@ -6,25 +6,73 @@
|
||||
/// </summary>
|
||||
public interface IMemoryImage : IImageStorage
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the image's width in pixels.
|
||||
/// </summary>
|
||||
int Width { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the image's height in pixels.
|
||||
/// </summary>
|
||||
int Height { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the image's horizontal resolution in pixels per inch.
|
||||
/// </summary>
|
||||
float HorizontalResolution { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the image's vertical resolution in pixels per inch.
|
||||
/// </summary>
|
||||
float VerticalResolution { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the image's horizontal and vertical resolution in pixels per inch. This has no effect for invalid (zero or
|
||||
/// negative) values.
|
||||
/// </summary>
|
||||
/// <param name="xDpi">The horizontal resolution.</param>
|
||||
/// <param name="yDpi">The vertical resolution.</param>
|
||||
void SetResolution(float xDpi, float yDpi);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the bits per pixel for the image's underlying binary data.
|
||||
/// </summary>
|
||||
ImagePixelFormat PixelFormat { get; }
|
||||
|
||||
ImageFileFormat OriginalFileFormat { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Obtains access to the underlying binary data for the image.
|
||||
/// </summary>
|
||||
/// <param name="lockMode">The access level (read/write) needed.</param>
|
||||
/// <param name="scan0">A pointer to the start of the binary data.</param>
|
||||
/// <param name="stride">The number of bytes per row in the binary data.</param>
|
||||
/// <returns>An object that, when disposed, releases the lock.</returns>
|
||||
ImageLockState Lock(LockMode lockMode, out IntPtr scan0, out int stride);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the original image file's format (e.g. png/jpeg) if known.
|
||||
/// </summary>
|
||||
ImageFileFormat OriginalFileFormat { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Saves the image to the given file path. If the file format is unspecified, it will be inferred from the
|
||||
/// file extension if possible.
|
||||
/// </summary>
|
||||
/// <param name="path">The path to save the image file to.</param>
|
||||
/// <param name="imageFormat">The file format to use.</param>
|
||||
/// <param name="quality">The quality parameter for JPEG compression, if applicable. -1 for default.</param>
|
||||
void Save(string path, ImageFileFormat imageFormat = ImageFileFormat.Unspecified, int quality = -1);
|
||||
|
||||
/// <summary>
|
||||
/// Saves the image to the given stream. The file format must be specified.
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream to save the image to.</param>
|
||||
/// <param name="imageFormat">The file format to use.</param>
|
||||
/// <param name="quality">The quality parameter for JPEG compression, if applicable. -1 for default.</param>
|
||||
void Save(Stream stream, ImageFileFormat imageFormat, int quality = -1);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a copy of the image so that one can be edited or disposed without affecting the other.
|
||||
/// </summary>
|
||||
/// <returns>The copy.</returns>
|
||||
IMemoryImage Clone();
|
||||
}
|
Loading…
Reference in New Issue
Block a user