본문 바로가기
안드로이드/센서

안드로이드 사진 기능

by 김어찐 2022. 6. 25.
728x90

카메라 기능이 구현되어 있는 Activity를 실행하여 사진을 촬영할 수 있다.
만약 카메라 기능이 구현되어 있는 애플리케이션이 다수 설치되어 있다면 앱을 선택하면 된다.
기본 카메라 사용하는 방법을 사용하면 사진 원본이 아닌 썸네일 이미지를 가져오게 된다.

 

원본 이미지 가져오기

안드로이드에서 촬영된 사진의 원본을 가져오려면 촬영된 사진을 파일로 저장한 다음 파일로부터 이미지 데이터를 가져오는 방식으로 개발해야 한다.

 

 

사진 보정하기

카메라로 촬영된 사진은 다음의 이유 때문에 보정을 해야한다.
ImageView는 특정 크기 보다 큰 이미지는 표현할 수 없다. 이 크기는 단말기 마다 다르다.
이미지의 용량이 너무 크면 서버와 송수신 할 때 데이터를 너무 많이 사용하게 된다.
스마트폰을 세워서 촬영할 경우 사진이 90도로 회전되어 있다.

package com.example.camera

import android.content.Intent
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Matrix
import android.media.ExifInterface
import android.net.Uri
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.provider.MediaStore
import androidx.core.content.FileProvider
import kotlinx.android.synthetic.main.activity_main.*
import java.io.File

class MainActivity : AppCompatActivity() {

    lateinit var contentUri:Uri

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val file_path = getExternalFilesDir(null).toString()

        button.setOnClickListener {
            val intent1 = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
            startActivityForResult(intent1,1)
        }

        button2.setOnClickListener {
            val intent2 = Intent(MediaStore.ACTION_IMAGE_CAPTURE)

            // 촬영한 사진이 저장될 파일이름
            val file_name = "/temp_${System.currentTimeMillis()}.jpg"
            // 경로 + 파일 이름
            val pic_path = "$file_path/$file_name"
            val file = File(pic_path)

            // 사진이 저장될 위치를 관리하는 uri 객체
            contentUri = FileProvider.getUriForFile(this,"kr.co.eojin.camera.file_provider",file)

            if(contentUri != null){
                intent2.putExtra(MediaStore.EXTRA_OUTPUT,contentUri)
                startActivityForResult(intent2,2)
            }
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        when(requestCode){
            1 -> {
                if(resultCode == RESULT_OK){
                    // 사진정보 "data"에 저장
                    val bitmap = data?.getParcelableExtra<Bitmap>("data")
                    // 썸네일 이미지
                    imageView.setImageBitmap(bitmap)
                }
            }
            2 ->{
                if(resultCode == RESULT_OK){
                    val bitmap =BitmapFactory.decodeFile(contentUri.path)

                    val degree = getDegree(contentUri,contentUri.path!!)

                    imageView.setImageBitmap(bitmap)

                    val bitmap2 = resizeBitmap(1024,bitmap)
                    val bitmap3 = rotateBitmap(bitmap2,degree)

                    imageView.setImageBitmap(bitmap3)

                    // 사진 삭제
                    val file = File(contentUri.path)
                    file.delete()
                }
            }
        }
    }

    // 사진의 사이즈를 조정하는 메서드
    fun resizeBitmap(targetWidth:Int,source:Bitmap):Bitmap{
        // 이미지의 비율을 계산한다.
        val ratio = targetWidth.toDouble()/source.width.toDouble()
        //보정될 세로 길이를 구한다.

        val targetHeight = (source.height * ratio).toInt()
        // 크기를 조정한 bitmap객체를 생성한다.
        val result = Bitmap.createScaledBitmap(source,targetWidth,targetHeight,false)
        return result
    }

    // 이미지의 회전 각도값을 구한다
    fun getDegree(uri:Uri, source:String) : Float{
        var exif:ExifInterface? = null

        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){

            val photoUri = MediaStore.setRequireOriginal(uri)
            val stream = contentResolver.openInputStream(photoUri)
            exif = ExifInterface(stream!!)
        }
        else{
            exif = ExifInterface(source)
        }
        var degree = 0
        val ori = exif .getAttributeInt(ExifInterface.TAG_ORIENTATION,-1)
        when(ori){
            ExifInterface.ORIENTATION_ROTATE_90 -> degree = 90
            ExifInterface.ORIENTATION_ROTATE_180 -> degree = 180
            ExifInterface.ORIENTATION_ROTATE_270 -> degree = 270
        }
        return degree.toFloat()
    }

    fun rotateBitmap(bitmap: Bitmap,degree:Float) : Bitmap{
        // 각도값을 관리하는 객체
        val matrix = Matrix()
        matrix.postRotate(degree)

        // 회전된 이미지를 받아온다
        val bitmap2 = Bitmap.createBitmap(bitmap,0,0,bitmap.width,bitmap.height,matrix,true)
        return bitmap2
    }
}

 

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path
        name="storage/emulated/0"
        path="."/>
</paths>

 

mainfest provider 설정

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.example.camera">

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Camera"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <provider
            android:authorities="kr.co.eojin.camera.file_provider"
            android:name="androidx.core.content.FileProvider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths"/>
        </provider>
    </application>


</manifest>
728x90

'안드로이드 > 센서' 카테고리의 다른 글

안드로이드 앨범에서 사진 가져오기  (0) 2022.06.25
안드로이드 사진 보정  (0) 2022.06.25
안드로이드 GPS  (0) 2022.06.25
안드로이드 센서  (0) 2022.06.24
안드로이드 단말기 정보 파악  (0) 2022.06.24