2013-10-29 5 views
2

나는 다음과 같은 코드를 가지고 :BufferedImage의 크기를 조정하고는 JPG의 이미지를 검정색 배경에서 결과를 파일로 저장

import java.awt.Graphics2D; 
import java.awt.Image; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import javax.imageio.ImageIO; 


public class JavaApplication 
{ 
    public static void main(String[] args) throws Exception 
    { 
     File orig = new File ("/home/xxx/Pictures/xxx.jpg"); 
     BufferedImage bm1 = ImageIO.read(orig); 

     Image scaled = bm1.getScaledInstance(100, 200, BufferedImage.SCALE_SMOOTH); 
     BufferedImage bm2 = toBufferedImage(scaled); 

     File resized = new File ("/home/xxx/Pictures/resized.jpg"); 
     ImageIO.write(bm2, "jpg", resized); 
    } 

    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); 

     bimage.getGraphics().drawImage(img, 0, 0 , null); 
     return bimage; 
     } 
} 

나는 .PNG 파일에이 코드를 사용하는 경우, 그것은 잘 작동하고 파일 크기를 조정 예상했다. 그러나 jpg 파일에서 검은 색 배경이됩니다.

getScaledInstance() 코드를 제거하고 ImageIO.write(bm1, "jpg", resized)을 사용하여 원래 bm1을 디스크에 다시 쓰려고하면 정상적으로 작동합니다. getScaledInstance()을 사용하여 크기를 조정하고 그 결과로 ImageBufferedImage으로 변환하려고 할 때만 완전히 검정색 배경 파일이 생성됩니까?

이 문제를 해결하는 방법이나 내가 잘못하고있는 것에 대한 아이디어가 있습니까?

+0

이미지 스케일링을 한 지 오래되었지만이 기사는 유용합니다. https : //today.ja va.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html. 어쩌면 거기에있는 기술 중 일부가 도움이 될까요? – Ash

+0

@Ash 너는 나에게 tl을 줄 수 있니,이 박사? 어쨌든'Image.getScaledInstance()'를 사용하지 않고 BufferedImage.getScaledInstance()를 사용하고 있습니다. –

+0

문제는 당신이'getScaledInstance()'를 사용하고 있다는 것입니다. 'Image', *로 즉시 반환하지만이 시점에서 이미지의 크기가 아직 조정되지 않았습니다 *. 그래서 나중에이 이미지를 사용하여'drawImage'를 호출하면 사실상 아무 작업도 수행하지 않습니다. 업데이트 :'Image' 나'BufferedImage'에서'getScaledInstance'를 사용하면 아무런 차이가 없습니다. – haraldK

답변

9

코드를 실행하면 검정색 배경이 나타나지 않지만 이미지의 색상이 이상하게 보입니다 (채널이 엉망으로 보임). (JPEG는 투명도를 지원하지 않기 때문에, 알파 없음) 내가 toBufferedImage(..)BufferedImage.TYPE_INT_RGB에 이미지 유형을 변경

은 모두 잘 작동합니다.

JPEG 이미지를 기록 할 때 ImageIO는 관련이 점을 고려하지 않는 것을 여전히 이상한 ... 방법, 비동기 이미지 스케일링으로

이 (getScaledInstance(..)이처럼) 문제가 아니었다, 나는 이미지 크기 조정 확인했다 계속하기 전에 완료되었지만 결과에 아무런 영향을 미치지 않습니다.

MediaTracker 완전히 이미지를로드 사용하려면

public static void loadCompletely (Image img) { 

    MediaTracker tracker = new MediaTracker(new JPanel()); 
    tracker.addImage(img, 0); 
    try { 
     tracker.waitForID(0); 
    } catch (InterruptedException ex) { 
     throw new RuntimeException(ex); 
    } 
} 

편집
다음 비율을 유지 나는 이미지의 크기를 조정하는 데 사용하는 코드는 (다른 크기 조정 방법은 당신이 업 스케일링 또는 다운 스케일링하고 있는지에 따라입니다, 지역 평균화에 대한보다 빠른 대안) :

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

감사합니다. 한 가지 더 .. 당신이 원래 크기를 고려하면서 이미지의 크기를 조정할 라이브러리를 알고 있습니까? 예를 들어 100x100을 새로운 크기로 지정하면 100x100 크기로 조정하고 이미지를 왜곡하지 않습니다. 원래 비율을 염두에두고 100x100의 가장 가까운 크기로 원래 비율을 유지하면서 크기를 조정합니까? –

+0

답변에 내 크기 조정 코드를 추가했는데 주석이 너무 길었습니다. –

+1

이 기능은 대부분의 이미지에서 훌륭하게 작동하지만 일부 이미지에서는 이상한 색상을 제공합니다. 예 : http://i.imgur.com/8cZl4NJ.jpg의 경우 http://i.imgur.com/DLFwNSM.jpg로 크기가 조정되고 http://i.imgur.com/bF9gqlv.jpg의 경우 크기가 조정됩니다. http://i.imgur.com/hiS3Nh7.jpg. 어떤 아이디어? –