Java를 사용하여 이미지 크기를 조정하는 방법은 무엇입니까?


126

PNG, JPEG 및 GIF 파일의 크기를 조정해야합니다. Java를 사용하여이 작업을 수행하려면 어떻게해야합니까?


14
당신이 라이브러리를 요구하기 때문에, 진짜 대답은 여기에 있습니다 : stackoverflow.com/questions/244164/... . 그것은 허용 대답의 코드보다 사용하기 훨씬 쉽다)
아르투르 Gajowy

라이브러리 부분에 동의하지 않습니다. Graphics2D는 awt 라이브러리의 일부이며 오픈 소스입니다. 마지막 부분 (오픈 소스)에 대해서는 100 % 확신 할 수 없지만 어쨌든 awt 코드를 누가 볼 것입니까?
Burkhard

답변:


87

이미지를로드 한 후 시도해 볼 수 있습니다.

BufferedImage createResizedCopy(Image originalImage, 
            int scaledWidth, int scaledHeight, 
            boolean preserveAlpha)
    {
        System.out.println("resizing...");
        int imageType = preserveAlpha ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
        BufferedImage scaledBI = new BufferedImage(scaledWidth, scaledHeight, imageType);
        Graphics2D g = scaledBI.createGraphics();
        if (preserveAlpha) {
            g.setComposite(AlphaComposite.Src);
        }
        g.drawImage(originalImage, 0, 0, scaledWidth, scaledHeight, null); 
        g.dispose();
        return scaledBI;
    }

9
이 기술은 내 요구에 충분하지 않은 이미지를 만듭니다.
morgancodes

1
Image.getScaledInstance (width, height, hints)도 수행합니까?
코드 플레이

1
preserveAlpha가 잘못된 방법을 확인합니까 (imageType의 경우)?
Thilo

@morgancodes에 동의합니다. 동일한 크기로 크기를 조정할 때 OS X Preview와 같이 이미지 품질이 훨씬 떨어집니다. 그들이 더 나은지 확인하기 위해 일부 오픈 소스 라이브러리를 시도합니다.
Thilo

1
"RiyadKalla의 답변에서 imgscalr의 경우 +1입니다.
Thilo

182

FWIW 방금 imgscalr ( Maven central에서 사용 가능) 이라는 Java 용 간단한 이미지 스케일링 라이브러리 (GitHub에서 호스팅되는 Apache 2)를 출시했습니다 .

이 라이브러리는 이미지 스케일링에 대한 몇 가지 다른 접근 방식을 구현하며 (몇 가지 사소한 개선 사항이있는 Chris Campbell의 증분 방식 포함) 요청하면 가장 적합한 방식을 선택하거나 가장 빠르거나 최상의 모습을 제공합니다 ( 요청하십시오).

사용법은 매우 간단하고 정적 메소드입니다. 가장 간단한 사용 사례는 다음과 같습니다.

BufferedImage scaledImage = Scalr.resize(myImage, 200);

모든 작업은 이미지의 원래 비율을 유지하므로이 경우 이미지 크기를 200 픽셀과 200 픽셀의 범위 내에서 이미지 크기를 조정하도록 imgscalr에 요청하면 기본적으로 이미지가 가장 잘 보이고 가장 빠른 방법을 자동으로 선택합니다. 지정되지 않았습니다.

나는 처음에는 이것이 자기 진흥처럼 보인다는 것을 알고 있지만, 나는 똑같은 주제를 인터넷 검색하는 데 상당한 시간을 보냈고 다른 결과 / 접근법 / 생각 / 제안을 계속해서 앉아서 앉아서 결정했습니다. 이미지가 있고 가능한 한 빨리보기 좋거나보기 좋은 이미지를 원한다면 80-85 %의 사용 사례를 다루는 간단한 구현입니다. 작은 이미지에 대한 BICUBIC 보간법으로도 Graphics.drawImage를 수행하면 여전히 가비지처럼 보입니다.


1
리야드, 저는 Scalr 사용을 좋아했습니다. 궁금한 점이 있습니다. 모든 정적 메소드로 API를 어떻게 선택하게 되었습니까? 나는 건축업자에 더 가까운 비슷한 API를 작성했습니다. 처럼 new ImageScaler(img).resizeTo(...).rotate(...).cropTo(...).toOutputBuffer(). 나도 당신의 방식을 좋아하고 그것이 더 간단하다고 생각합니다.
Amir Raminfar

4
나는 그것이라고 생각하기 때문에 아미르는 빌더 패턴이 아니라 라이브러리 이러한 유형의 멋지고 작동, 난 그냥 정적 인 방식의 접근 방식으로 갈 일이 머리 원래 (새 사용자와 내가 imgscalr에서 예상되는 사용량 패턴에 따라 쉽게 (단일 크기 조정 방법 만)은 인스턴스 보유 상태 (빌더 인스턴스)를 갖는 이점이 없었습니다. 그래서 객체 인스턴스화를 저장하고 정적 메서드를 사용했습니다. 나는 그것을 피할 수있는 모든 곳에서 imgscalr 내부의 객체 생성에 대해 강한 입장을 취했습니다. 두 방법 모두 훌륭하게 작동합니다.
리야드 칼라

5
중앙 Maven 저장소에서이를 사용할 수있게 해 +1!
Grilse

이 BufferedImage 클래스는 무엇이며, 왜 안드로이드 스튜디오가 그것을 찾지 못합니까? @Riyad Kalla
Milad

3
@ xe4me BufferedImage는 압축되지 않은 원시 픽셀 데이터를 나타내는 데 사용되는 J2SE JDK (Java2D 프레임 워크의 일부)의 클래스입니다. Android에서는 사용할 수 없으며 Android는 이미지 데이터로 작업하기위한 자체 클래스를 제공합니다.
Riyad Kalla

54

ThumbnailatorMIT 라이센스에 따라 유창한 인터페이스를 갖춘 Java 용 오픈 소스 이미지 크기 조정 라이브러리입니다 .

Java로 고품질 썸네일을 만드는 것은 놀라 울 정도로 어려울 수 있으며 결과 코드가 매우 어려울 수 있기 때문에이 라이브러리를 작성했습니다. Thumbnailator를 사용하면 간단한 유창한 API를 사용하여 상당히 복잡한 작업을 표현할 수 있습니다.

간단한 예

간단한 예를 들어, 이미지를 가져 와서 100 x 100으로 크기를 조정하고 (원본 이미지의 가로 세로 비율을 유지) 파일에 저장하면 단일 명령문으로 달성 할 수 있습니다.

Thumbnails.of("path/to/image")
    .size(100, 100)
    .toFile("path/to/thumbnail");

고급 예

Thumbnailator의 유연한 인터페이스를 통해 복잡한 크기 조정 작업을 간편하게 수행 할 수 있습니다.

다음을 수행한다고 가정 해 봅시다.

  1. 디렉토리에서 이미지를 가져와
  2. 원본 이미지의 가로 세로 비율로 100 x 100으로 크기를 조정합니다.
  3. 의 품질 설정을 사용하여 JPEG에 모두 저장하십시오 0.85.
  4. 파일 이름은 처음에 thumbnail.추가 된 원본에서 가져옵니다.

Thumbnailator로 번역하면 다음과 같이 위의 작업을 수행 할 수 있습니다.

Thumbnails.of(new File("path/to/directory").listFiles())
    .size(100, 100)
    .outputFormat("JPEG")
    .outputQuality(0.85)
    .toFiles(Rename.PREFIX_DOT_THUMBNAIL);

이미지 품질 및 속도에 대한 참고 사항

이 라이브러리는 또한 만족스러운 런타임 성능을 보장하면서 고품질 썸네일을 생성하기 위해 Chet Haase 및 Romain Guy의 Filthy Rich Clients 에서 강조된 점진적 이중 선형 스케일링 방법을 사용합니다 .


1
coobird, API에 대한 훌륭한 작업. 매우 직설적이고 사용하기 쉽습니다.
리야드 칼라

@LordT : Thumbnailator가 사용하기 쉽다는 것을 알게되어 기쁩니다 :)
coobird

500x400 원본 이미지로 80x80 썸네일을 만들려면 어떻게해야합니까? 나는 그것에 대한 옵션을 보지 못했습니다. 감사!
terry

".outputFormat ("JPEG ")"는 설명서의 어디에도 쓰지 않습니다.
Vincent Cantin

Thumbnailator의 API 문서에 사용할 수있는 방법의 전체 목록을 @Vincent - thumbnailator.googlecode.com/hg/javadoc/net/coobird/...을
coobird

12

이를 위해 라이브러리가 필요하지 않습니다. Java 자체로 할 수 있습니다.

Chris Campbell은 이미지 스케일링에 대해 훌륭하고 자세한 글을 작성했습니다 ( 이 기사 참조) .

Chet Haase와 Romain Guy는 그들의 책 Filthy Rich Clients 에 이미지 스케일링에 대한 상세하고 매우 유익한 글을 썼습니다 .


7
Chris의 기사는 처음에 imgscalr를 작성하도록 동기를 부여한 것입니다. 이 같은 질문 (그리고 당신과 같은 답변). 많은 사람들이 이미지에서 멋진 썸네일을 얻는 방법을 반복해서 요구하고 있습니다. 그것을하는 방법에는 여러 가지가 있습니다 .Chris는 항상 최선의 방법 은 아니며 , 수행하려는 작업과 축소의 크기에 달려 있습니다. imgscalr는이 모든 것을 해결하며 1 클래스입니다.
리야드 칼라

2
+1, Filthy Rich 클라이언트는 "Effective java"와 동등한 최고의 Java 책 중 하나이지만 ImgScalr은 내가 게으 르기 때문에 사용하는 것입니다.
Shawn Vader


9

큰 이미지를 다루거나 멋진 결과를 원한다면 자바에서 사소한 작업이 아닙니다. Graphics2D를 통한 재조정 작업을 통해 간단하게 수행하면 고품질 썸네일이 생성되지 않습니다. JAI를 사용하여 수행 할 수 있지만,보기에 좋은 것보다 더 많은 작업이 필요하고 JAI는 OutOfMemory 오류로 JVM을 불쾌하게 만드는 습관이 있습니다.

ImageMagick을 외부 실행 파일로 사용하는 것이 좋습니다. 사용하기 쉽고 작업을 올바르게 수행하므로 필요하지 않습니다.


4

만약 여러분의 maschine에 imagemagick을 설치하는 것이 옵션이라면, im4java를 추천 합니다 . 커맨드 라인 인터페이스에 대한 매우 얇은 추상화 계층이지만 그 기능은 매우 훌륭합니다.


3

Java API는 이미지 및 이미지 품질 저하에 대한 표준 스케일링 기능을 제공하지 않습니다.

이 때문에 JavaCV에서 cvResize를 사용하려고 시도했지만 문제가있는 것 같습니다.

이미지 스케일링을위한 좋은 라이브러리를 찾았습니다. 간단히 pom.xml에 "java-image-scaling"에 대한 종속성을 추가하십시오.

<dependency>
    <groupId>com.mortennobel</groupId>
    <artifactId>java-image-scaling</artifactId>
    <version>0.8.6</version>
</dependency>

maven 저장소에서 최신 버전을 얻을 수 있습니다.

전의. 자바 프로그램에서

ResampleOp resamOp = new ResampleOp(50, 40);
BufferedImage modifiedImage = resamOp.filter(originalBufferedImage, null);

GitHub ( github.com/mortennobel/java-image-scaling.git ) 에서도 사용할 수 있으며 현재 8.7 버전입니다. pom.xml에서 수정이 필요했습니다 (새로운 Maven은 더 이상 1.5를 지원하지 않으므로 소스와 대상을 1.6 이상으로 변경).
Cromax

2

당신은 사용을 시도 할 수 GraphicsMagick 이미지 처리 시스템을 함께 im4java 자바에 대한 COMAND 줄 인터페이스로.

GraphicsMagick에는 많은 장점이 있지만 모두를위한 하나의 장점이 있습니다.

  • GM은 세계 최대 사진 사이트 (예 : Flickr 및 Etsy)에서 수십억 개의 파일을 처리하는 데 사용됩니다.

1

Image Magick가 언급되었습니다. JMagick이라는 JNI 프론트 엔드 프로젝트가 있습니다. 특히 안정적인 프로젝트는 아닙니다 (그리고 Image Magick 자체는 많은 것을 변경하고 호환성을 손상시키는 것으로 알려져 있습니다). 즉, 프로덕션 환경에서 JMagick과 호환 가능한 Image Magick 버전을 사용하여 처리량이 높고 대기 시간이 짧은 비율로 스케일링을 수행 한 경험이 있습니다. 이전에 시도했던 모든 Java 그래픽 라이브러리보다 속도가 훨씬 향상되었습니다.

http://www.jmagick.org/index.html


1

Burkhard의 답변을 사용하지만 그래픽을 만든 후 다음 줄을 추가하십시오.

    g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);

값을 BICUBIC으로 설정할 수도 있습니다. 이미지 품질은 좋아 지지만 비용이 많이 듭니다. 설정할 수있는 다른 렌더링 힌트가 있지만 보간이 가장 주목할만한 효과를 낸다는 것을 알았습니다. 크게 확대하려면 Java 코드가 매우 느릴 것입니다. 더 큰 이미지는 모든 렌더링 힌트가 품질보다 속도를 최적화하도록 설정되어 있어도 약 300 % 확대 / 축소를 시작합니다.



1

성능 스케일러를 작성하는 것은 사소한 것이 아닙니다. 오픈 소스 프로젝트 인 ImageScaler에 대해 한 번 수행했습니다 .

원칙적으로 'java.awt.Image # getScaledInstance (int, int, int)'도 작업을 수행하지만 이에 대한 버그가 있습니다. 자세한 내용은 내 링크를 참조하십시오.


0

GIF 애니메이션 처리에 사용할 수있는 무료 클래스 (AnimatedGifEncoder, GifDecoder 및 LWZEncoder)가있는 솔루션을 개발했습니다.
jgifcode jar을 다운로드하고 GifImageUtil 클래스를 실행할 수 있습니다. 링크 : http://www.jgifcode.com


1
추천 제품과 제휴 한 경우 답변에 언급하십시오.
한스 올슨

와우 ... GIF 애니메이션 이미지의 크기를 조정하는 것입니까? 그리고 무료입니다 ?? 와우 ... 지금 시도해야합니다 ...
gumuruh

예, 이것은 저에 의해 개발되었습니다. 소스 코드는 다음과 같습니다. github.com/rt29/jgifcode- 여기 있습니다. 더 이상 지원하지 않습니다.
Rohit Tiwari


0

가져올 해달라고하면 imgScalr을 내가 테스트하는 이상 @Riyad 카라의 대답처럼 너무 잘, 당신은에서 촬영이 할 수있는 일 피터 발저의 대답은 또 다른 문제를 생각에 @ 피터 발저를 :

 /**
     * utility method to get an icon from the resources of this class
     * @param name the name of the icon
     * @return the icon, or null if the icon wasn't found.
     */
    public Icon getIcon(String name) {
        Icon icon = null;
        URL url = null;
        ImageIcon imgicon = null;
        BufferedImage scaledImage = null;
        try {
            url = getClass().getResource(name);

            icon = new ImageIcon(url);
            if (icon == null) {
                System.out.println("Couldn't find " + url);
            }

            BufferedImage bi = new BufferedImage(
                    icon.getIconWidth(),
                    icon.getIconHeight(),
                    BufferedImage.TYPE_INT_RGB);
            Graphics g = bi.createGraphics();
            // paint the Icon to the BufferedImage.
            icon.paintIcon(null, g, 0,0);
            g.dispose();

            bi = resizeImage(bi,30,30);
            scaledImage = bi;// or replace with this line Scalr.resize(bi, 30,30);
            imgicon = new ImageIcon(scaledImage);

        } catch (Exception e) {
            System.out.println("Couldn't find " + getClass().getName() + "/" + name);
            e.printStackTrace();
        }
        return imgicon;
    }

 public static BufferedImage resizeImage (BufferedImage image, int areaWidth, int areaHeight) {
        float scaleX = (float) areaWidth / image.getWidth();
        float scaleY = (float) areaHeight / image.getHeight();
        float scale = Math.min(scaleX, scaleY);
        int w = Math.round(image.getWidth() * scale);
        int h = Math.round(image.getHeight() * scale);

        int type = image.getTransparency() == Transparency.OPAQUE ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;

        boolean scaleDown = scale < 1;

        if (scaleDown) {
            // multi-pass bilinear div 2
            int currentW = image.getWidth();
            int currentH = image.getHeight();
            BufferedImage resized = image;
            while (currentW > w || currentH > h) {
                currentW = Math.max(w, currentW / 2);
                currentH = Math.max(h, currentH / 2);

                BufferedImage temp = new BufferedImage(currentW, currentH, type);
                Graphics2D g2 = temp.createGraphics();
                g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
                g2.drawImage(resized, 0, 0, currentW, currentH, null);
                g2.dispose();
                resized = temp;
            }
            return resized;
        } else {
            Object hint = scale > 2 ? RenderingHints.VALUE_INTERPOLATION_BICUBIC : RenderingHints.VALUE_INTERPOLATION_BILINEAR;

            BufferedImage resized = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2 = resized.createGraphics();
            g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
            g2.drawImage(image, 0, 0, w, h, null);
            g2.dispose();
            return resized;
        }
    }

0

이 folowing 방법을 사용해보십시오 :

ImageIcon icon = new ImageIcon("image.png");
Image img = icon.getImage();
Image newImg = img.getScaledInstance(350, 350, java.evt.Image.SCALE_SMOOTH);
icon = new ImageIcon(img);
JOptionPane.showMessageDialog(null, "image on The frame", "Display Image", JOptionPane.INFORMATION_MESSAGE, icon);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.