Como corrigir a orientação das fotos no Android
Imagina que você tá usando o seu aplicativo bacana pra tirar fotos e aplicar uns filtros marotos. Você vira o celular de lado para enquadrar melhor a foto e quando vai ver o resultado percebe que a foto saiu desse jeito:
Mas por que será que isso aconteceu?
Isso acontece porque o sensor da câmera é fixo e não sabe como o dispositivo está posicionado quando a foto é tirada. O papel dele é simplesmente capturar a imagem. Ah, mas quando tiramos uma foto com o celular virado de lado e abrimos a foto na galeria ela tá com a orientação correta!
Verdade! Isso mostra pra gente que tem alguém no meio do caminho fazendo algum tipo de correção pra mostrar a foto direitinho. Bom, o sensor da câmera é fixo mas sabemos que as câmeras digitais e também nossos smartphones tem aqueles sensores de orientação pra saber quando devem virar a tela. O que eles fazem então é salvar a imagem juntamente com essa informação da orientação justamente pra que a gente consiga corrigir depois.
Pra salvar essas informações extras, praticamente toda câmera digital salva as imagens no formato Exif que permite armazenar algumas tags com informações como data, hora, geolocalização e também a orientação da câmera no momento da captura. Isso significa que para mostrar uma foto no seu aplicativo com a orientação correta, você só precisa conseguir ler esses dados extras e descobrir qual correção aplicar antes de exibir a foto!
Mãos à obra então! Vamos criar uma classe que consiga devolver pra gente um Bitmap
corrigido a partir do caminho de uma foto. Usaremos a classe ExifInterface
para acessar as informações extras da imagem e descobrir a orientação da foto:
public class CarregadorDeFoto {
public static Bitmap carrega(String caminhoFoto) {
ExifInterface exif = new ExifInterface(caminhoFoto);
String orientacao = exif.getAttribute(ExifInterface.TAG_ORIENTATION);
}
}
Agora que temos a orientação, só precisamos descobrir qual rotação devemos aplicar ao abrir o Bitmap
. Para isso, vamos comparar a orientação que obtivemos da ExifInterface
com algumas constantes que já estão prontas. Como essas constantes são do tipo inteiro, vamos ter que converter a orientação que pegamos da ExifInterface
pra inteiro antes de fazer a comparação:
public class CarregadorDeFoto {
public static Bitmap carrega(String caminhoFoto) {
ExifInterface exif = new ExifInterface(caminhoFoto);
String orientacao = exif.getAttribute(ExifInterface.TAG_ORIENTATION);
int codigoOrientacao = Integer.parseInt(orientacao);
switch (codigoOrientacao) {
// rotaciona 0 graus no sentido horário case
case ExifInterface.ORIENTATION_NORMAL:
// rotaciona 90 graus no sentido horário case
ExifInterface.ORIENTATION_ROTATE_90:
// rotaciona 180 graus no sentido horário case
ExifInterface.ORIENTATION_ROTATE_180:
// rotaciona 270 graus no sentido horário
ExifInterface.ORIENTATION_ROTATE_270:
} } }
Agora só precisamos criar mais um método que abra a imagem como um Bitmap
e faça a rotação de acordo com a correção a ser aplicada.
private Bitmap abreFotoERotaciona(String caminhoFoto, int angulo) {
// Abre o bitmap a partir do caminho da foto Bitmap
bitmap = BitmapFactory.decodeFile(caminhoFoto);
// Prepara a operação de rotação com o ângulo escolhido
Matrix matrix = new Matrix(); matrix.postRotate(angulo);
// Cria um novo bitmap a partir do original já com a rotação aplicada
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}
Pronto! Agora só precisamos utilizar esse método na nossa classe que carrega as fotos. Veja como fica o código completo:
public class CarregadorDeFoto {
public static Bitmap carrega(String caminhoFoto) {
ExifInterface exif = new ExifInterface(caminhoFoto);
String orientacao = exif.getAttribute(ExifInterface.TAG_ORIENTATION);
int codigoOrientacao = Integer.parseInt(orientacao);
switch (codigoOrientacao) {
case ExifInterface.ORIENTATION_NORMAL: return abreFotoERotaciona(caminhoFoto, 0);
case ExifInterface.ORIENTATION_ROTATE_90: return abreFotoERotaciona(caminhoFoto, 90);case ExifInterface.ORIENTATION_ROTATE_180: return abreFotoERotaciona(caminhoFoto,180);
case ExifInterface.ORIENTATION_ROTATE_270: return abreFotoERotaciona(caminhoFoto,270);
} }
private Bitmap abreFotoERotaciona(String caminhoFoto, int angulo) {
// Abre o bitmap a partir do caminho da foto Bitmap
bitmap = BitmapFactory.decodeFile(caminhoFoto);
// Prepara a operação de rotação com o ângulo escolhido
Matrix matrix = new Matrix(); matrix.postRotate(angulo);
// Cria um novo bitmap a partir do original já com a rotação aplicada
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); } }
Legal! Então agora só precisamos usar essa classe toda vez que formos carregar uma imagem. Então se a gente tiver uma Activity
com uma ImageView
pra mostrar uma foto, poderíamos usar nossa classe assim:
public class VisualizadorDeFoto extends AppCompatActivity {
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.activity_visualizador);
ImageView campoFoto = (ImageView) findViewById(R.id.campoFoto);
Bitmap bitmap = CarregadorDeFoto.carrega("foto_supimpa.jpg");
campoFoto.setImageBitmap(bitmap); }
}
Agora sim já podemos mostrar nossas fotos sem se preocupar se elas foram tiradas com o celular de pé ou de lado!
O que você achou dessa dica? Também já passou por esse problema e resolveu de outro jeito? Conta pra gente! Se quiser aprender mais sobre desenvolvimento pra mobile, dá uma olhadinha nos cursos mobile do Alura ou nos cursos presenciais da Caelum!