2009-06-13 4 views
16

им пытаются изменить размер bufferdImage в памяти в Java, но, чтобы сохранить пропорции изображения им есть что-то вроде этого, но это не хорошоИзменение размера изображения при сохранении соотношения сторон в Java

int w = picture.getWidth(); 
int h = picture.getWidth(); 
int neww=w; 
int newh=h; 
int wfactor = w; 
int hfactor = h; 
if(w > DEFULT_PICTURE_WIDTH || h > DEFULT_PICTURE_HIGHT) 
{ 
    while(neww > DEFULT_PICTURE_WIDTH) 
    { 
     neww = wfactor /2; 
     newh = hfactor /2; 
     wfactor = neww; 
     hfactor = newh; 
    } 
} 

picture = Utils.resizePicture(picture,neww,newh); 

ответ

6

Вы можете посмотреть на perils-of-image-getscaledinstance.html, что объясняет, почему getScaledInstance(), используемый в некоторых из ответы следует избегать.

В статье также содержится альтернативный код.

8

Для начала - взгляните на строку 2. Не должно быть getHeight()?

Вам не нужен цикл while для изменения размера, вы хотите узнать соотношение размеров, которое является простым битом математики.

(width/height) = (new_width/new_height) 

Если вы знаете, один из «новых» размеров, другие могут быть найдены с помощью умножения

new_height * (width/height) = new_width 

Вы также можете использовать ленивый метод, предусмотренный BufferedImage's суперкласс Image, getScaledInstance() - с использованием -1 для ширины или высоты будет поддерживать соотношение сторон

например:
scaledPic = picture.getScaledInstance(new_width, -1, Image.SCALE_FAST);

+0

да его GetHeight неправильно опечатка есть какие-либо причине я не могу использовать getScaledInstance с BufferdImage? – user63898

+0

Это должно быть хорошо, потому что BufferedImage extends Image – Max

+0

Hah, спасибо за это первое уравнение. Сделал что-то щелчком в моем запутанном мозгу! – Cameron

0

Если вы хотите изменить размер изображения w0 x h0 на w1 x h1, сохранив соотношение сторон, затем вычислите вертикальную и горизонтальную шкалу и выберите меньшую.

double scalex = 1; 
double scaley = 1; 
if (scalingMode == ScalingMode.WINDOW_SIZE) { 
    scalex = (double)getWidth()/frontbuffer.getWidth(); 
    scaley = (double)getHeight()/frontbuffer.getHeight(); 
} else 
if (scalingMode == ScalingMode.KEEP_ASPECT) { 
    double sx = (double)getWidth()/frontbuffer.getWidth(); 
    double sy = (double)getHeight()/frontbuffer.getHeight(); 
    scalex = Math.min(sx, sy); 
    scaley = scalex; 
    // center the image 
    g2.translate((getWidth() - (frontbuffer.getWidth() * scalex))/2, 
    (getHeight() - (frontbuffer.getHeight() * scaley))/2); 
} 
g2.scale(scalex, scaley); 
if (interpolation != ImageInterpolation.NONE) { 
    g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, interpolation.hint); 
} 
g2.drawImage(frontbuffer, 0, 0, null); 
+0

Что представляет собой передний буффер? – user63898

+0

Это отрывок из одного из моих кодов, который отображает анимацию с использованием буферизации подкачки. frontbuffer - это просто BufferedImage, который нужно показать в данный момент. – akarnokd

8

Если ширина, высота источника и цель известны, используйте следующую функцию для определения масштаба изображения.

private double determineImageScale(int sourceWidth, int sourceHeight, int targetWidth, int targetHeight) { 

double scalex = (double) targetWidth/sourceWidth; 
double scaley = (double) targetHeight/sourceHeight; 
return Math.min(scalex, scaley); 

}

Затем используйте эту шкалу для масштабирования вверх/вниз изображения, используя следующий код

Image scaledImage = sourceBufferedImage.getScaledInstance((int) (width * scale), (int) (height * scale), Image.SCALE_SMOOTH); 
63

Добавляя к точке зрения Erik о getScaledInstance, если вы перешли от нее к использованию рекомендуемых механизмов масштабирования в Java2D, возможно, вы заметили, что ваши изображения выглядят значительно хуже.

Причиной этого является, когда Java2D рекомендуется использовать getScaledInstance и AreaAveragingScaleFilter, они не заменили его с чем-нибудь , как легко использовать в API, вместо того, чтобы мы оставили нашим собственным устройствам с помощью Java2D API, непосредственно. К счастью, Крис Кэмпбелл (из команды J2D) следил за рекомендацией использовать инкрементный метод масштабирования, который дает похожие результаты для AreaAveragingScaleFilter и работает быстрее; к сожалению, код имеет приличный размер и не затрагивает ваш первоначальный вопрос о соблюдении пропорций.

Около 6 месяцев назад я снова и снова повторял все эти вопросы о «масштабировании изображений на Java» и, в конце концов, собрал все советы, сделал все необходимые исследования и исследования и скомпилировал все в один «лучший» практики "image scaling library.

API прост, так как он всего лишь 1 класс и множество статических методов.Основное использование выглядит следующим образом:

BufferedImage img = ImageIO.read(...); // load image 
BufferedImage scaledImg = Scalr.resize(img, 320); 

Это simplest call где библиотека сделает лучше предугадывать по качеству, чтить свои пропорции изображения, и установите результат в поле на 320x320 ограничивающем. ПРИМЕЧАНИЕ. Ограничивающая коробка - это только максимальная используемая W/H, так как ваши пропорции изображения соблюдены, получившееся изображение по-прежнему будет считать это, скажем 320x200.

Если вы хотите переопределить автоматический режим и заставить его получить наилучший результат и даже применить к результату очень мягкий фильтр с псевдонимом, чтобы он выглядел еще лучше (особенно хорош для миниатюр), этот вызов будет выглядеть так:

BufferedImage img = ImageIO.read(...); // load image 
BufferedImage scaledImg = Scalr.resize(img, Method.QUALITY, 
             150, 100, Scalr.OP_ANTIALIAS); 

все это просто примеры, то API широк и охватывает все, от супер-простых случаев использования в очень специализированы. Вы можете даже передать свой собственный BufferedImageOps, который будет применен к изображению (и библиотека автоматически исправит вам 6-летнюю ошибку BufferImageOp JDK!)

Существует гораздо больше возможностей для масштабирования изображений в Java, для вас, например, всегда сохраняя изображение в одном из лучших поддерживаемых типов изображений RGB или ARGB во время работы на нем. Под защитой конвейер обработки изображений Java2D возвращается к более низкому программному конвейеру, если тип изображения, используемый для любых операций с изображениями, плохо поддерживается.

Если все это звучит как большая головная боль, это своего рода ... вот почему я написал библиотеку и открыл ее, поэтому люди могли просто изменять размеры своих изображений и продолжать свою жизнь, не беспокоясь о Это.

Надеюсь, что помогает.

+10

Просто взглянул на эту библиотеку, и это очень помогло; мог бы +2 этот пост, если бы мог, с другим +1, потому что ваш проект имеет свой собственный репозиторий maven. Благодаря! –

+0

Спасибо за добрые слова Эндрю, я рад, что ты сочла это полезным! –

+0

+1 для @RiyadKalla для написания Scalr !!! – flybywire

3

Я использую эти два метода для масштабирования изображений, где max - это больший размер вашего целевого изображения. Для 100x100 изображения будет 100, для 200х300 изображения будет 300.

public static BufferedImage scale(InputStream is, int max) { 
    Image image = null; 
    try { 
     image = ImageIO.read(is); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
    int width = image.getWidth(null); 
    int height = image.getHeight(null); 
    double dWidth = 0; 
    double dHeight = 0; 
    if (width == height) { 
     dWidth = max; 
     dHeight = max; 
    } 
    else if (width > height) { 
     dWidth = max; 
     dHeight = ((double) height/(double) width) * max; 
    } 
    else { 
     dHeight = max; 
     dWidth = ((double) width/(double) height) * max; 
    } 
    image = image.getScaledInstance((int) dWidth, (int) dHeight, Image.SCALE_SMOOTH); 
    BufferedImage bImage = toBufferedImage(image); 
    return bImage; 

} 

public static BufferedImage toBufferedImage(Image img) 
{ 
    if (img instanceof BufferedImage) 
    { 
     return (BufferedImage) img; 
    } 

    BufferedImage bimage = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB); 

    Graphics2D bGr = bimage.createGraphics(); 
    bGr.drawImage(img, 0, 0, null); 
    bGr.dispose(); 

    return bimage; 
} 
Смежные вопросы