1

I'm really weak with math and having a problem with an image resize algorithm. I'm trying to resize an image to a a specific ratio.

double neededRatio = 1.6d;
while (!AboutEqual(imageRatio, neededRatio))
{
    var cropPixels = 10;
    //crop code
    ...
    imageRatio = (double)img.Width / img.Height;
}

public static bool AboutEqual(double x, double y)
{
    double epsilon = Math.Max(Math.Abs(x), Math.Abs(y)) * 1E-15;
    return Math.Abs(x - y) <= epsilon;
}

The problem is, I can't seem to find the right number of pixels to crop to actually make the AboutEqual method work (I found it here). Sometimes it fails and the image get cropped indefinitely, I tried to log the inner-workings of the AboutEqual method and it's showing things I find weird, like:

X: 1.5249500998004  Y: 1.6 result: false
X: 1.55600814663951 Y: 1.6 result: false
X: 1.55600814663951 Y: 1.6 result: false
X: 1.58835758835759 Y: 1.6 result: false
X: 1.62208067940552 Y: 1.6 result: false
X: 1.60084925690021 Y: 1.6 result: false
X: 1.5796178343949  Y: 1.6 result: false
X: 1.61388286334056 Y: 1.6 result: false
X: 1.59219088937093 Y: 1.6 result: false
X: 1.62749445676275 Y: 1.6 result: false
X: 1.60532150776053 Y: 1.6 result: false
X: 1.58314855875831 Y: 1.6 result: false
X: 1.61904761904762 Y: 1.6 result: false
X: 1.59637188208617 Y: 1.6 result: false
X: 1.63341067285383 Y: 1.6 result: false

The linked question says "If both x and y are computed values then you have to increase the epsilon." - How do I do that and find the best number of pixels to crop?

Community
  • 1
  • 1
Madd0g
  • 3,841
  • 5
  • 37
  • 59
  • What does the crop code do? Chop pixels off the longer edge (or shorter edge) to increase (or decrease) the ratio? – Chris Shain Feb 03 '12 at 00:53
  • Yes, `if (imageRatio > neededShape)` cuts width, else cuts height – Madd0g Feb 03 '12 at 00:54
  • 1
    `1e-15` is pretty tiny, effectively 0 in terms of the magnitude difference from `1.6e0`. What are you looking for as "close" is concerned? – user7116 Feb 03 '12 at 00:56
  • @sixlettervariables - that's the thing, I'm not sure :) I'm sure a couple of pixels off wouldn't be the end of the world, but my naive 10 pixel cutoff is probably part of the problem, it never gets close enough to the limit – Madd0g Feb 03 '12 at 01:02

1 Answers1

3

You don't need to iterate to get your value. Calculate the target x value which would give you the desired ratio, and remove extra pixels.

Presuming that x is too large and you want to crop it:

// x/y should be 1.6
double neededRatio = 1.6d;

// so if we know y, then x should be:
int xTarget = (int)Math.Round(y * neededRatio);

// pixels to crop
int pixelsToCrop = x - xTarget;

[Edit]

The point is, this code gets the target x you will need to get to (presuming you need the ratio). If you still thing you need a loop, nothing stops you from doing:

while (x > xTarget)
{
    // crop 10 pixels
    // and do magic stuff
}
vgru
  • 49,838
  • 16
  • 120
  • 201
  • I need to to it my way because I cut from both sides and apply additional logic when cropping, it has to be with a loop – Madd0g Feb 03 '12 at 01:04
  • @Madd0g: can you elaborate a bit more? What additional logic? You need to get to the target value, one way or the other. I haven't touched your cropping code at all, so if you want to decrease `x` in several steps until you finally reach `xTarget`, I don't see why you couldn't do it. But neither do I see why you *should* do it. You can update your question, add an example dimension, and what and how you want it cropped. – vgru Feb 03 '12 at 01:05
  • Take half the pixels to crop from the left, half from the right? – user7116 Feb 03 '12 at 01:05
  • Yes, half of each side, I also cut off white areas (like in case of a screenshot with edges) – Madd0g Feb 03 '12 at 01:07
  • @Groo - if width is the problem I cut 10 off from either left or right (in case it's white) and otherwise cut 5 from both left and right, same with height. But the crop size is the problem, not the method, I think – Madd0g Feb 03 '12 at 01:14
  • oh, I see what you mean - loop on the size and not the ratio - but I still need to choose the crop size correctly somehow – Madd0g Feb 03 '12 at 01:16
  • 10 is just a random number like any other, there is absolutely no reason to do this operation in several steps (and I see no reason why these should be 10px steps), instead of deciding how many pixels to crop (and from where) and do it all at once. How do you detect if a part of the image is white? Do you check pixels, one by one? If you described your actual problem, there would surely be a better solution. – vgru Feb 03 '12 at 01:51