-
Problem DescriptionI encountered an issue where I was using scaling an image with where the image with resolution 1427*136 with 600dpi. A setting is present that automatically resizes the image to a maxHeight * maxWidth. The issue was that the image was too small, so I to took the image density and multiplied by scale, which was computed as: var scale = 1.0f;
bool hasScale = false;
if (maxHeight > 0)
{
scale = Math.Min(maxHeight / attImage.Height, scale);
if (scale < 1)
hasScale = true;
} The issue was that the image was too small, so I took the image density and multiplied it by scale, which was computed as: var resizedImage = new MagickImage(attImage);
if (hasScale)
{
int width = (int)(attImage.Width * scale);
int height = (int)(attImage.Height * scale);
resizedImage.FilterType = FilterType.Lanczos;
resizedImage.Density = new Density(resizedImage.Density.X * scale);
resizedImage.Resize(width, height);
}
else if (scaleToOriginalSize)
{
resizedImage.FilterType = FilterType.Lanczos;
resizedImage.Resample(attImage.Density.X, attImage.Density.Y);
}
return resizedImage;
} I don't remember the exact coordinates but the pixel density is reduced from 600 ppi to ~96ppi and the issues regarding the problem of the bigger images is solved, but now I have another problem. Images smaller than 200x100 and with low ppi (26-9ppi) are appearing pixelated. I'd like to make them sharper by shrinking them, but keeping the ppi intact so I don't have to provide new files. public static MagickImage ResizeImageField(
MagickImage attImage,
float maxHeight,
float maxWidth,
bool preservePixelDensity = false)
{
// If the image is not scheduled for scaling and within bounds and with low pixel density, scale the max width and height, but preserve the density
bool isImageWithinBounds = maxHeight >= attImage.Height && maxWidth >= attImage.Width;
if (!scaleToOriginalSize && isImageWithinBounds)
{
// Scale the old settings with a custom factor to get the new settings.
const float scalingFactor = 0.5f;
(float newMaxHeight, float newMaxWitdth) = (maxHeight * scalingFactor, maxWidth * scalingFactor);
return ResizeImageField(attImage, newMaxHeight, newMaxWitdth, false, scalingFactor, true);
}
bool hasScale = false;
if (maxHeight > 0)
{
scale = Math.Min(maxHeight / attImage.Height, scale);
if (scale < 1)
hasScale = true;
}
if (maxWidth > 0)
{
scale = Math.Min(maxWidth / attImage.Width, scale);
if (scale < 1)
hasScale = true;
}
var resizedImage = new MagickImage(attImage);
if (hasScale)
{
int width = (int)(attImage.Width * scale);
int height = (int)(attImage.Height * scale);
resizedImage.FilterType = FilterType.Lanczos;
if (!preservePixelDensity)
{
resizedImage.Density = new Density(attImage.Density.X * scale); // should work for the bigger images, than out target bounds.
resizedImage.Resize(width, height);
}
else
{
resizedImage.Density = new Density(attImage.Density.X * 1.0)
resizedImage.Resize(width, height);
}
}
return resizedImage;
} The target image should be 50*83 but 12ppi (anything not pixelated really). I acually don't understand why the code for the bigger images work's flawlessly not so much for the smaller ones. If my scaling algorithm is correct then I guess we have another problem. |
Beta Was this translation helpful? Give feedback.
Replies: 7 comments 2 replies
-
I don't understand the problem that you are trying to solve. Setting the |
Beta Was this translation helpful? Give feedback.
-
The problem I am trying to solve is to prepare an image of a signature, that is going to be inserted on a pdf page. Unfortunately I am not in control I what size and what quality the uploads his/hers signature, so a treshold is established with is a system setting and works for most signatures. The bounds are 200x100. In System.Drawing.Image it was all sorted out, but due to security reasons of the library, I had to rewrite this in this library. Then someone uploaded a rediculously high quality signature as mentioned (1427*136 with 600dpi), the snippet resizedImage.Density = new Density(attImage.Density.X * scale);
resizedImage.Resize(width, height); apparently solves the issue, but now am stuck on how should I handle images where at least one dimension is below 200x100 with low ppi. I fiddled with Affinity Photo, where i could get the image smaller and sharper, where I can lower the dimension and preserve the ppi, but don't know how do this correctly in code. |
Beta Was this translation helpful? Give feedback.
-
One detail, that i discovered plays a huge role in it, that when dealing with the PDF library, I am sending in the bytes from the Image Magick Lib. When I convert the MagickImage to System.Drawing.Bitmap and specify the exact dimensions to Aspose.Words.Drawing.Shape the smaller images seem fine. I'll test them on other images and share my results. |
Beta Was this translation helpful? Give feedback.
-
I managed to get the image manipulation working with my current, althoutgh I am not sure why this is working. The key to passing the imagebytes from the MagickImage object to the aspose method. var imageIsOnBounds = resizedImage.Width == imageField.MaxWidth || resizedImage.Height == imageField.MaxHeight;
if (imageIsOnBounds)
builder.InsertImage(resizedImage.ToByteArray());
else
builder.InsertImage(resizedImage.ToByteArray(), resizedImage.Width, resizedImage.Height);``` |
Beta Was this translation helpful? Give feedback.
-
Maybe the aspose method is doing some magic when inserting the image? But thanks for coming back and reporting how you resolved your issue. |
Beta Was this translation helpful? Give feedback.
-
Unfortunately my solution is still not as robust as
Where everything seem to be working perfectly. Any other suggestions? |
Beta Was this translation helpful? Give feedback.
-
Ok, so after fiddling with the libraries, I found a confirmed by QA way to do this without any stretching or other glitches. public static MagickImage ResizeImageField(
MagickImage originalImage,
float maxHeight,
float maxWidth,
bool scaleToOriginalSize,
double targetImageDensity = 96
)
{
if (scaleToOriginalSize)
return originalImage;
// Determine the scale ratio needed to fit within the maxWidth and maxHeight
double widthScale = maxWidth / (double)originalImage.Width;
double heightScale = maxHeight / (double)originalImage.Height;
double scale = Math.Min(widthScale, heightScale);
// If scaling is needed, ensure it doesn't exceed the original size if scaleToOriginalSize is false
int newWidth = (int)(originalImage.Width * scale);
int newHeight = (int)(originalImage.Height * scale);
// Create a new MagickImage for the resized image to avoid altering the original
var resizedImage = new MagickImage(originalImage.Clone());
// Set the filter to use for resizing. Lanczos is usually a good choice, but feel free to experiment.
resizedImage.FilterType = FilterType.Lanczos;
// Resize the image using the new dimensions and apply the new density if not preserving the original
resizedImage.Density = new Density(targetImageDensity);
resizedImage.Resize(newWidth, newHeight);
return resizedImage;
} The Aspose.Words.DocumentBuilder call is |
Beta Was this translation helpful? Give feedback.
Ok, so after fiddling with the libraries, I found a confirmed by QA way to do this without any stretching or other glitches.