изменить размер изображения по области

Я пытаюсь написать функцию javascript для изменения размера изображения на основе заданной области (или в моем случае (несколько неточного) «среднего размера», поскольку об этом легче думать. Вместо того, чтобы подавать максимальную высоту и ширину, я хочу для подачи на максимальную площадь, чтобы длинные или узкие изображения визуально выглядели примерно одинакового размера.

введите здесь описание изображения

Однако я действительно увлекся математическим аспектом этого ... просто как логически это понять, поскольку в последнее время я мало занимался математикой.

По сути, учитывая соотношение сторон, я хочу определить максимальный размер в области.

Что-то вроде этого:

function resizeImgByArea(img, avgDimension){
    var w = $(img).width();
    var h = $(img).height();
    var ratio = w/h;
    var area = avgDimension * avgDimension;
    var targetHeight //something involving ratio and area
    var targetWidth //something involving ratio and area
    $(img).width(targetWidth);
    $(img).height(targetHeight);
}

Не уверен, что это в тему здесь, но я не могу это понять.


person Damon    schedule 27.09.2011    source источник


Ответы (5)


Похоже, вы хотите, чтобы пиксели миниатюры были как можно ближе к средней области, как и все остальные миниатюры, верно?

Итак, в основном, учитывая ч / б исходного изображения и целевую область A:

h * w = original image's pixel size (let's got with 640x480 = 307,200 pixels)
A = maximum number of pixels allowed (let's go for 100x100 = 10,000 pixels)

307,200 / 10,000 = 30x reduction

original aspect ratio = 640 / 480 = 1.3333 : 1

Чтобы рассчитать размер x/y новой миниатюры:

newX * newY = 10000
newX = newY * 1.333
(newY * 1.333) * newY = 10000
newY^2 * 1.333 = 10000
newY^2 = 10000 / 1.333
newY^2 = 7502
newY = 86.6 -> 87
newX = 87 * 1.333 = 115.97 -> 116

116 x 87 = 10,092 pixels

если бы мы округли размеры миниатюр, мы бы получили 86x114 = 9804 пикселя.

Итак... чтобы преобразовать изображение 640x480 в стандартный размер 10 000 пикселей, вам понадобится новый размер изображения 86-87 по высоте и 114-116 по ширине.

person Marc B    schedule 27.09.2011
comment
Потребовалось некоторое время, чтобы понять ваш странный способ объяснения, потому что он вообще не работал бы как код, но он действительно работает, как только я понял это! В основном это просто newY = sqrt(newArea/aspectRatio); newX = newY * aspectRatio. - person Moss; 10.03.2016

Вы ищете что-то вроде:

function resizeImgByArea(img, avgDimension) {
    var w = $(img).width();
    var h = $(img).height();
    var maxWidth = avgDimension;
    var maxHeight = avgDimension;
    var divisor;
    var targetWidth = w;
    var targetHeight = h;

    if (w > maxWidth || h > maxHeight) {
        // Set the divisor to whatever will make the new image fit the dimensions given
        if((w - maxWidth) > (h - maxHeight)) {
            divisor = w / maxWidth;
        }
        else {
            divisor = h / maxHeight;
        }

        targetWidth = w / divisor;
        targetHeight = h / divisor;
    }

    $(img).width(targetWidth);
    $(img).height(targetHeight);
}
person John Kurlak    schedule 27.09.2011
comment
нет, я не хочу, чтобы он был установлен на maxHeight или maxWidth.. скорее, чтобы сделать изображение максимально большим, сохраняя при этом то же соотношение сторон, учитывая максимальную площадь.. в действительности, чтобы получить изображения, которые выглядят примерно одинакового размера, если они узкие против квадратных - person Damon; 27.09.2011
comment
Итак, вы хотите, чтобы изображение помещалось в квадрат? При необходимости изображение приходится обрезать? - person John Kurlak; 27.09.2011
comment
нет, я хочу, чтобы он имел ту же общую площадь, что и квадрат, но позволял ему выходить за его пределы. - person Damon; 27.09.2011
comment
Или вы хотите, чтобы (targetWidth+targetHeight)/2 == mediumDimension и сохранялось исходное соотношение сторон? - person John Kurlak; 27.09.2011
comment
эээ.. это не совсем то же самое, но это может сработать. в основном пытаясь, чтобы изображения имели такое же соотношение сторон, как и было, но чтобы все они выглядели примерно одинакового размера; Я подумал, что площадь будет самым простым способом сделать это. - person Damon; 27.09.2011

Это не так сложно.

maxPix = среднее ^ 2

maxPix = х * ч + х * ш

среднее^2 = x*h + x*w //: x

среднее ^ 2 / х = ч + ш

инвертировать и умножить на среднее ^ 2

х = среднее ^ 2 / (ч + ш)

затем умножьте h и w на x, чтобы получить новые размеры

person Stephan    schedule 27.09.2011
comment
Благодарю. является обратным и умножает свою собственную операцию или описывает то, что вы сделали выше? Я не посещал уроки математики почти 10 лет. - person Damon; 27.09.2011
comment
Это описание того, что я делаю. Таким образом, инвертирование (я не носитель английского языка) помещает значение под линию, поэтому инвертированный x равен 1/x, а инвертированный 1/2 равен 2... это полезно, когда у вас есть var для решения под линией. Вы можете просто инвертировать все вещи. И затем я умножаю на среднее ^ 2, чтобы получить только х - person Stephan; 28.09.2011

Вот функция, которую я придумал, она проще, чем некоторые упомянутые, и делает то, что мне нужно. Он ограничивается набором maxWidth, но не высотой из-за конкретных требований, которые я использовал. Возможно, было бы уместно добавить maxHeight, а также некоторую очистку, но это делается.

function resizeImgByArea(imgId, avgDimension){
   var node, w, h, oldArea, oldAvgDimension, multiplicator, targetHeight, targetWidth, defAvgDimension;
   node = $('#' + imgId);
   node.css('width', '').css('height', '');
   var maxW = $('#' + imgId).css('maxWidth');
   if (maxW){
       defAvgDimension = maxW;
   } else {
       defAvgDimension = 200;
   }
   avgDimension = (typeof avgDimension == "undefined")?'defAvgDimension':avgDimension;
   w = node.width();
   h = node.height();
   oldArea = w*h;
   oldAvgDimension = Math.sqrt(oldArea);
   if (oldAvgDimension > avgDimension){
       multiplicator = avgDimension / oldAvgDimension;
       targetHeight = h * multiplicator;
       targetWidth = w * multiplicator;
       node.width(targetWidth);
       node.height(targetHeight);
   }
}
person Damon    schedule 04.11.2011

function fitImageInArea(img, area) {
    var r;

    if (img.width/img.height >= area.width/area.height) {
        r = area.width / img.width;
        img.width = area.width;
        img.height = img.height*r;
    } else {
        r = area.height / img.height;
        img.height = area.height;
        img.width = img.width*r;
    }

    return img;
}

Дайте изображение или что-нибудь со свойствами width и height в качестве аргумента. Аргумент area также предполагает свойства width и height.

person adriendenat    schedule 17.08.2015