IT_Programming/Java

jpg, gif 파일의 크기 구하는 방법

JJun ™ 2008. 9. 7. 23:59

인터넷 쇼핑몰 등의 사이트에서 유용하게 쓰일 수 있다.

 

==================================================================================================

 

[GIF]

- width 정보 : 6~7번째 바이트 / Short Endian 으로 합침

- height 정보 : 8~9번째 바이트 / Short Endian 으로 합침

 

--------------------------------------------------------------------------------------------------

 

[JPEG]

- 4 바이트를 읽어들임

- marker 정보: 2~3 번째 바이트 / Big Endian 으로 합침

- skip size 정보: 3~4 번째 바이트 / Big Endian 으로 합침

- marker 정보가 지원하는 SOF marker 인지 확인

- 지원하는 marker 가 발견될 경우 추가 6바이트를 읽어 들임

  ( 0xc0, 0xc1, 0xc2, 0xc3, 0xc5, 0xc6, 0xc7, 0xc9, 0xca, 0xcb, 0xcd, 0xce, 0xcf 중 하나)

- width 정보 : 읽어들인 6 바이트에서 1~2 바이트 / Big Endian 으로 합침

- height 정보 : 읽어들인 6 바이트에서 3~4 바이트 / Big Endian 으로 합침

- 위의 단계 중 4번째 단계에서 지원하는 marker가 발견되지 않을 경우 2번째 단계에서 산출한

   skipsize에서 2를 뺀 바이트 만큼을 skip하고 다시 1부터 루프를 돌림.

 

==================================================================================================

* Short Endian: 2 바이트로 구성된 값을 논리합 할 때 하위 비트를 큰 값으로(8비트 좌향 shift) 연산한다.

* Big Endian: short endian과 반대로 상위 비트를 8비트 좌향 shift 시켜 하위 비트와 논리합한다.

==================================================================================================

 

/*
 * File : ImgSize.java
 * brief : Get ImgFile's width and height
 */

import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;

 

public class ImgSize

{
 
 private int width;
 private int height;
 private InputStream in;

 public boolean check()
 {
  width = 0;
  height = 0;
  
  try
  {

   // read()함수를 통해 읽은 정수값이 음수일 수 있기 때문
   int b1 = read() & 0xff;
   int b2 = read() & 0xff;
   // 0xff (0x000000ff)로 마스크 함으로써 32비트 정수값의 첫 비트에 있는  음수 비트를 없애주기 위함 


   if(0x47 == b1 && 0x49 == b2)
   {
    return chkGIF();
   }
   else if(0xff == b1 && 0xd8 == b2)
   {
    return chkJPG();
   }
   else
   {
    return false;
   }
  }catch(IOException ioe)
  {
   return false;
  }
 }
 
 private boolean chkGIF() throws IOException
 {
  final byte[] GIF_MAGIC_87A = {0x46, 0x38, 0x37, 0x61};
  final byte[] GIF_MAGIC_89A = {0x46, 0x38, 0x39, 0x61};
  byte[] a = new byte[11];
  
  if(read(a) != 11)
  {
   return false;
  }
  if((!equals(a, 0, GIF_MAGIC_87A, 0, 4)) &&
    (!equals(a, 0, GIF_MAGIC_89A, 0, 4)))
  {
   return false;
  }
  
  width = getLittleEndian(a, 4);
  height = getLittleEndian(a, 6);
  
  return (width >0 && height > 0);
 }
 
 private boolean chkJPG() throws IOException
 {
  byte[] data = new byte[12];
  
  while(true)
  {
   if( read(data, 0, 4) != 4)
   {
    return false;
   }
   int marker = getBigEndian(data, 0);
   int size = getBigEndian(data, 2);
   
   if((marker & 0xff00) != 0xff00)
   {
    return false;
   }
   
   if(marker >= 0xffc0 && marker <= 0xffcf && marker != 0xffc4 &&
     marker != 0xffc8)
   {
    if(read(data, 0, 6) != 6)
    {
     return false;
    }    
    width = getBigEndian(data, 3);
    height = getBigEndian(data, 1);
    
    return (width >0 && height > 0);
   }
   else
   {
    skip(size -2);
   }
  }
 }
 
 private boolean equals(byte[] a1, int offs1, byte[] a2, int offs2, int num)
 {
  while(num-- > 0)
  {
   if(a1[offs1++] != a2[offs2++])
   {
    return false;
   }
  }
  return true;
 }
 

 // byte값에 0xff를 masking 한 다음, 두 값을 논리합하고 있다.

 // 이 때 상위 byte를 8비트 좌향 shift 시키고, 하위 byte를 논리합하는데,

 // 이렇게 함으로써 16 비트의 공간의 각각 반에 상위 바이트와 하위 바이트를 위치 시킬 수 있다.
 private int getBigEndian(byte[] a, int offs)
 {
  return (a[offs] & 0xff) << 8 | (a[offs + 1]& 0xff);
 } 

// 아래와 같은 방법으로 값을 뽑아낼 수 있다.

// 상위비트: (a >> 8) & 0xff

// 하위비트: a & 0xff

 private int getLittleEndian(byte[] a, int offs)
 {
  return (a[offs] & 0xff) | (a[offs + 1]& 0xff) << 8;
 }


 private int read() throws IOException
 {
  return in.read();
 }


 private int read(byte[] a)throws IOException
 {
  if (in != null)
  {
   return in.read(a);
  }
  return 0;
 } 


 private int read(byte[] a, int offset, int num) throws IOException
 {
  if(in != null)
  {
   return in.read(a, offset, num);
  }
  return 0;
 }


 private void skip(int num) throws IOException
 {
  in.skip(num);
 }


 public int getHeiht()
 {
  return height;
 }


 public int getWidth()
 {
  return width;
 }


 public boolean SetImage(String imagepath)
 {
  try
  {
   in = new FileInputStream(imagepath);
   return check();
  }
  catch(Exception e)
  {
   return false;
  }
  finally {
   try{
    if(in != null) in.close(); } catch(Exception ie){}
  }
 }
 
 public ImgSize() {}


 public static void main(String[] args) {
  ImgSize imgsize = new ImgSize();
  if(imgsize.SetImage("bbb.gif"))
  {
   System.out.println("width : " + imgsize.getWidth());
   System.out.println("height : " + imgsize.getHeiht());
  }
 }
}

'IT_Programming > Java' 카테고리의 다른 글

Java performance tips  (0) 2008.09.08
DB 관련된 한글 처리 방법  (0) 2008.09.08
Java 기타 튜닝법   (0) 2008.09.07
JAVA Tip & Tuning Technic   (0) 2008.09.07
[펌] Annotation (주석)   (0) 2008.08.28