Browse Source

Finish ResizeModes proper

Former-commit-id: 4582848b6fb5eee5c57c3a087ebd754015afe7b0
Former-commit-id: 79bf4fed23de01d328004558b9d1389ededc6192
Former-commit-id: 0ffc0e8c7fb9b123b251123f1aeb66612a09d089
af/merge-core
James Jackson-South 10 years ago
parent
commit
afe23fc305
  1. 3
      src/ImageProcessorCore/Samplers/IImageSampler.cs
  2. 23
      src/ImageProcessorCore/Samplers/Resize.cs
  3. 37
      src/ImageProcessorCore/Samplers/ResizeHelper.cs
  4. 14
      src/ImageProcessorCore/Samplers/ResizeMode.cs
  5. 7
      src/ImageProcessorCore/Samplers/ResizeOptions.cs
  6. 3
      tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs

3
src/ImageProcessorCore/Samplers/IImageSampler.cs

@ -11,7 +11,8 @@ namespace ImageProcessorCore.Samplers
public interface IImageSampler : IImageProcessor public interface IImageSampler : IImageProcessor
{ {
/// <summary> /// <summary>
/// Gets or sets a value indicating whether to compand the value on processing. /// Gets or sets a value indicating whether to compress
/// or expand individual pixel colors the value on processing.
/// </summary> /// </summary>
bool Compand { get; set; } bool Compand { get; set; }
} }

23
src/ImageProcessorCore/Samplers/Resize.cs

@ -56,8 +56,10 @@ namespace ImageProcessorCore.Samplers
int width = target.Width; int width = target.Width;
int height = target.Height; int height = target.Height;
int sourceHeight = sourceRectangle.Height; int sourceHeight = sourceRectangle.Height;
int targetY = targetRectangle.Y; int targetX = target.Bounds.X;
int targetBottom = targetRectangle.Bottom; int targetY = target.Bounds.Y;
int targetRight = target.Bounds.Right;
int targetBottom = target.Bounds.Bottom;
int startX = targetRectangle.X; int startX = targetRectangle.X;
int endX = targetRectangle.Right; int endX = targetRectangle.Right;
bool compand = this.Compand; bool compand = this.Compand;
@ -65,25 +67,28 @@ namespace ImageProcessorCore.Samplers
if (this.Sampler is NearestNeighborResampler) if (this.Sampler is NearestNeighborResampler)
{ {
// Scaling factors // Scaling factors
float widthFactor = source.Width / (float)target.Width; float widthFactor = sourceRectangle.Width / (float)targetRectangle.Width;
float heightFactor = source.Height / (float)target.Height; float heightFactor = sourceRectangle.Height / (float)targetRectangle.Height;
Parallel.For( Parallel.For(
startY, startY,
endY, endY,
y => y =>
{ {
if (y >= targetY && y < targetBottom) if (targetY <= y && y < targetBottom)
{ {
// Y coordinates of source points // Y coordinates of source points
int originY = (int)((y - targetY) * heightFactor); int originY = (int)((y - startY) * heightFactor);
for (int x = startX; x < endX; x++) for (int x = startX; x < endX; x++)
{ {
// X coordinates of source points if (targetX <= x && x < targetRight)
int originX = (int)((x - startX) * widthFactor); {
// X coordinates of source points
int originX = (int)((x - startX) * widthFactor);
target[x, y] = source[originX, originY]; target[x, y] = source[originX, originY];
}
} }
this.OnRowProcessed(); this.OnRowProcessed();

37
src/ImageProcessorCore/Samplers/ResizeHelper.cs

@ -26,6 +26,8 @@ namespace ImageProcessorCore.Samplers
{ {
switch (options.Mode) switch (options.Mode)
{ {
case ResizeMode.Crop:
return CalculateCropRectangle(source, options);
case ResizeMode.Pad: case ResizeMode.Pad:
return CalculatePadRectangle(source, options); return CalculatePadRectangle(source, options);
case ResizeMode.BoxPad: case ResizeMode.BoxPad:
@ -35,9 +37,9 @@ namespace ImageProcessorCore.Samplers
case ResizeMode.Min: case ResizeMode.Min:
return CalculateMinRectangle(source, options); return CalculateMinRectangle(source, options);
// Default case ResizeMode.Crop // Last case ResizeMode.Stretch:
default: default:
return CalculateCropRectangle(source, options); return CalculateStretchRectangle(source, options);
} }
} }
@ -348,12 +350,16 @@ namespace ImageProcessorCore.Samplers
if (sourceRatio < ratio) if (sourceRatio < ratio)
{ {
destinationHeight = Convert.ToInt32(source.Height * percentWidth); destinationHeight = Convert.ToInt32(source.Height * percentWidth);
height = destinationHeight;
} }
else else
{ {
destinationWidth = Convert.ToInt32(source.Width * percentHeight); destinationWidth = Convert.ToInt32(source.Width * percentHeight);
width = destinationWidth;
} }
// Replace the size to match the rectangle.
options.Size = new Size(width, height);
return new Rectangle(0, 0, destinationWidth, destinationHeight); return new Rectangle(0, 0, destinationWidth, destinationHeight);
} }
@ -372,12 +378,12 @@ namespace ImageProcessorCore.Samplers
int destinationWidth; int destinationWidth;
int destinationHeight; int destinationHeight;
// Fractional variants for preserving aspect ratio. // Don't upscale
double percentHeight = Math.Abs(height / (double)source.Height); if (width > source.Width || height > source.Height)
double percentWidth = Math.Abs(width / (double)source.Width); {
options.Size = new Size(source.Width, source.Height);
height = height > 0 ? height : Convert.ToInt32(source.Height * percentWidth); return new Rectangle(0, 0, source.Width, source.Height);
width = width > 0 ? width : Convert.ToInt32(source.Width * percentHeight); }
double sourceRatio = (double)source.Height / source.Width; double sourceRatio = (double)source.Height / source.Width;
@ -401,7 +407,22 @@ namespace ImageProcessorCore.Samplers
destinationHeight = height; destinationHeight = height;
} }
// Replace the size to match the rectangle.
options.Size = new Size(width, height);
return new Rectangle(0, 0, destinationWidth, destinationHeight); return new Rectangle(0, 0, destinationWidth, destinationHeight);
} }
/// <summary>
/// Calculates the target rectangle for stretch mode.
/// </summary>
/// <param name="source">The source image.</param>
/// <param name="options">The resize options.</param>
/// <returns>
/// The <see cref="Rectangle"/>.
/// </returns>
private static Rectangle CalculateStretchRectangle(ImageBase source, ResizeOptions options)
{
return new Rectangle(0, 0, options.Size.Width, options.Size.Height);
}
} }
} }

14
src/ImageProcessorCore/Samplers/ResizeMode.cs

@ -22,9 +22,11 @@ namespace ImageProcessorCore.Samplers
Pad, Pad,
/// <summary> /// <summary>
/// Stretches the resized image to fit the bounds of its container. /// Pads the image to fit the bound of the container without resizing the
/// original source.
/// When downscaling, performs the same functionality as <see cref="ResizeMode.Pad"/>
/// </summary> /// </summary>
Stretch, BoxPad,
/// <summary> /// <summary>
/// Constrains the resized image to fit the bounds of its container maintaining /// Constrains the resized image to fit the bounds of its container maintaining
@ -34,14 +36,14 @@ namespace ImageProcessorCore.Samplers
/// <summary> /// <summary>
/// Resizes the image until the shortest side reaches the set given dimension. /// Resizes the image until the shortest side reaches the set given dimension.
/// Upscaling is disabled in this mode and the original image will be returned
/// if attempted.
/// </summary> /// </summary>
Min, Min,
/// <summary> /// <summary>
/// Pads the image to fit the bound of the container without resizing the /// Stretches the resized image to fit the bounds of its container.
/// original source.
/// When downscaling, performs the same functionality as <see cref="ResizeMode.Pad"/>
/// </summary> /// </summary>
BoxPad Stretch
} }
} }

7
src/ImageProcessorCore/Samplers/ResizeOptions.cs

@ -33,8 +33,15 @@ namespace ImageProcessorCore.Samplers
/// </summary> /// </summary>
public Size Size { get; set; } public Size Size { get; set; }
/// <summary>
/// Gets or sets the sampler to perform the resize operation.
/// </summary>
public IResampler Sampler { get; set; } = new BicubicResampler(); public IResampler Sampler { get; set; } = new BicubicResampler();
/// <summary>
/// Gets or sets a value indicating whether to compress
/// or expand individual pixel colors the value on processing.
/// </summary>
public bool Compand { get; set; } public bool Compand { get; set; }
} }
} }

3
tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs

@ -215,7 +215,8 @@
ResizeOptions options = new ResizeOptions() ResizeOptions options = new ResizeOptions()
{ {
Size = new Size(image.Width , image.Height + 200), Size = new Size(image.Width , image.Height + 200),
Mode = ResizeMode.Pad Mode = ResizeMode.Pad,
Sampler = new NearestNeighborResampler()
}; };
image.Resize(options, this.ProgressUpdate) image.Resize(options, this.ProgressUpdate)

Loading…
Cancel
Save