sábado, 31 de outubro de 2015

Resolution, Density, Pixel, File Size, ...

Manipulação de imagem é assunto interessante mas ao mesmo tempo cheio de detalhes técnicos. Compreender um pouco deste tema é fundamental para construir aplicações bonitas, mas também bem dimensionadas na questão armazenamento. Praticamente todo mundo virou fotografo nos dias atuais, com direito a equipamento de alta qualidade e também armazenamento instantâneo em sites como facebook, snapchat, ..., e nada mais natural aproveitarmos a câmera dos smartphones para capturar momento, eventos, situações para armazenarmos no nosso App.

Outra motivação importante diz respeito a escolha das imagens para comporem nossa aplicação, normalmente por meio de um ícone, um background, enfim, imagem é um recurso necessário, mas vem acompanhado de muita teoria: Pixel, Resolution, Density, ....

Então vamos estudar um pouco a respeito deste tema, buscando aprender um pouco sobre a teoria, mas também informando os caminhos para desenvolvermos imagens para nossas aplicações.  Vai ficar um pouco longo, me desculpem, e para quebrar um pouco vou deixar os dois primeiros temas neste artigo e o terceiro que trata da resolução de dispositivos móveis num segundo.
  • 1: Conceituação sobre imagens, resolução, pixel
  • 2: Manipulação de imagens no Genexus
  • 3: Resolução de imagens para dispositivos móveis.


1: Resolução, Densidade, Pixel, File Size

Inicialmente consideremos que uma imagem é formada por um conjunto de Pixels (Picture and Element) uma certa unidade de medida . Cada câmera digital possui um sensor que captura milhões de células ou  pontos de luz. Cada ponto ou célula capturada é chamada de pixel, e quando se fala 8 Megapixel ou 8 Mp se define um dispositivo que consegue capturar 8 milhões de pontos em uma única imagem.  O valor de cada pixel capturado determina uma certa cor lida pelo sensor, que também possui uma teoria para medir sua composição a partir de três cores básicas (Red-Green-Blue ou RGB), estaremos mais abaixo discutindo este assunto..

Somente e total de células ou pontos de luz não define se uma imagem será boa ou não, porque entra em cena um segundo elemento que determina a dimensão da imagem em função de sua largura e altura, Width e Height, que alguns autores chamam de Resolução (Resolution).  Esta define o total de pixel medidos a partir da horizontal (width) e vertical (height) que o sensor da câmera consegue capturar, portanto nosso 8Mp não quer dizer muita coisa, precisamos também identificar a resolução horizontal e vertical, que normalmente é descrita por meio de uma representação do tipo 640 x 480, 1216 x 912, 1600 x 1200, 2240 x 1680, 4256 x 2832.  Esta última representa uma imagem com 12052992 pixels, ou seja, uma imagem de 12.1Mp.

Para os fotógrafos profissionais o fator mais importante não é a resolução em si, mas sim o tamanho impresso da imagem, que seria formado pela combinação de uma alta resolução mas também pela distância entre cada pixel, tanto horizontal quanto vertical, ou seja, se os pontos estão comprimidos ou espaçados. Mais comprimido, mais nítida seria a imagem, mais espaçado, teríamos uma imagem mais granulada.  Desta forma uma nova unidade de medida PPI (Pixels Per Inch ) define a densidade (Density) da mesma. Máquinas fotográficas profissionais trabalham com densidades de 300PPI, um monitor de vídeo 72PPI or 96. A Unidade PPI normalmente é associada a outra DPI (Dots Per Inch), referindo-se aos pontos de impressão em uma impressora laser ou jato de tinta.O iPhone 6, por exemplo, possui uma densidade de 326 PPI na tela retina.

Pixel não é Byte


Finalmente vamos falar da dimensão da imagem gravada, o File Size, onde buscamos traduzir a unidade megapixel em megabytes, bytes e bits, para enfim tratarmos da quetão armazenamento. Neste sentido entra em cena a criatividade humana, que identificou que quando analisamos uma certa imagem pixel-a-pixel, se concluiu que existem sequencias onde os valores se repetem. Por exemplo, se você pegar um retângulo de dimensões 4256 x 2832, totalmente preenchido com uma única cor vermelha, não precisaríamos de todos os pixels armazenados no arquivo, mesmo porque seria uma repetição, bastaria de algo como 'repita a mesma cor vermelha, 12.1Mp vezes' e em seguida um processador para ler e repetir a informação no momento de apresentar. Sabe quem faz isso? os formatos de imagem: PNG, JPG, GIF que são algoritmos que comprimem uma imagem para a menor dimensão possível de armazenamento.

Se tivéssemos esta mesma imagem de 4256 x 2832 consumindo, para cada pixel um único bit, e sem nenhuma compressão, teríamos um arquivo com 12.1Mbytes, mas para se medir a dimensão de um pixel em bits, precisamos entender um pouco do que podemos representar em termos desta unidade. Por exemplo, se cada pixel consumir um único bit, podemos apenas designar duas cores para esse pixel (branco/ligado e preto/desligado),  desta forma, para representar mais cores, precisamos de mais bits, e aqui temos mais um conceito importante chamado Color Depth  (ou Bit Depth).  Neste, um Bit Deph de 8 bits permite representar 256 cores diferentes.

Portanto, para se calcular a dimensão final em bytes de uma imagem, precisaríamos incluir em nossa conta a dimensão da imagem, o bit depth, a densidade, a compressão, e mesmo assim, nunca chegaremos a uma conclusão definitiva, porque cada imagem tem suas próprias características que influenciariam na dimensão final.

Por exemplo, uma foto com dimensão de 2592 x 1936, imagem (a) abaixo, com  resolução horizontal de 72 dpi e vertical de 72 dpi, com bit depth de 24, comprimida com formato JPEG, gera uma dimensão aproximada de 1.5Mb. Digo aproximada, porque outra foto neste mesmo aparelho, imagem (b) poderá ter uma dimensão completamente diferente, devido a compressão, mesmo se tiradas do mesmo dispositivo.





O fato é que atualmente os dispositivos precisam de cada vez mais memória para guardar todas as imagens capturadas e nossos Apps e sistemas também sofrem influencia deste novo comportamento, precisamos então compreender quais os recursos que temos a nossa disposição para programarmos.


2: Armazenamento de Imagens no Genexus

No Genexus as imagens podem ser capturadas e armazenadas diretamente na tabela por meio do tipo Image ou Blob.  O primeiro é indicado para imagens com formatos tradicionais (JPEG, GIF, PNG) enquanto que o segundo tipo permite armazenar qualquer coisa, desde imagem a documentos Word, Excel, PDF, ...

Image

Muito simples, definir um atributo com o tipo Image, e o Genexus se encarrega de fazer o resto (upload, armazenamento, recuperação). Nas versoes mais antigas o Genexus definia este tipo como Bitmap.

Este tipo utiliza dois atributos no banco para armazenar a informação.  O primeiro, do tipo VARBINARY armazena a imagem em si num formato BLOB (binário). O segundo uma string com um formato meio esquisito, por exemplo: gxdbfile:1_6095d6f151664be2b40f6d073e391b69.PNG, que é o nome do arquivo de controle da imagem no BD.

 [ClienteFoto]     VARBINARY(MAX)    NOT NULL,
 [ClienteFoto_GXI] VARCHAR(2048)    NOT NULL


Blob

Tipo bastante interessante que permite armazenar qualquer coisa na tabela, um EXE, PDF, ... Ja exploramos esse assunto no Genexando.


UploadFy

Além desses dois tipos, você poderá optar por realizar um upload manual da imagem para o servidor, armazenando-a fisicamente em uma pasta no servidor. Neste caso, recomendo estudar um pouco o controle uploadfy.


Temp Storage

Falar sobre Image ou Blob nos remete também ao assunto de reconstrução da imagem para sua inclusão na pagina ao usuario, isto considerando que a mesma deve existir fisicamente no servidor para que possa ser incluida em uma tag <img> no browser.

Para isso o Genexus reconstroi a imagem do BD para uma imagem fisica, armazenando-a em dois diretorios: PrivateTempStorage e PublicTempStorage.  Estes ficam localizados na raiz da aplicação (web para o .Net), e apontadas no web.config no appSettings:

  <appSettings>
      <add key="CS_BLOB_PATH" value="PublicTempStorage" />
      <add key="TMPMEDIA_DIR" value="PrivateTempStorage" />


Nestas pastas o Genexus armazenara o arquivo para upload e também restaurará a imagem para mostra-la no browser.


Maximum Upload Size Property

A versão Genexus Evolution 3 apresenta um recurso para controlar a dimensão da imagem a ser submetida ao banco de dados (upload) que é a resolução da mesma de acordo com uma determinada dimensão Large, Medium e Small, previamente definida em Preferences - Kb.


Em seguida, no próprio atributo Image definimos em Maximum Upload Size a dimensão que permitiremos ao usuário subir para o servidor.


No Maximum Upload Size se você deixar o valor Actual Size será submetida a imagem original ao Banco de Dados, evidentemente sujeitando o sistema a crescente evolução da resolução dos dispositivos. Por outro lado se a opção for limitar em um tamanho Small, Medium, Large, a mesma será reduzida mantendo-se o Aspect Ratio, ou seja, a proporção, caso a mesma seja maior que a dimensão definida. Ate o momento este tratamento é realizado em iPhone e Androids.