Merhabalar,
Bu Unity dersinde, Android ve iOS platformlarda cihazın kamerasını kullanarak resim çekmeyi veya video kaydetmeyi göreceğiz.
O halde hadi başlayalım!
Kurulum
İlk önce şu adresteki NativeCamera.unitypackage‘ı Assets-Import Package yoluyla projenize import edin: https://github.com/yasirkula/UnityNativeCamera/releases
Alternatif olarak, asset’i Asset Store’dan da import edebilirsiniz: https://assetstore.unity.com/packages/tools/integration/native-camera-for-android-ios-117802
Eğer iOS’a build alacaksanız, Plugins/NativeCamera/Editor/NCPostProcessBuild.cs scriptindeki CAMERA_USAGE_DESCRIPTION‘ın değerini dilerseniz değiştirin. Buraya girdiğiniz yazı, kameraya erişim izni isterken gözükecek. Android’e build alacaksanız özel bir şey yapmanız gerekmiyor.
Fonksiyonlar
A) Kameranın Durumunu Kontrol Etmek
NativeCamera.DeviceHasCamera()
Cihazın kamerası olup olmadığını döndürür. Bazı telefonlarda kamera olmadığı için, bu fonksiyon o cihazlarda false döndürür.
NativeCamera.IsCameraBusy()
Kameranın meşgul olup olmadığını döndürür. Eğer kamera meşgulse (true), o an kameraya erişmek mümkün değildir.
B) Resim Çekmek
NativeCamera.TakePicture( CameraCallback callback, int maxSize = -1, PreferredCamera preferredCamera = PreferredCamera.Default )
callback: Kullanıcı kamera ile bir resim çekince veya işlemi iptal edince bu fonksiyon çağrılır. Buraya vereceğiniz fonksiyon bir string parametre almak zorundadır. Eğer işlem iptal edildiyse bu parametrenin değeri null olurken aksi taktirde, çekilen resim dosyasının konumu bu string’de depolanır.
maxSize: Eğer resmin genişliği veya yüksekliği bu değerden büyük olursa, resmin bu boyuta küçültülmüş bir versiyonu döndürülür. Varsayılan olarak bir büyüklük limiti yoktur ancak resim ne kadar büyük olursa hafızada o kadar çok yer kaplayacağı için bu parametreye 512, 1024 vs. gibi işinizi görmeye yetecek bir değer vermeniz şiddetle önerilir.
preferredCamera: Varsayılan olarak arka kamera mı yoksa ön kamera mı açılsın belirlemeye yarar. Ancak Android’de her cihaz bu değişkeni desteklemediğinden bazı Android cihazlarında bir etkisi olmayabilir.
C) Video Kaydetmek
NativeCamera.RecordVideo( CameraCallback callback, Quality quality = Quality.Default, int maxDuration = 0, long maxSizeBytes = 0L, PreferredCamera preferredCamera = PreferredCamera.Default )
quality: Çekilen videonun kalitesini belirler. Değeri Default (varsayılan), Low, Medium veya High olabilir.
maxDuration: Çekilen videoya saniye cinsinden bir süre limiti koyar. Bu süre bitiminde video çekimi hâlâ devam ediyorsa, video otomatik olarak durdurulur. Varsayılan olarak bir süre limiti yoktur. Yalnız bu parametrenin doğru çalışabilmesi için, cihazın üreticisinin kamera yazılımına bu işlevselliği eklemiş olması gerekmektedir; yani bu parametre bazı cihazlarda bir işe yaramayabilir.
maxSizeBytes: Çekilen videoya byte cinsinden bir boyut limiti koyar. Video bu boyutu aşarsa, çekim otomatik olarak durdurulur. Varsayılan olarak bir boyut limiti yoktur. Bu parametrenin iOS’ta bir etkisi yoktur. Ayrıca bu parametrenin doğru çalışabilmesi için, cihazın üreticisinin kamera yazılımına bu işlevselliği eklemiş olması gerekmektedir; yani bu parametre bazı cihazlarda bir işe yaramayabilir.
D) Çalışma Zamanı İzinleri (Runtime Permissions) Hakkında
Android 6.0 sürümü itibariyle artık önemli bir Android fonksiyonuna erişmeden önce, çalışma zamanında bu fonksiyona erişim izni istemek zorundayız. NativeCamera fonksiyonları çalışmadan önce otomatik olarak izin isterler ancak dilerseniz kendi başınıza da izinlerin mevcut durumunu sorgulayabilir veya izin isteyebilirsiniz.
NativeCamera.CheckPermission()
İzinlerin durumunu sorgular ve bir NativeCamera.Permission enum‘u döndürür. Eğer kameraya erişim iznimiz varsa bu enum’un değeri Permission.Granted olurken eğer henüz iznimiz yoksa Permission.ShouldAsk olur. Eğer kullanıcı karşısına gelen izin ekranını “Bir daha sorma” seçili bir şekilde reddederse veya kullanıcının cihazında aktif olan bir ebeveyn kontrol sistemi bu iznin verilmesini engelliyorsa, Permission.Denied döndürülür. Bu durumda kullanıcı izni cihazın ayarlar menüsünden elle vermek zorundadır. Böyle bir durumla baş başa kalırsanız, kullanıcıya ayarlar menüsünden izin vermesini söyleyen bir uyarı penceresi göstermenizi öneririm.
NativeCamera.RequestPermission()
Kameraya erişim izni ister ve sonucu bir NativeCamera.Permission enum’unda döndürür. Resim/video çekmeye yarayan NativeCamera fonksiyonları bu fonksiyonu otomatik olarak çağırıp sonucu döndürürler.
E) Çekilen Resim Dosyasını Texture’a Çevirmek
NativeCamera.LoadImageAtPath( string imagePath, int maxSize = -1, bool markTextureNonReadable = true, bool generateMipmaps = true, bool linearColorSpace = false )
Bu fonksiyon vasıtasıyla bir resim dosyasını hızlıca bir Texture2D objesine çevirebilirsiniz.
imagePath: Texture2D olmasını istediğiniz resim dosyasının konumunu buraya girmelisiniz.
maxSize: Eğer resmin genişliği veya yüksekliği bu değerden büyük olursa, resmin bu boyuta küçültülmüş bir versiyonu döndürülür. Varsayılan olarak bir büyüklük limiti yoktur ancak resim ne kadar büyük olursa hafızada o kadar çok yer kaplayacağı için bu parametreye 512, 1024 vs. gibi işinizi görmeye yetecek bir değer vermeniz şiddetle önerilir.
markTextureNonReadable: Texture2D objesinin RAM’deki kopyasını silerek hafızayı rahatlatır. Bunun dezavantajı, artık resmin piksellerine elle erişemezsiniz; yani eğer GetPixel veya SetPixel fonksiyonlarını kullanıyorsanız bu parametreyi false yapın.
generateMipmaps: Texture’un mipmap’lerinin olup olmayacağını belirler.
linearColorSpace: Texture’un linear renk uzayını mı yoksa gamma renk uzayını mı (varsayılan) kullanacağını belirler.
Örnek Kod
Aşağıdaki örnek kodun iki işlevi bulunmaktadır:
- ekranın sol yarısına tıklarsanız, kamera ile resim çekmeniz istenir ve çekilen resim geçici bir küp objesine texture olarak verilir
- ekranın sağ yarısına tıklarsanız, kamera ile video kaydetmeniz istenir ve bu kaydedilen video daha sonra oynatılır
void Update()
{
if( Input.GetMouseButtonDown( 0 ) )
{
// Eğer kamera meşgulse bir şey yapma
if( NativeCamera.IsCameraBusy() )
return;
if( Input.mousePosition.x < Screen.width / 2 )
{
// Kamera ile resim çek
// Eğer resmin genişliği veya yüksekliği 512 pikselden büyükse, resmi ufalt
ResimCek( 512 );
}
else
{
// Kamera ile video kaydet
VideoKaydet();
}
}
}
private void ResimCek( int maksimumBuyukluk )
{
NativeCamera.Permission izin = NativeCamera.TakePicture( ( konum ) =>
{
Debug.Log( "Çekilen resmin konumu: " + konum );
if( konum != null )
{
// Çekilen resmi bir Texture2D'ye çevir
Texture2D texture = NativeCamera.LoadImageAtPath( konum, maksimumBuyukluk );
if( texture == null )
{
Debug.Log( konum + " konumundaki resimden bir texture oluşturulamadı." );
return;
}
// Texture'u geçici bir küp objesine ver
GameObject kup = GameObject.CreatePrimitive( PrimitiveType.Cube );
kup.transform.position = Camera.main.transform.position + Camera.main.transform.forward * 5f;
kup.transform.forward = -Camera.main.transform.forward;
kup.transform.localScale = new Vector3( 1f, texture.height / (float) texture.width, 1f );
Material material = kup.GetComponent<Renderer>().material;
if( !material.shader.isSupported ) // eğer Standard shader desteklenmiyorsa Diffuse shader'ı kullan
material.shader = Shader.Find( "Legacy Shaders/Diffuse" );
material.mainTexture = texture;
// 5 saniye sonra küp objesini yok et
Destroy( kup, 5f );
// Küp objesi ile birlikte Texture2D objesini de yok et
// Eğer prosedürel bir objeyi (Texture2D) işiniz bitince yok etmezseniz,
// mevcut scene'i değiştirene kadar obje hafızada kalmaya devam eder
Destroy( texture, 5f );
}
}, maksimumBuyukluk );
Debug.Log( "İzin durumu: " + izin );
}
private void VideoKaydet()
{
NativeCamera.Permission izin = NativeCamera.RecordVideo( ( konum ) =>
{
Debug.Log( "Kaydedilen videonun konumu: " + konum );
if( konum != null )
{
// Videoyu oynat
Handheld.PlayFullScreenMovie( "file://" + konum );
}
} );
Debug.Log( "İzin durumu: " + izin );
}
Böylece bu dersi de noktalamış olduk. Bir sonraki derste görüşmek dileğiyle!