'Mobile Dev/Android'에 해당되는 글 12건

  1. 2010.10.05 BMP 32/16Bit to 24Bit 변환 1
  2. 2010.08.21 Android 간단한 Tip 정리
  3. 2010.08.14 android-opencv 포팅하기 (code.google.com 내용 정리 및 추가) 26
Mobile Dev/Android2010. 10. 5. 16:39

안드로이드의 Bitmap은 기본적으로 16Bit(RGB_565)를 제공하며, 32Bit(ARGB_8888)을 지원한다.
그러나 이미지 처리를 위해서 Bitmap을 24Bit(RGB_888)로 변경을 해야하는 경우도 있다.
이런 경우는 기본 Android Platform에서는 지원을 하지 않고 있다. 변경이 필요하다면 소스코드에서 실제 데이터 값의 변경 작업으로 수행을 해야 하는 것 같다.

기본적으로 24Bit의 헤더 정보를 생성하야 하며, 16Bit 또는 32Bit Bitmap의 색상데이터 값에서 24Bit로 변경하는 작업을 수행해야 한다.

16Bit Bitmap : #RRRRRGGGGGGBBBBB (RGB_565)
24Bit Bitmap : #RRRRRRRRGGGGGGGGBBBBBBBB (RGB_888)
32Bit Bitmap : #AAAAAAAARRRRRRRRGGGGGGGGBBBBBBBB (ARGB_8888)

16Bit를 24Bit 또는 32Bit로의 변환은 헤더정보가 동일하며, Android에서 pixel 값을 int 형으로 추출하므로 동일하게 처리를 할 수 있다. 물론 int 형이 아닌 실 byte[]의 값으로 가져오는 것이 처리 속도면에서는 좋으나, byte에 대한 데이터형의 차이에 때문에 조금 번거로워 int 형의 픽셀값으로 처리를 한다.

* Bitmap 헤더 정보 생성
private static void encode24BMPHeader(DataOutputStream stream, int width,
        int height, int fileSize) throws IOException {
    // the magic number used to identify the BMP file: 0x42 0x4D
    stream.writeByte(0x42);
    stream.writeByte(0x4D);
    stream.writeInt(swapEndian(fileSize));
    // reserved
    stream.writeInt(0);
    // the offset, i.e. starting address of the bitmap data
    stream.writeInt(swapEndian(14 + 40));
    // INFORMATION HEADER (Windows V3 header) the size of this header (40 bytes)
    stream.writeInt(swapEndian(40));
    // the bitmap width in pixels (signed integer).
    stream.writeInt(swapEndian(width));
    // the bitmap height in pixels (signed integer).
    stream.writeInt(swapEndian(height));
    // the number of colour planes being used. Must be set to 1.
    stream.writeShort(swapEndian((short) 1));
    // the number of bits per pixel, which is the colour depth of the image.
    stream.writeShort(swapEndian((short) 24));
    // the compression method being used.
    stream.writeInt(0);
    // image size. The size of the raw bitmap data. 0 is valid for uncompressed.
    stream.writeInt(0);
    // the horizontal resolution of the image. (pixel per meter, signed integer)
    stream.writeInt(0);
    // the vertical resolution of the image. (pixel per meter, signed integer)
    stream.writeInt(0);
    // the number of colours in the colour palette, or 0 to default to 2n.
    stream.writeInt(0);
    // the number of important colours used, or 0 when every colour is important. generally ignored.
    stream.writeInt(0);
}
실제 Bitmap의 헤더 정보에 대한 부분은 구글을 통해 손쉽게 알 수 있을 것이다.

* Bitmap 픽셀 값의 변경 (32/16Bit to 24Bit)
public static byte[] encodeBMPTo24(int[] rgb, int width, int height) throws IOException {
    int padding = (4 - (width % 4)) % 4;
    // the size of the BMP file in bytes
    int fileSize = 14 + 40 + height * (padding + width * 3);

    ByteArrayOutputStream bytes = new ByteArrayOutputStream(fileSize);
    DataOutputStream out = new DataOutputStream(bytes);

    // encode bitmap header (24bit over)
    encode24BMPHeader(out, width, height, fileSize);

    // PALETTE (none for 24 bit depth) IMAGE DATA starting in the bottom left, working right and then up
    // a series of 3 bytes per pixel in the order B G R.
    int colorValue = 0;
    for (int j = height - 1; j >= 0; j--) {
        for (int i = 0; i < width; i++) {
            colorValue = rgb[i + width * j];
    
            out.writeByte(colorValue & 0x000000FF);
            out.writeByte((colorValue >>> 8) & 0x000000FF);
            out.writeByte((colorValue >>> 16) & 0x000000FF);
        }

        // number of bytes in each row must be padded to multiple of 4
        for (int i = 0; i < padding; i++) {
            out.writeByte(0);
        }
    }

    byte[] encodeBytes = bytes.toByteArray();
    bytes.close();

    // quick consistency check
    if (encodeBytes.length != fileSize) {
        throw new RuntimeException("bitmap file size bad match (32bit to 24bit)");
    }

    return encodeBytes;
}

위의 소스를 이용하여 실제 변경하는 소스는 아래와 같다.

public static byte[] decode24Bitmap(Bitmap bitmap) throws IOException {
    
int width = bitmap.getWidth();
    int height = bitmap.getHeight();
    int[] rgb = new int[width * height];
    bitmap.getPixels(rgb, 0, width, 0, 0, width, height);

    byte[] bitmap24Bytes = encodeBMPTo24(rgb, width, height);
    
    bitmap.recycle();
    bitmap = null;
    rgb = null;
  
    // system gc
    //System.gc();

    return bitmap24Bytes;
}

Posted by as.wind.914
Mobile Dev/Android2010. 8. 21. 00:14
* 화면이 자동으로 꺼지는 것을 막는다.
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

* 카메라 줌 설정하기
    "zoom", "taking-picture-zoom" 두가지 설정 방법이 있다. 하드웨어에 따라 달리 사용된다.
    기본적으로 "zoom"을 사용하면 되나, 갤럭시에서는 "taking-picture-zoom"을 사용해야 된다.
    왜 항상 갤럭시는 혼자 저모양인지 모르겠음. (여튼 개발자 최대의 적은 갤럭시인건 분명하다.)
   1. "zoom" parameter 이용
       Camera.Parameters parmeters = camera.getParameters();
       parmeters.set("zoom", String.valueOf(value));
       camera.setParameters(parmeters);
    2. "taking-picture-zoom" parameter 이용
       Camera.Parameters parmeters = camera.getParameters();
       parmeters.set("taking-picture-zoom", String.valueOf(value));
       camera.setParameters(parmeters);

* 카메라 쵀대줌 값 가져오기
    줌 설정과 마찬가지로 "max-zoom", "taking-picture-zoom-max" 두가지 방법이 있다.
    물론 갤럭시는 "taking-picture-zoom-max"을 사용한다. 젠장할~~
    String maxZoomStr = parameters.get("max-zoom");
        또는
    String takingPicMaxZoomStr = parameters.get("taking-picture-zoom-max");

* Intent를 이용한 Web Browser 띄우기
    String webUrl = http://www.google.co.kr;
    Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(webUrl));
    intent.putExtra(Browser.EXTRA_APPLICATION_ID, AppConstants.APP_ID_TAG);
    context.startActivity(intent);
    
    Extra에 자신 어플리케이션의 ID를 넘기게 되면 동일한 ID에 대해서는 항상 동일한 창에 띄워준다.

* WiFi Mac Address 가져오기
    WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
    WifiInfo wifiInfo = wifiManager.getConnectionInfo();
    String macAddress = wifiInfo.getMacAddress();

    ACCESS_WIFI_STATE 사용 권한을 줘야 한다.
Posted by as.wind.914
Mobile Dev/Android2010. 8. 14. 19:35
Android 어플에서 객체인식 및 특징점 검출, 카메라 핸들링, 이미지 처리 등 많은 부분에서 유용하게 쓰이는 OpenCV가 Android로 포팅이 가능한 android-opencv가 code.google.com에 올라와서 간단히 정리해 본다.
이 내용은 http://code.google.com/p/android-opencv/ 내용을 기반으로 정리한 것이다.

위 code.google.com의 페이지에 보듯이 opencv를 android에 포팅하기 위해서는 미리 준비해야 하는 것들이 있다.
일단 window 환경에서 포팅하는 것으로 정리한다.

1. android-opencv 포팅을 위한 사전 준비
    - android-sdk : 기본으로 준비해야 함. 
        www.android.com에서 다운받아서 설치하면 된다.
    - android-ndk : crystax ndk r4 이용
        code.google.com의 android-opencv는 Android의 기본 NDK로는 build가 되지 않는다.
        Down : http://www.crystax.net/android/ndk-r4.php
    - cygwin
        windows에서 가상 리눅스 환경을 만들어준다.
        Down : http://www.cygwin.com/
    - android-opencv source
        SVN을 이용하여 checkout 받는다. (http://android-opencv.googlecode.com/svn/trunk/)
        SVN에 접속하면 opencv, samples 모두 사용한다. 먼저 opencv를 빌드 한후에 samples를 빌드하여
        테스트한다.

2. cygwin 설치
    - 먼저 android-opencv를 빌드하기 위해 리눅스 환경을 만들기 위해 다운로드 후 설치한다.
    - 설치하는 절차는 간략히 설명한다. 부족하면 검색하면 좋은 자료가 많다.
    - [Choose A Download Site] 화면이 나올때 까지는 기본 설정 또는 경로만 변경하고 지나가면 된다.
    - [Choose A Download Site]도 적당한 사이트를 선택하고 Next (난 ftp://ftp.kaist.ac.kr을 선택했음.)
    - 다음 화면이 중요하다. 리눅스 환경에서 android-opencv를 빌드 시 필요한 패키지를 선택하여
      설치하는 부분이다.
       너무 걱정하지 말자. 모두 설치 후 필요한 패키지는 다시 설치파일을 실행하여 똑같이 진행해서 이 화면에서
       다시 선택하여 설치가 가능하다.
       설치 할 항목
            Devel : gcc-core, gcc-g++, make, swig
            Editor : vim    
    - 그 다음부터는 그냥 두면 설치가 된다.
    - 설치 완료 후 실행하게 되면 리눅스 환경의 콜솔 창이 하나 뜨고 최초 실행 시 window 로그인 계정으로
       /home/[user] 형식으로 폴더가 생성이된다. 기본 사용 쉘은 bash shell 이다.

3. crystax ndk r4 
    - 해당 사이트에서 다운로드 받아 적당한 곳에 압축을 풀면된다.
    - 압축을 푼 후 cygwin이 설치 된 /home/[user]/ 아래 복사를 한다. cygwin 환경에서 빌드를 진행하기 위함.
    - 저의 빌드 환경에서의 패스는 /home/ukzzang/android-ndk-r4-crystax 임.

4. android-opencv source
    - svn을 이용하여 checkout 받은 뒤 체크 받은 소스를 cygwin이 설치 된 /home/[user]/ 아래에
       android-opencv로 복사한다. 경로를 변경해도 무방하다.

이로써 android-opencv를 빌드하기 위한 사전 준비 작업은 끝났다.

5. android-opencv build
    5.1. cygwin 환경 설정
        - windows 환경에서 패스 설정
            [바탕화면 컴퓨터] -> [설정] -> [고급 시스템 설정] -> [환경변수]의 path 부분에
            C:\cygwin\home\ukzzang\android-ndk-r4-crystax;C:\cygwin\bin; 추가한다.
        - cygwin 실행 후 bash 환경 파일 수정 (.bashrc 파일 수정 후 적용)
            vi ~/.bashrc 실행 (사용자 home 경로에서 실행)
        - 아래 내용을 추가한다.
            export PATH=$PATH:/home/ukzzang/android-ndk-r4-crystax
            export ANDROID_NDK_ROOT=/home/ukzzang/android-ndk-r4-crystax
            source ~/.bashrc 환경 설정 정보 재적용
    5.2. android-opencv build
        - cd /home/ukzzang/android-opencv/opencv 로 이동
        - sh build.sh
        - 뭐 빌드는 아주 간단하죠 ... build 하는데 시간이 꽤 걸리는 편이다. 천천히 기다리자
        - 빌드가 완료되면 ....../opencv/android/libs/armeabi 아래에 libopencv.so 파일이 생성된다.

여기까지로 android-opencv 빌드가 끝났다 ... 그럼 다음올 svn에서 받은 samples의 CVCamera를 빌드하여
실행해서 테스트 해보겠다.

6. android-opencv test
    6.1. CVCamera Sample Build
        - 테스트는 samples 안에 있는 CVCamera Project를 이용하여 진행하겠다.
        - 먼저 CVCamera Project를 NDK로 빌드한다. android-opencv 빌드와 동일하다.
        - ......./samples/CVCamera로 경로 이동
        - sh build.sh 실행하면 빌드 된다.
           혹시 경로부분에서 오류가 발생하면 jni 폴더의 Android.mk 파일을 vi로 열어서 수정하고 다시 빌드.
        - 위 화면처럼 빌드가 완료되면 libs/armeabi 아래에 libcvcamera.so 파일이 생성되어 있다.
        - 프로젝트 빌드 끝 ... 이제 Eclipse에서 프로젝트를 생성하고 실행만 해보면 된다.
    6.2. Eclipse Project Create & Test
        - Eclipse에 Android Project를 생성하고 cygwin에서 빌드한 CVCamera를 Import 한다.
        - 빌드 한 android-opencv 밑에 가면 android로 빌드하면서 생성 된 폴더가 있는데 안의 jni 밑의 Java 
           파일들도 Import 한다. 그리고 당연히 libandroid-opencv.so 파일도 프로젝트의 libcvcamera.so가 있는
           위치에 복사한다.
        - 프로젝트를 폰이나 에뮬에서 테스트하면 된다.
        - 카메라 뷰가 보이며, 뷰에 보이는 영상이 메뉴에서 선택한 알고리즘에 따라 특징 점들이 추출되어 보이게 된다.

이걸로 정말 끝 ...
       
Posted by as.wind.914