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
{
/// <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>
bool Compand { get; set; }
}

23
src/ImageProcessorCore/Samplers/Resize.cs

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

37
src/ImageProcessorCore/Samplers/ResizeHelper.cs

@ -26,6 +26,8 @@ namespace ImageProcessorCore.Samplers
{
switch (options.Mode)
{
case ResizeMode.Crop:
return CalculateCropRectangle(source, options);
case ResizeMode.Pad:
return CalculatePadRectangle(source, options);
case ResizeMode.BoxPad:
@ -35,9 +37,9 @@ namespace ImageProcessorCore.Samplers
case ResizeMode.Min:
return CalculateMinRectangle(source, options);
// Default case ResizeMode.Crop
// Last case ResizeMode.Stretch:
default:
return CalculateCropRectangle(source, options);
return CalculateStretchRectangle(source, options);
}
}
@ -348,12 +350,16 @@ namespace ImageProcessorCore.Samplers
if (sourceRatio < ratio)
{
destinationHeight = Convert.ToInt32(source.Height * percentWidth);
height = destinationHeight;
}
else
{
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);
}
@ -372,12 +378,12 @@ namespace ImageProcessorCore.Samplers
int destinationWidth;
int destinationHeight;
// Fractional variants for preserving aspect ratio.
double percentHeight = Math.Abs(height / (double)source.Height);
double percentWidth = Math.Abs(width / (double)source.Width);
height = height > 0 ? height : Convert.ToInt32(source.Height * percentWidth);
width = width > 0 ? width : Convert.ToInt32(source.Width * percentHeight);
// Don't upscale
if (width > source.Width || height > source.Height)
{
options.Size = new Size(source.Width, source.Height);
return new Rectangle(0, 0, source.Width, source.Height);
}
double sourceRatio = (double)source.Height / source.Width;
@ -401,7 +407,22 @@ namespace ImageProcessorCore.Samplers
destinationHeight = height;
}
// Replace the size to match the rectangle.
options.Size = new Size(width, height);
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,
/// <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>
Stretch,
BoxPad,
/// <summary>
/// Constrains the resized image to fit the bounds of its container maintaining
@ -34,14 +36,14 @@ namespace ImageProcessorCore.Samplers
/// <summary>
/// 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>
Min,
/// <summary>
/// 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"/>
/// Stretches the resized image to fit the bounds of its container.
/// </summary>
BoxPad
Stretch
}
}

7
src/ImageProcessorCore/Samplers/ResizeOptions.cs

@ -33,8 +33,15 @@ namespace ImageProcessorCore.Samplers
/// </summary>
public Size Size { get; set; }
/// <summary>
/// Gets or sets the sampler to perform the resize operation.
/// </summary>
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; }
}
}

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

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

Loading…
Cancel
Save