Esta resposta é resumida em Carregando bitmaps grandes com eficiência
que explica como usar inSampleSize para carregar uma versão de bitmap em escala reduzida.
Em particular , os bitmaps de pré-dimensionamento explicam os detalhes de vários métodos, como combiná-los e quais são os mais eficientes em termos de memória.
Existem três maneiras dominantes de redimensionar um bitmap no Android, que têm diferentes propriedades de memória:
API createScaledBitmap
Esta API pegará um bitmap existente e criará um NOVO bitmap com as dimensões exatas que você selecionou.
No lado positivo, você pode obter exatamente o tamanho de imagem que está procurando (independentemente de sua aparência). Mas a desvantagem é que essa API requer um bitmap existente para funcionar . Significa que a imagem teria que ser carregada, decodificada e um bitmap criado, antes de ser capaz de criar uma nova versão menor. Isso é ideal em termos de obter suas dimensões exatas, mas horrível em termos de sobrecarga de memória adicional. Como tal, isso é uma espécie de quebra de negócio para a maioria dos desenvolvedores de aplicativos que tendem a se preocupar com a memória
Sinalizador inSampleSize
BitmapFactory.Optionstem uma propriedade inSampleSizeque irá redimensionar sua imagem enquanto a decodifica, para evitar a necessidade de decodificar para um bitmap temporário. Este valor inteiro usado aqui carregará uma imagem em tamanho 1 / x reduzido. Por exemplo, definir inSampleSizecomo 2 retorna uma imagem com metade do tamanho, e definir como 4 retorna uma imagem com 1/4 do tamanho. Basicamente, os tamanhos das imagens serão sempre um pouco menores do que o tamanho da fonte.
Do ponto de vista da memória, usar inSampleSizeé uma operação muito rápida. Efetivamente, ele só decodificará cada X pixel de sua imagem em seu bitmap resultante. Existem dois problemas principais inSampleSize:
Não fornece resoluções exatas . Ele apenas diminui o tamanho do seu bitmap em uma potência de 2.
Não produz o redimensionamento de melhor qualidade . A maioria dos filtros de redimensionamento produz imagens com boa aparência ao ler blocos de pixels e, em seguida, ponderá-los para produzir o pixel redimensionado em questão. inSampleSizeevita tudo isso lendo apenas alguns pixels. O resultado é bastante eficiente e com pouca memória, mas a qualidade é prejudicada.
Se você está lidando apenas com o encolhimento de sua imagem em algum tamanho pow2, e a filtragem não é um problema, então você não encontrará um método mais eficiente em memória (ou desempenho) do que inSampleSize.
Sinalizadores inScaled, inDensity, inTargetDensity
Se você precisa redimensionar uma imagem para uma dimensão que não é igual a uma potência de dois, então você vai precisar do inScaled, inDensitye inTargetDensitybandeiras de BitmapOptions. Quando o inScaledsinalizador for definido, o sistema derivará o valor de escala a ser aplicado ao seu bitmap, dividindo o inTargetDensitypelos inDensityvalores.
mBitmapOptions.inScaled = true;
mBitmapOptions.inDensity = srcWidth;
mBitmapOptions.inTargetDensity = dstWidth;
// will load & resize the image to be 1/inSampleSize dimensions
mCurrentBitmap = BitmapFactory.decodeResources(getResources(),
mImageIDs, mBitmapOptions);
Usar este método redimensionará sua imagem e também aplicará um 'filtro de redimensionamento' a ela, ou seja, o resultado final parecerá melhor porque alguma matemática adicional foi levada em consideração durante a etapa de redimensionamento. Mas esteja avisado: essa etapa de filtro extra, leva mais tempo de processamento e pode aumentar rapidamente para imagens grandes, resultando em redimensionamentos lentos e alocações de memória extra para o próprio filtro.
Geralmente não é uma boa ideia aplicar essa técnica a uma imagem significativamente maior do que o tamanho desejado, devido à sobrecarga de filtragem extra.
Combinação mágica
De uma perspectiva de memória e desempenho, você pode combinar essas opções para obter os melhores resultados. (definindo o inSampleSize, inScaled, inDensitye inTargetDensitybandeiras)
inSampleSizeserá aplicado primeiro à imagem, colocando-a na próxima potência de dois MAIOR do que o tamanho de destino. Em seguida, inDensity& inTargetDensitysão usados para dimensionar o resultado para as dimensões exatas que você deseja, aplicando uma operação de filtro para limpar a imagem.
Combinar esses dois é uma operação muito mais rápida, uma vez que a inSampleSizeetapa reduzirá o número de pixels que a etapa baseada em densidade resultante precisará para aplicar seu filtro de redimensionamento.
mBitmapOptions.inScaled = true;
mBitmapOptions.inSampleSize = 4;
mBitmapOptions.inDensity = srcWidth;
mBitmapOptions.inTargetDensity = dstWidth * mBitmapOptions.inSampleSize;
// will load & resize the image to be 1/inSampleSize dimensions
mCurrentBitmap = BitmapFactory.decodeFile(fileName, mBitmapOptions);
Se você precisar ajustar uma imagem a dimensões específicas, e alguma filtragem mais agradável, essa técnica é a melhor ponte para obter o tamanho certo, mas feita em uma operação rápida e com pouca memória.
Obtendo as dimensões da imagem
Obtendo o tamanho da imagem sem decodificar a imagem inteira Para redimensionar seu bitmap, você precisará saber as dimensões de entrada. Você pode usar o inJustDecodeBoundssinalizador para ajudá-lo a obter as dimensões da imagem, sem a necessidade de realmente decodificar os dados de pixel.
// Decode just the boundaries
mBitmapOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(fileName, mBitmapOptions);
srcWidth = mBitmapOptions.outWidth;
srcHeight = mBitmapOptions.outHeight;
//now go resize the image to the size you want
Você pode usar este sinalizador para decodificar o tamanho primeiro e, em seguida, calcular os valores adequados para dimensionar a sua resolução alvo.