2016-06-08 5 views
0

때때로 내 이미지가 너무 큰 내가이 오류 비율을 mantaining 동안 .크기 조정은 가능한 한 큰 이미지

if (targetWidth * targetHeight >= Integer.MAX_VALUE || targetWidth * targetHeight < 0) { 
     System.out.println("Target image too big... Size will be adjusted!"); 
     if (targetWidth > targetHeight) { 
      targetWidth = (int)Math.sqrt((Integer.MAX_VALUE) * (float)(targetWidth/targetHeight)); 
      targetHeight = (Integer.MAX_VALUE)/targetWidth; 
     } else { 
      targetHeight = (int)Math.sqrt((Integer.MAX_VALUE) * (float)(targetHeight/targetWidth)); 
      targetWidth = (Integer.MAX_VALUE)/targetHeight; 
     } 
    } 

나는 여전히 같은 문제를 얻을, 내 조건을 만족 :

나는 다음과 같은 공식으로 돌아가 셨습니다. 나는

WIDTH * HEIGHT < Integer.MAX_VALUE

명확하지 내가 어떤 도움을 찾고 조건 가 추측?

편집 : 그럴하기 위해 BufferedImage의 생성자에 전달할 수있는 가장 큰 가능한 크기에없는 NegativeArraySizeException을 얻을 무엇 :

at java.awt.image.DataBufferByte.(Unknown Source)

+0

배열 크기를 확인하십시오 : http://stackoverflow.com/questions/31382531/why-i-cant-create-an-array-with-large-size –

+0

그 오류가 나타나지 않습니다. –

+0

너비 및 높이 정수? width * height가 Integer.MAX_VALUE보다 실제로 큰 경우 int에 제품을 보유 할 수 없다는 의미입니다. Trying은 그것을 잘라 버릴 것이므로, Java의 결과는 true 값과 상관없이 항상 <= Integer.MAX_VALUE가됩니다. 한 가지 방법은 너비와 높이를 곱하기 전에 항상 제품을 고정 할 수있는 데이터 유형 (예 : long)으로 변환하는 것입니다. 그 후 Integer.MAX_VALUE와의 비교는 잘 작동합니다. –

답변

1

논의 후 나는이 문제에 대한 진짜 질문은 생각 BufferedImage 제한은 Raster 클래스 (ref)의 제한으로 인해 byte[Integer.MAX_VALUE]이있는 것과 같은 제한입니다. 또한 플랫폼 및 구현에 따라 헤더의 오버 헤드가 있습니다. 그래서 long 길이의 안전 버퍼를 권장합니다.

(Integer.MAX_VALUE - 8)/4은 안전한 제한이어야합니다.

참고 : 은 각 픽셀 크기 (ref)를 고려해야합니다. 예를 들어 BufferedImage.TYPE_4BYTE_ABGR은 픽셀 당 4 바이트입니다. 이 경우 귀하의 지역 제한은 Integer.MAX_VALUE/4입니다. 물론 각 픽셀에서 사용하는 바이트 수는 사용하는 유형에 따라 다릅니다. 테스트 최대 영역을 각 픽셀을 나타내는 바이트 수로 조정하십시오. 그 점을 이해하려면 API를 살펴 봐야합니다 : https://docs.oracle.com/javase/7/docs/api/java/awt/image/BufferedImage.html. 종횡비 계산을 유지하면서 화상의 크기를 조정하기 위해


꽤 간단

double aspectRatio = width/height; 

if (aspectRatio < 1) { 
    // taller than wide 
    targetHeight = maxDimension; 
    targetWidth = (int)(targetHeight * aspectRatio); 
} else { 
    // wider than tall 
    targetWidth = maxDimension; 
    targetHeight = (int)(targetWidth/aspectRatio); 
} 

이미지의 전체 영역을 기반으로 maxDimension 계산하는 문제이다. 논증을 위해서 우리의 최대 면적이 Integer.MAX_VALUE - 8 (relatively safe)이라고 가정 해 봅시다. 우리는 이것을 대수학을 사용하여 추정 할 수 있습니다. 위의 수식을 사용하면 width * height = area을 알 수 있습니다. 최대 영역을 풀려면 두 가지 방법이 필요합니다.

aspectRatio < 1 위해 우리는를 얻기 위해 식으로 폭 대체 :

height * height * aspectRatio = area

높이 해결 :

  • height^2 * aspectRatio = area
  • height^2 = area/aspectRatio
  • height = Math.sqrt(area/aspectRatio
012,351,641 asptectRatio >= 1 들어

우리는 그것을 얻기 위해 formulat과 높이를 대체 :

width * width/aspectRatio = area

폭 풀면 : aspectRatio

  • 폭^2/aspectRatio = 지역
  • 폭^2 = 면적 *
  • width = Math.sqrt (영역 * aspectRatio)

아니요 우리는 최대 영역의 모양을 고려하여 기본 공식을 업데이트 할 수 있습니다 W : 물론

public static final long MAX_AREA = (Integer.MAX_VALUE - 8)/4; 

if (aspectRatio < 1) { 
    targetHeight = Math.sqrt(MAX_AREA/aspectRatio); 
    targetWidth = (int)(targetHeight * aspectRatio); 
} else { 
    // wider than tall 
    targetWidth = Math.sqrt(MAX_AREA * aspectRatio); 
    targetHeight = (int)(targetWidth/aspectRatio); 
} 

, 이것은 당신이 당신의 최대 영역 임계 값을 초과하는 경우 테스트의 기본 질문을 남긴다. 그것은 int 이외의 것으로 끝나야합니다.

public static final long MAX_AREA = (Integer.MAX_VALUE - 8)/4; 
long area = (long)width * (long)height; 

if(area < MAX_AREA) { 
    // recalculate size 
} 

그렇지 않으면 오버플로 문제가 발생합니다.

+0

당신은 내가 가지고있는 것과 같은 공식이 있습니다. –

+0

적절한 제한 및 테스트 영역을 강력하게 추가했습니다. –

+0

내가 알고 싶은 건 BufferedImage 제한과 그 이유입니다. –