Bitmap 이미지를 파일로 저장하는 방법

|

Bitmap 이미지를 파일로 저장하는 코드는 다음과 같습니다.


private void saveBitmapAsFile(Bitmap bitmap, String filepath) {
    File file = new File(filepath);
    OutputStream os = null;

    try {
      file.createNewFile();
      os = new FileOutputStream(file);

      bitmap.compress(CompressFormat.PNG, 100, os);

      os.close();
    } catch (Exception e) {
      e.printStackTrace();
    } 
  }

이미지의 Rotation 정보를 획득하고 회전하는 방법

|

안드로이드에서 사진을 ImageView 등에 출력할 때, 이미지의 Rotation 정보를 획득하여 적절하게 회전시켜주는 방법입니다.


이미지의 Orientation 정보 획득

public int getOrientationOfImage(String filepath) {
    ExifInterface exif = null;

    try {
      exif = new ExifInterface(filepath);
    } catch (IOException e) {
      e.printStackTrace();
      return -1;
    }

    int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, -1);

    if (orientation != -1) {
      switch (orientation) {
        case ExifInterface.ORIENTATION_ROTATE_90:
          return 90;

        case ExifInterface.ORIENTATION_ROTATE_180:
          return 180;

        case ExifInterface.ORIENTATION_ROTATE_270:
          return 270;
      }
    }

    return 0;
  }


Image 회전

  public Bitmap getRotatedBitmap(Bitmap bitmap, int degrees) throws Exception {
    if(bitmap == null) return null;
    if (degrees == 0) return bitmap;
    
    Matrix m = new Matrix();
    m.setRotate(degrees, (float) bitmap.getWidth() / 2, (float) bitmap.getHeight() / 2);

    return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), m, true);;
  }

간단한 애니메이션 예제

|

안드로이드에서 간단한 애니메이션(Animation)을 구현하는 방법을 알아보도록 하겠습니다.


투명도 조절

다음 XML 파일을 res/anim 폴더 아래에 만들어줍니다. 만약, anim 폴더가 존재하지 않는 경우는 직접 만들어주면 됩니다.

alpha.xml

<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
  android:duration="3000"
  android:fromAlpha="0.0"
  android:interpolator="@android:anim/accelerate_interpolator"
  android:toAlpha="1.0" />

투명도 값을 의미하는 alpha 값은 0.0이 완전 투명, 1.0이 완전 불투명을 의미합니다. 그리고 duration의 단위는 msec(1/1000 초)입니다.


MainActivity.java

public class snowSample extends Activity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.snow_intro);

    ImageView imageview = (ImageView) findViewById(R.id.img_intro_logo);
    Animation anim = AnimationUtils.loadAnimation(this, R.anim.alpha);
    imageview.startAnimation(anim);
  }
}


객체 움직임

객체 움직임을 나타내는 Tween Animation 예제를 살펴보겠습니다.

scale.xml

<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
  android:duration="3000"
  android:fromXScale="1.0"
  android:fromYScale="1.0"
  android:interpolator="@android:anim/accelerate_interpolator"
  android:pivotX="50%p"
  android:pivotY="50%p"
  android:toXScale="0.5"
  android:toYScale="0.5" />


set 태그 사용법

set 태그는 여러 종류의 Animation을 하나의 세트로 묶어서 동작하도록 하는 태그입니다. 예제는 다음과 같습니다.

set1.xml (첫 번째 예제)

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
  android:interpolator="@android:anim/accelerate_interpolator">
  <alpha
    android:duration="5000"
    android:fromAlpha="0.0"
    android:toAlpha="1.0" />

  <scale
    android:duration="3000"
    android:fromXScale="1.0"
    android:fromYScale="1.0"
    android:pivotX="50%p"
    android:pivotY="50%p"
    android:startOffset="3000"
    android:toXScale="0.5"
    android:toYScale="0.5" />
</set>

startOffset은 시작 시간을 의미합니다. 위의 Animation 내용을 살펴보면, Animation이 시작되면서 5 초(5000 msec)동안 투명도가 서서히 변하는 애니메이션이 구동됩니다. 그리고, 3 초 후에 크기 변경 애니메이션이 3 초동안 실행됩니다. 즉, Animation 효과들이 순차적 또는 동시에 실행되도록 할 수 있습니다.


set2.xml (두 번째 예제)

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
  android:interpolator="@android:anim/accelerate_interpolator">
  <alpha
    android:duration="5000"
    android:fromAlpha="0.0"
    android:toAlpha="1.0" />

  <scale
    android:duration="3000"
    android:fromXScale="1.0"
    android:fromYScale="1.0"
    android:pivotX="50%p"
    android:pivotY="50%p"
    android:startOffset="3000"
    android:toXScale="0.5"
    android:toYScale="0.5" />

  <translate
    android:duration="3000"
    android:fromXDelta="0"
    android:fromYDelta="0"
    android:startOffset="5000"
    android:toXDelta="0"
    android:toYDelta="50%p" />

  <rotate
    android:duration="1000"
    android:fromDegrees="0"
    android:pivotX="30%p"
    android:pivotY="50%p"
    android:startOffset="7000"
    android:toDegrees="360" />

</set>

URL을 이용해서 Bitmap 가져오기

|

URL을 이용해서 HTTP 기반으로 이미지를 다운로드하는 코드입니다.

일단, 인터넷 경로를 통해 다운을 받기 위해서는 AndroidManifest.xml 파일에 다음 permission을 추가해줘야 합니다.


Permission

<uses-permission android:name="android.permission.INTERNET" />


URL을 이용하여 Bitmap 가져오는 함수

private Bitmap getImageFromURL(String imageUrl) {
    Bitmap bitmap = null;

    try {
      URL url = new URL(imageUrl);
      URLConnection connection = url.openConnection();
      connection.connect();

      int size = conn.getContentLength();
      BufferedInputStream bis = new BufferedInputStream(connection.getInputStream(), size);
      bitmap = BitmapFactory.decodeStream(bis);

      bis.close();
    } catch (Exception e) {
      e.printStackTrace();
    }

    return bitmap;
  }

내부/외부 저장소 용량 체크

|

모바일 디바이스내 내부/외부 저장소의 용량을 확인하는 함수입니다.


MemoryUtil.java

public class MemoryUtil {

  public static void showStatus() {
    Log.i("", "< MemoryStatus >");
    Log.i("", "Total Internal MemorySize : " + getFormattedSize(GetTotalInternalMemorySize()));
    Log.i("",
        "Available Internal MemorySize : " + getFormattedSize(GetAvailableInternalMemorySize()));

    if (IsExternalMemoryAvailable() == true) {
      Log.i("", "Total External MemorySize : " + getFormattedSize(GetTotalExternalMemorySize()));
      Log.i("",
          "Available External MemorySize : " + getFormattedSize(GetAvailableExternalMemorySize()));
    }
  }

  private static boolean IsExternalMemoryAvailable() {
    return android.os.Environment.getExternalStorageState()
        .equals(android.os.Environment.MEDIA_MOUNTED);
  }

  private static long GetTotalInternalMemorySize() {
    File path = Environment.getDataDirectory();
    StatFs stat = new StatFs(path.getPath());
    long blockSize = stat.getBlockSize();
    long totalBlocks = stat.getBlockCount();

    return totalBlocks * blockSize;
  }

  private static long GetAvailableInternalMemorySize() {
    File path = Environment.getDataDirectory();
    StatFs stat = new StatFs(path.getPath());
    long blockSize = stat.getBlockSize();
    long availableBlocks = stat.getAvailableBlocks();

    return availableBlocks * blockSize;
  }

  private static long GetTotalExternalMemorySize() {
    if (IsExternalMemoryAvailable() == true) {
      File path = Environment.getExternalStorageDirectory();
      StatFs stat = new StatFs(path.getPath());
      long blockSize = stat.getBlockSize();
      long totalBlocks = stat.getBlockCount();

      return totalBlocks * blockSize;
    }

    return -1;
  }

  private static long GetAvailableExternalMemorySize() {
    if (IsExternalMemoryAvailable() == true) {
      File path = Environment.getExternalStorageDirectory();
      StatFs stat = new StatFs(path.getPath());
      long blockSize = stat.getBlockSize();
      long availableBlocks = stat.getAvailableBlocks();

      return availableBlocks * blockSize;
    }

    return -1;
  }

  private static String getFormattedSize(long size) {
    String suffix = "";

    if (size >= 1024) {
      suffix = "KB";
      size /= 1024;
      if (size >= 1024) {
        suffix = "MB";
        size /= 1024;
      }
    }

    StringBuilder sb = new StringBuilder(Long.toString(size));

    int commaOffset = sb.length() - 3;
    while (commaOffset > 0) {
      sb.insert(commaOffset, ',');
      commaOffset -= 3;
    }

    sb.append(suffix);

    return sb.toString();
  }
}