Механизм приложения: вычисление размеров миниатюр, которые должны быть сгенерированы, путем предоставления миниатюр из интернет-магазина - PullRequest
5 голосов
/ 22 февраля 2011

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

Как бы я рассчитал размеры миниатюры, созданной в интернет-магазине, зная только размеры исходного изображения?

Мои предыдущие попытки были не очень точными, большую часть времени они были отклонены на один или два пикселя (вероятно, из-за округления).

Я понимаю, что получение эскиза и использование API изображений для проверки размеров будет работать, но я думаю, что это неэффективно.

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

from __future__ import division
def resized_size(original_width, original_height, width, height):
    original_ratio = float(original_width) / float(original_height)
    resize_ratio = float(width) / float(height)
    if original_ratio >= resize_ratio:
        return int(width), int(round(float(width) / float(original_ratio)))
    else:
        return int(round(float(original_ratio) * float(height))), int(height)

Точность очень важна!

Ответы [ 2 ]

4 голосов
/ 28 февраля 2011

Я вижу проблему. Причина в том, что ринг C используется для расчета размеры. Python не имеет эквивалентной реализации rint как это было снято Россумом в 1.6:

http://markmail.org/message/4di24iqm7zhc4rwc

Ваш единственный выход сейчас заключается в том, чтобы реализовать свой собственный rint в Python.

rint по умолчанию делает раунд в четных против раунд питонов, который делает что-то еще. Вот простая реализация (без обработки краевого регистра для + inf -inf и т. Д.)

import math

def rint(x):
  x_int = int(x)
  x_rem = x - x_int  # this is problematic
  if (x_int % 2) == 1:
    return round(x)
  else:
    if x_rem <= 0.5:
      return math.floor(x)
    else:
      return math.ceil(x)

Приведенный выше код показывает, как он должен быть реализован в теории. Проблема заключается в x_rem. x - x_int должен получить дробный компонент, но вместо этого вы можете получить дробь + дельта. Таким образом, вы можете попытаться добавить порог, если хотите

import math

def rint(x):
  x_int = int(x)
  x_rem = x - x_int
  if (x_int % 2) == 1:
    return round(x)
  else:
    if x_rem - 0.5 < 0.001:
      return math.floor(x)
    else:
      return math.ceil(x)

Здесь. Я жестко закодировал порог 0,001. Сам по себе порог является проблематичным. Я думаю, вам действительно нужно поиграть с реализацией ринта и подогнать его в ваше приложение и посмотрите, что работает лучше всего. Удачи!

0 голосов
/ 26 февраля 2011

Предполагая, что у вас есть оригинальное изображение 1600x1200, и вы хотите получить миниатюру размера 800, ожидаемый результат - изображение 800x600. Чтобы рассчитать это, вы можете сделать следующее:

// In Java
double aspectRatio = originalWidth / originalHeight;
output_width = 800;
output_height = (int)Math.round(800.0 / aspectRatio);

Посмотрим, будет ли это работать с вырожденными случаями. Предположим, что у вас есть оригинал размером 145x111, и вы хотите получить миниатюру размера 32.

aspectRatio == 1.3063063063063063
output_width == 32
output_height == Math.round(32.0 / 1.3063063063063063) == 24

Вы можете сделать нечто подобное для портретно-ориентированных изображений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...