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.

sexta-feira, 23 de outubro de 2015

Que? App Transport Security Policy?

Construir coisas com recursos muito novos pode dar nisso, mensagens malucas que não apenas levam um tempo para serem entendidas mas também acabam gerando um pouco de frustração, principalmente quando se da conta que a ferramenta ainda não dá suporte ao XCode 7.


Para ser mais exato o problema se chama The resource could not be loaded because the App Transport Security policy requires the use of a secure connection.


Esta situação somente afeta quem usa o Mac e atualizou o XCode recentemente para a nova versão, se estiver usando outro emulador, como o KBN, por exemplo, não viverá este problema.


Portanto, fica a dica, não saia atualizando tudo sem antes dar uma olhada se o Genexus já oferece suporte ao recurso. Quanto ao XCode, sim, já estão trabalhando para atender aos recursos de proteção incluidos nesta nova versao, eu só vou ter que esperar um pouquinho, :(



terça-feira, 13 de outubro de 2015

IoT: Internet of Things

Um dos pilares do evento Genexus Gx25 deste ano foi o tema Internet das Coisas (Internet of Things,)  que consiste em Hardware + Software para gerenciamento de sensores eletronicos a partir da Internet. Em outras palavras, as inúmeras possibilidades de se  utilizar a internet para controlar dispositivos eletrônicos localizados em qualquer lugar no mundo.

Chega a ser impressionante a velocidade com que novos recursos de Hardware vem surgindo para dar suporte ao modelo de se conectar dispositivos na internet.  No próprio evento tivemos a palestra do Rodolfo Robalo e Marcelo Eguiluz (Genexus), que destacou a arquitetura de um dispositivo  Raspberry Pi, no qual instalaram o Windows 10 e um programa Genexus para controlar sensores de iluminação.

Este novo cenário proporciona a construção de soluções inteligentes sem a necessidade de se utilizar um computador externo, para o gerenciamento. O próprio controlador atua como computador, e com Windows + Genexus temos a possibilidade de comunicar webservices, redes sociais, armazenamento, enfim, lidar com temas complexos em alto nível. Se você não teve a oportunidade de ver a palestra, aqui esta o link: Internet of Things con GeneXus. Lo que se viene, ¡ya está hoy!

Para você que tem interesse, como eu, neste novo mundo, separei três links que tratam deste tema.

Microsoft IoT

A Microsoft define diversos cenários que permitem conectar os sensores com o Windows 10, mediante diversos dispositivos.  https://dev.windows.com/pt-br/iot

Intel IoT

Oferece um cenário de grande escalabilidade para conectar na IoT, baseado em seu hardware Intel Galeleo e Edison:  https://software.intel.com/pt-br/iot/home

IBM Iot

Neste link voce encontrara um exemplo para conectar o Arduino a nuvem Bluemix da IBM, https://developer.ibm.com/recipes/tutorials/connect-an-arduino-uno-device-to-the-ibm-internet-of-things-foundation/ A propria IBM possui uma IBM Foundations destinada a pesquisas neste tema: http://www-03.ibm.com/software/products/en/internet-of-things-foundation



Todos os três destacam a importância do tema mas também a utilização da nuvem para armazenar os dados dos sensores, que são capturados e armazenados em Big Data!  E também o que  chama muito a atenção neste tema é o envolvimento de grandes empresas destacando muita energia para construir soluções.

Outras Palestras sobre o Tema








sábado, 10 de outubro de 2015

Prototipando no Mac

Que tal um Mac para construir Apps Genexus? Além do investimento necessário  para comprar o equipamento (parte mais dolorida digamos), também será preciso investir cinco minutos para configurar tudo, parece interessante não? de fato tudo se encaixa perfeitamente nesta brincadeira.

Mesmo que você tenha que criar toda a aplicação em uma máquina Windows, veja que salada:
  1.  Notebook Windows rodando Genexus (Evolution 3 no meu caso),
  2.  Mac rodando XCode, se não tiver instalado terá que baixar na Apple Store,
  3. Ambos Notebook e Mac rodando na mesma rede,
  4. Aplicação gerada no Genexus sendo enviada para o Mac, que cria um projeto na pasta Documents do usuário
  5. Simulador abrindo no Mac, permitindo que se interaja com a aplicação em execução
  6. Dados da aplicação sendo recuperadas do banco de dados que se encontra no Notebook Windows em um BD.
Enfim, um cenário muito complexo, mas por incrível que pareça, funciona!

Então, caso você tenha toda esta curiosidade, vou passar as dicas:

1) No Notebook

Será necessário desligar o Firewall do notebook para que não barre a transmissão de dados do BD local para o Mac. Faça isso selecionando Network and Sharing Center, tem uma opção para acessar o Firewall de lá
.

2) No Genexus

Além de construir um SD Panel + Dashboard (marcar como main), ou seja, seguir os procedimentos normais para criar uma App para o Ios, será necessário definir as propriedades corretas no Environment - Generators - SmartDevice

Onde as propriedades significam: mac-host é o valor de Computer name no mac, que pode ser obtido (se voce nao souber) na aba Software do System Reporter, (About This Mac). mac user e password é a senha do administrador da maquina Mac.

Em seguida no Environment terá que ajustar as propriedades para execução do programa por meio de IP e não pelo nome da máquina, isto porque o MAC deverá acessar os serviços REST por meio do IP onde se localizam.  Deve ficar mais ou menos assim: http://192.168.0.102/first.NetEnvironment/

3) Problemas: error: Auth fail

Gostaria muito de não passar por isso, mas ocorreu duas situações de erro aqui. Esta (Auth Fail) significa que o usuário fornecido não tem privilégios de administrador da maquina. Para corrigir designe o usuario no mac como administrador ou coloque o usuário correto no Genexus.

 \========== iOS Compilation started ==========
Command: MacTransfer compile "Douglas-Mac" "douglas" "" "first" ".Net Environment" "Map" "SimMac/iPhone-6/Latest" "Z:\Models\Produto\first\CSharpModel" "10.3.94353 U4"
Connecting to Douglas-Mac
error: Auth fail
iOS Compilation Failed
Run Map Failed


3) Problemas: error: Error getting sdk version (error code 69)

Para mim este erro ocorreu porque não havia ainda registrado o XCode para o usuário administrador do Mac. Após uma atualização perdeu-se este registro. Para realizar a operação deve-se abrir o XCode no Mac e fornecer a senha do usuário quando solicitada.

\Command: MacTransfer compile "Douglas-Mac" "Douglas H Oliveira" "" "first" ".Net Environment" "Map" "SimMac/iPhone-6/Latest" "Z:\Models\Produto\first\CSharpModel" "10.3.94353 U4"
Connecting to Douglas-Mac
error: Error getting sdk version (error code 69)
error: Execute in Mac's command line the following:
error: /Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild -version -sdk
iOS Compilation Failed
Run Map Failed


4) Sucesso

Nem só de erros vivemos esta vida, após os dois pequenos ajustes anteriormente chegamos a instalação correta do projeto no XCode no MAC.Lendo o resultado das mensagens apresentadas temos que o aplicativo foi instalado na pasta:

/Users/douglas/Documents/Projects/first/dotNet Environment/Map


Ao término da operação um comando para abrir o simulador no MAC é enviado e o simulador é aberto.
 

sshExec: osascript -e 'tell application "Terminal" to do script "/Users/douglas/Library/Artech/GeneXus/10.3.94353_U4/ios-sim launch \"~/Documents/Projects/first/dotNet Environment/Map/build/Debug-iphonesimulator/Map.app\" --devicetypeid \"com.apple.CoreSimulator.SimDeviceType.iPhone-6, 9.0\" --exit"'
iOS Execution Success
Run Map Success


 Comparando com a demora do emulador Android, diria que é bem mais rápido e preciso.

terça-feira, 6 de outubro de 2015

Imagens Redondinhas

Parece que o charme do momento é a apresentação das imagens redondinhas ao invés de quadradinhas, porque? acredito que algum curioso algum dia resolver testar as novas propriedades do CSS 3 e descobriu algo muito interessante: uma propriedade de transforma a imagem de quadrada para redonda. Bingo!!  Descobriu-se a America!!

Bom e como fazer isso? eu estava imaginando um controle em Java ou .NEt que processaria a imagem, que cortaria as bordas, mas pessoal, a coisa é simples, esqueça essas idéias de Gerico, e acho que pela simplicidade e belo efeito, você vai aderir a esta moda também.

Passo 1: Cada um no seu quadrado

Primeiramente precisará de uma imagem quadrada, se usar uma retangular não vai ficar totalmente redondinhas, seria tipo uma linguiça, não legal. E a imagem também precisa ter uma dimensão fixa, previamente conhecida, por exemplo 100x100, 200x200, e por ai vai.

Passo 2: Não Fuja da Aula de Geometria

Se não fugiu saberá o significado de RAIO, que é a metade de um diâmetro, ... me lembrei dos meus dias de desenhista da Torque, do Jaques, rs, o chefe era bravo. Então vamos lá, para uma imagem de 200x200, por exemplo teremos um raio de 100.


Em resumo pegue a lateral do quadrado e divida por dois e terá o tal RAIO.

Crie uma classe Image e defina Border-Radius:RAIO, ou seja, para nosso exemplo, Border-Radius:100;  Tai o segredo da Maria.

Passo 3: Peça ajuda ao Steve

Obtenha uma imagem de boa qualidade e aplique a classe com o Border-Radius e terá o tal efeito da imagem redondinha.


Mistério resolvido!

Enroscos do RWD

Nem tudo em Responsive Web Design é um oceano de rosas, imagine ter que criar interface sem informar em momento algum a dimensão das coisas, no minimo vai ser difícil representar certo design que foi previamente determinado com larguras e alturas que harmonizam com os espaços negativos, hehehe... digamos que estou gastando um pouco do que não tenho, de fato até tento, mas design não é meu forte.

Então para os pobres mortais que precisam criar coisas bonitas em RWD, e claro, após ter tido uma excelente aula com a Sabrina Juarez, vamos ao que interessa: Enroscos no RWD. Ou se quiser traduzir: onde você vai sofrer para criar interfaces responsivas.

Para complementar o assunto recomendo a leitra dos artigos anteriores sobre este tema:

Conceito Um

Sua interface para ser responsiva tem que ficar boa em um iPhone mas também em um iMac de 29 polegadas, e só neste exemplo estamos falando em uma dimensão 10 vezes maior (ou menor). O desafio aqui é grande, e ao que me parece até agora, muitas colunas em um Grid preenchem um iMac mas entopem um iPhone , portanto, o primeiro conceito é que nem tudo que enche uma tela de fato é importante, pois quando temos que resumir um conteúdo em 10 vezes, quase tudo vai desaparecer.

Esse conceito deixaria o Steve Jobs feliz, pois ao falar de RWD estamos lidando principalmente com a simplificação da interface, digamos sua obsessão na vida.  E aproveitando a citação, expresso aqui minhas condolências ao grande gênio.

Portanto, a primeira coisa que deve ter em mente é que não deverá nunca fixar dimensões em colunas de Grid, por exemplo, pois esta simplesmente poderá prejudicar totalmente a visualização em outros dispositivos. A menos que tenha nervos de aço e sangue frio.

Dimensões Horizontais

Ao que me parece a questão do dimensionamento horizontal é bem resolvida em RWD, mesmo porque, como vimos em artigos anteriores, temos o Grid System que segue uma lógica linear com dimensões múltiplas de 8%. De forma bem resumida temos 100 / 8  = 12 colunas. Portanto, se pensar que tem 12 colunas e que vai preenche-las com informações, por exemplo, colocando uma imagem em uma unica coluna, um nome em três colunas, vai chegar a um resultado satisfatório.

O que você não deve fazer é fixar uma coluna em pixel, pois ao fazer isso, automaticamente estará afetando a apresentação em dispositivos pequenos. Portanto, sempre pense em dimensões percentuais.

O problema ocorre quando as colunas ficam meio desajeitadas, digo com dimensões inexplicavelmente estranhas, como o exemplo a seguir, onde temos uma imagem com uma largura gigantesca enquanto que as outras colunas ficam meio espremidas.


Para corrigir isso, crie uma classe Section com uma dimensão percentual de Width, e aplique sobre a imagem e as colunas que deseja reduzir. Criando uma classe, por exemplo, Section 1 e definindo Width=5%, aplicando sobre a Foto e Id, teríamos um rearranjo nas dimensões do Grid, conforme pode ser visto a seguir.


Dimensões Verticais

Então, aqui é que a coisa fica mais esquisita, isto no sentido brasileiro, não espanhol.  Falando o português mais claro possível, digamos que o resultado apresentado é feio pra caramba,e pior que tem uma lógica para isso funcionar desta maneira, pois as informações verticalmente devem parecer mais espaçadas para poderem ser pressionadas em dispositivos menores.

Portanto programando um grid FreeStyle como o apresentado a seguir temos um resultado estranho. sendo apresentado.

Estranho no minimo, porque a apresentação fica com espaçamentos verticais muito grandes.

Para corrigir isso soa mais estranho ainda, pois, é necessário criar uma classe vinculada a uma Rule, E é preciso um pouco se sangue frio para fazer isso, pois não esta muito claro no Genexus como conduzir esta operação.

Primeiro deve-se criar uma Rule (Add Rule) nova no tema Flat. Em seguida renomear esta Rule para Small, Medium ou Large, e então criar uma nova classe em Section, com o nome que desejar, criei como EspremeVertical.  Posicionar na intersecção da coluna Large com a nova classe, EspremeVertical, pressionando em seguida  F4 para programar a propriedade desta classe no tamanho Large.


Como queremos reduzir a margem, criar EspremeVertical como Section, e defina a propriedade margim-bottom com uma dimensão negativa, usei -30px.

Definir em Cell Class a classe EspremeVertical para os itens no grid.

O resultado será a apresentação mais próxima dos conteúdos quando estiver com uma dimensão Large na interface, pois a Rule será aplicada e a classe aplicada aos controles.



Diante disso tudo, espero que esta operação fique mais simples de ser feita no Genexus, pois está meio confusa.  Acho que o meu guru Steve Jobs deve ter se incomodado um pouco com esse formato.

Mostrar-ou-Não-Mostrar-Eis-A-Opção

Design responsivo em Genexus é simples com a aplicação do Pattern Work With, se for definir manualmente a coisa complica um pouco, pois não pense que apenas aplicar o tema Flat e usar o editor abstrato que já resolve a coisa.

Por exemplo, se criar um Grid e incluir colunas no mesmo, ao reduzir a dimensão do navegador não vai sumir nenhuma coluna por mágica.

Um certo jogo de classes CSS é que fazem a coisa ficar recursiva, ou seja, para dizer que certa coluna não precisa ser apresentada precisa colocar nesta coluna a classe WWOptionalColumn ou OptionalColumn (ambas produzem o mesmo efeito de esconder a coluna). Para as demais colunas, que seriam consideradas essenciais, uma classe WWColumn ou GridColumn.

Todas essas propriedades devem ser sempre colocadas em ColumnClass.

Aplicamos a classe OptionalColumn na coluna Id do nosso gridezinho exemplo e o resultado é esse abaixo quando reduzimos a largura do browser.

Conclusão

Bom, tem mais algumas coisas para explorar mas vamos com calma, melhor não assustar ninguém pois este tema é muito relevante para nossas aplicações no futuro. Pois me parece que haverá punição no search do Google para aplicações não responsivas, ou como dizem por ai, Mobile Friendly.

Para finalizar, um especial agradecimento a doutora Sabrina Juarez, pela sua imensa paciência nesta sexta-feira cansativa e pós evento.