Artigos de ‘jan 2012’

Javascript – Checking the file size


Stack Overflow
Felipe Sabino
30janeiro

It is true that Javascript has no access to your File System.

http://en.wikipedia.org/wiki/JavaScript#Security

“JavaScript and the DOM provide the potential for malicious authors to deliver scripts to run on a client computer via the web. Browser authors contain this risk using two restrictions. First, scripts run in a sandbox in which they can only perform web-related actions, not general-purpose programming tasks like creating files”

However, the HTML5 File API specification, compatible with current modern browsers (IE 9- excluded, obviously), finally allows a standard interaction with local files.

For example, you could get the selected file size as the following

For the HTML bellow

<input type="file" id="myFile" />

Here is the Javascript code to alert the file size every time the user selects a different file.

//gets the element by its id
var myFile = document.getElementById('myFile');
 
//binds to onchange event of the input field
myFile.addEventListener('change', function() {
  //this.files[0].size gets the size of your file.
  alert(this.files[0].size);
 
});

In the example above, this.files exposes a FileList object, which is an array-like object of File objects.

As described by the File’s object HTML specification here are some other file properties you could retrieve.

  • name: Returns a string containing the file name (without the path information)
  • lastModifiedDate: Returns a Date object that represents the file last modified date
  • size: Returns an integer representing the file size in bytes
  • type: Returns a string with the file MIME type

This is a perfect solution for improving user experience while implementing file uploads and avoiding having to submit the file to have this kind of check only at the server side.

Other useful resources:

http://html5-demos.appspot.com/static/gdd11-modern-web-apps/index.html

http://stackoverflow.com/questions/4349144/will-ie9-support-the-html5-file-api

permalink
, , , , , , , ,

Uma Semana, um App e um Estudo de Caso


Ux
Daniel Mack
30janeiro

Um aplicativo muito interessante que foi criado dentro de uma loja, consiste em comparar modelos de óculos através da interação com o aplicativo de iPad.
O lado deslumbrante é como foi produzido de uma forma nunca visto antes.

A equipe de Nordstrom Innovation conseguiu introduzir os processos de design centrado no usuário tendo feedback instantâneo das funcionalidades principais. O aplicativo torna-se fácil, rápido e vai direto ao ponto.
Confira como foi tudo isso foi implementado no vídeo.

Criação e produção de Nordstrom Innovation.

permalink
, , , , , , , , , , , ,

Hy-Vee Mobile App


Apps
Edmar Miyake
27janeiro

Já imaginou entrar em um supermercado e ter na palma da mão a localização exata dos produtos que procura?

Esta é apenas uma das dezenas inovações que colocamos neste aplicativo mobile para a rede de supermercados norte-americana Hy-Vee.

Inúmeras outras novidades foram inseridas no aplicativo que realmente facilitam a vida do consumidor como busca de produtos por reconhecimento de voz, cupons de desconto, receitas, etc. Vale conferir o vídeo para saber mais sobre o aplicativo e a linha de produtos I.ndigo m-Commerce.

O aplicativo, que já estava disponível gratuitamente na App Store agora também na versão Android.

permalink
, , , , ,

Releasing NSURLConnection and its delegate


Stack Overflow
Felipe Sabino
27janeiro

When not using ARC, you will have to pay extra attention to NSURLConnection’s delegate object as there is a special consideration for it: it is always retained.

http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/Reference/Reference.html#//apple_ref/doc/uid/20001697-BAJDDIDG

initWithRequest:delegate:
 
Special Considerations: The connection retains delegate. It releases delegate when the connection finishes loading, fails, or is canceled.

So, taking that into consideration, you have several options to ensure that your delegate will be released correctly and I will try to explain 2 simple ones.

The first, and most commonly used, is to use the same class that initialize the NSURLConnection as the delegate.

[[NSURLConnection alloc] initWithRequest:request self];

By doing that, your class the retain count would be increased by 1 when the connection starts and then would de reduced by 1 after the connection finishes loading, fails, or is canceled, resulting in no memory leaks.

The second option, the one that you are trying to do, is to use another object to handle all connection calls. This works fine as well, but you will need extra attention with memory. One simple thing you could do to solve your problem is to initialize the connection with an autorelease object.

//creates the handler object
MyHandlerClass *handler = [[MyHandlerClass alloc] init];
 
//creates the connection with handler as an autorelease object
[[NSURLConnection alloc] initWithRequest:request delegate:[handler autorelease]];

OR you could release your handler right after creating the connection (as it will be already retained by the connection)

 
//creates the handler object
MyHandlerClass *handler = [[MyHandlerClass alloc] init];
 
//creates the connection with handler
[[NSURLConnection alloc] initWithRequest:request delegate:handler];
 
//releases handler object
[handler release];

Both ways will leave the handler object ownership only with the connection class, which will release the handler object right after it finishes loading, fails, or is canceled, once again resulting in no memory leaks. And you will not have to worry about releasing the delegate (but you still have to release the connection) in connectionDidFinishLoading and connection:didFailWithError: methods.

permalink
, , , , , , ,

Xperia Smart Tags


Keep Watching
Edmar Miyake
24janeiro

Parece mesmo um caminho sem volta a adoção do NFC pelos fabricantes de smartphones. Near field communication é uma tecnologia baseada em rádio-frequência que é cada vez mais utilizada no mundo, principalmente para pagamentos que costumam ser feitos com cartões de crédito e até transporte público (ao que tudo indica São Paulo pode ser a próxima cidade a adotar).

No entanto a Sony inovou ao apresentar um jeito muito mais criativo e pessoal de lidar com a tecnologia. As Smart Tags são pequenos tokens programáveis que dão uma série de comandos para o smartphone de acordo com o contexto do usuário.

Por exemplo, ao entrar no carro e detectar a presença da Smart Tag, o celular já ativa o GPS, o Bluetooth e desliga o Wifi, ou ainda, quando chegar ao escritório ativa o Wifi, ajusta o volume de toque e abre o calendário do dia e assim por diante.

Segundo representantes da Sony, as Smart Tags vão ser lançadas ainda neste semestre e o conjunto com 4 tokens vai sair ao redor de US$30 nos Estados Unidos.

permalink
, , , , , ,

Minnesota Wild iPhone app


Apps
Edmar Miyake
23janeiro

Mais um app desenvolvido pela I.ndigo que ganha destaque na mídia norte-americana.

Os apresentadores da rede ABC destacam entre as funcionalidades do aplicativo, o fato de você poder fazer um pedido à lanchonete do estádio sem precisar sair do seu lugar, os replays exclusivos e, a integração com as redes sociais.

Além das funcionalidades citadas acima, os torcedores também podem acompanhar os resultados do time, estatísticas da equipe e dos jogadores, localizar bares que irão transmitir o jogo e muito mais.

O aplicativo do Minnesota Wild, time da NHL, é mais uma implementação do nosso produto de automação de estádios e arenas, assim como fizemos para a Stanford University.

Ele já está disponível na app store e em breve também no Android Market.

Faça o download e nos diga o que achou.

permalink
, , , , , , , ,

Mobile Year in Review


English
Felipe Sabino
20janeiro

2011 was a really intense year here at I.ndigo. More rewarding than launching 29 apps, was being able to witness the Brazilian market maturation and successfully accomplish worldwide recognized cases.

We would like to thank all partners, agencies, clients, employees and our families for believing in our potential and helping us build this result that we are pleased to share with you.

Bring on 2012!

permalink
, , , , , , , , , , ,

Mobile Year in Review


App Forward, Apps, Go Tech, Keep Watching, Mobile Trends & Mobile Business
Edmar Miyake
20janeiro

Infografico I.ndigo 2011

O ano de 2011 foi realmente intenso aqui na I.ndigo. Mais gratificante do que o lançamento dos 29 apps, foi poder testemunhar o amadurecimento do mercado brasileiro e emplacar cases reconhecidos no mundo inteiro.

Agradecemos a todos os parceiros, agências, clientes, colaboradores e às nossas famílias por confiarem em nosso potencial e nos ajudarem a construir o resultado que temos o prazer de compartilhar com vocês.

Que venha 2012!

permalink
, , , , , , , , , , ,

iOS Facial Recognition


English
Raphael Petegrosso
19janeiro

iOS Facial Recognition Test

Core Image was one of the many interesting topics discussed at iOS Tech Talk Tour that took place in São Paulo on january 9th. It is a framework that was already available at the MacOS and now can also be used by iOS developers.

It is important to notice that this framework is available only after iOS 5.0, resulting in a use limited to the application requirements. However, according to CNET the percentage of devices using iOS 5 in November, 2011 was already 40%, showing that apps developed to this version will shortly be available to the majority of users

Facial recognition is, by far, the most interesting of Core Image’s features, which will be detailed in this article. This new technique allow developers to think about new apps using this concept with a very low implementation cost.

We will show you how to implement the facial recognition straight from the device’s camera data stream. The source code is based on Apple’s SquareCam example project.


Camera Configuration

The first step is to configure the camera using the AVFoundation Framework, available since iOS 4 release in a way we can directly read the device stream.

This configuration is made in order to use the following objects:

  • AVCaptureSession – This object represents a session that coordinates the data flow from AV input devices to the output. In order to accomplish that, We add the input and output devices to this session object and start data flow using the startRunning messages (and stop it by using stopRunning).

  • AVCaptureDevice – It is a physical device abstraction which provides an input for a AVCapureSession object. There is an object available for every input device type, for instance: there is one video input for iPhone 3G, but there are two of them for iPhone 4.

  • AVCaptureDeviceInput – It is an AVCaptureInput subclass used to add and input device into a session (AVCaptureSession).

  • AVCaptureOutput – It is an abstract class used to find a session output (AVCaptureSession).
The image below, from Apple’s AV Foundation Programming Guide shows the interaction between the instances and their data flow:

The folowing chunk of code was taken from SquareCam project. It shows how to configure the camera:

- (void)setupAVCapture
{
    AVCaptureSession *session = [AVCaptureSession new];
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
        [session setSessionPreset:AVCaptureSessionPreset640x480];
    else
        [session setSessionPreset:AVCaptureSessionPresetPhoto];
 
    // Select a video device, make an input
    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
 
    if ( [session canAddInput:deviceInput] )
        [session addInput:deviceInput];
 
    // Make a video data output
    videoDataOutput = [[AVCaptureVideoDataOutput alloc] init];
 
    // we want BGRA, both CoreGraphics and OpenGL work well with 'BGRA'
    NSDictionary *rgbOutputSettings = [NSDictionary dictionaryWithObject:
    [NSNumber numberWithInt:kCMPixelFormat_32BGRA] forKey:(id)kCVPixelBufferPixelFormatTypeKey];
    [videoDataOutput setVideoSettings:rgbOutputSettings];
    [videoDataOutput setAlwaysDiscardsLateVideoFrames:YES]; // discard if the data output queue is blocked (as we process the still image)
 
    videoDataOutputQueue = dispatch_queue_create("VideoDataOutputQueue", NULL);
    [videoDataOutput setSampleBufferDelegate:self queue:videoDataOutputQueue];
 
    if ( [session canAddOutput:videoDataOutput] )
        [session addOutput:videoDataOutput];
 
    previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
    [previewLayer setBackgroundColor:[[UIColor blackColor] CGColor]];
    [previewLayer setVideoGravity:AVLayerVideoGravityResizeAspect];
    CALayer *rootLayer = [previewView layer];
    [rootLayer setMasksToBounds:YES];
    [previewLayer setFrame:[rootLayer bounds]];
    [rootLayer addSublayer:previewLayer];
    [session startRunning];
 
}

Identifying a face with a CIDetector

According to CIDetector’s Class Reference the CIDetector object (available since iOS 5 inside CoreImage.framework) uses image processing to find “features” inside an image.

So, the next step is to identify the face in our video data stream is to configure a CIDetector. We can create an instance of the object by instantiating:

NSDictionary *detectorOptions = [[NSDictionary alloc] initWithObjectsAndKeys:CIDetectorAccuracyLow, CIDetectorAccuracy, nil];
 
faceDetector = [[CIDetector detectorOfType:CIDetectorTypeFace context:nil options:detectorOptions] retain];

When we previously initialized the camera, we configured our controller to act as a the video output stream’s delegate (videoDataOutput) at the line:

[videoDataOutput setSampleBufferDelegate:self queue:videoDataOutputQueue];

We can now implement the following method to read the video data stream:

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{}

Finally, with a CIDetector’s instance and the video data stream, We can identify our face.

// got an image
CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
CFDictionaryRef attachments = CMCopyDictionaryOfAttachments(kCFAllocatorDefault, sampleBuffer, kCMAttachmentMode_ShouldPropagate);
CIImage *ciImage = [[CIImage alloc] initWithCVPixelBuffer:pixelBuffer options:(NSDictionary *)attachments];
if (attachments)
    CFRelease(attachments);
NSDictionary *imageOptions = nil;
 
// '6' identifies device on vertical position
imageOptions = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:6] forKey:CIDetectorImageOrientation];
NSArray *features = [faceDetector featuresInImage:ciImage options:imageOptions];
[ciImage release];

The array features have each element as an instance of a CIFaceFeature, which identify a new face found in the video and allow us to retrieve several information from it.


Image’s CIFaceFeature

A CIFaceFeature object properties describes the face found in a image. These properties are:

hasLeftEyePosition
hasRightEyePosition
hasMouthPosition
leftEyePosition
rightEyePosition
mouthPosition

Besides that, due to its CIFeature inheritance, it also has the following properties:

bounds – The rectangle that the feature was found inside
type – The feature type

By using this information several actions can be taken, such as adding new visual elements on top of the face which was found in the image.


CIDetectorAccuracyLow Vs CIDetectorAccuracyHigh

When we created our CIDetector, we provided the CIDetectorAccuracyLow parameter:

NSDictionary *detectorOptions = [[NSDictionary alloc] initWithObjectsAndKeys:CIDetectorAccuracyLow, CIDetectorAccuracy, nil];

The reason we did that is because we are trying to read from a video stream, and using this option results in a faster analysis for each video frame, however, with a higher chance of not detecting any face at all.

In general, the CIDetectorAccuracyHigh option is used to analyse a single picture, resulting in a slower processing time, but with a higher face detection rate.

As you can notice, iOS 5 made it extremely easy to integrate facial recognition, which allows us to think again in several features that would be impracticable to implement in a project before. That said, we still have to be aware of the project requirements, since not all the users updates their operating system to the latest iOS version.

This post is also available in portuguese here.

permalink
, , , , , ,

Reconhecimento de Faces no iOS


Go Tech
Raphael Petegrosso
19janeiro

iOS Facial Recognition Test

Um dos interessantes tópicos abordados no evento iOS 5 Tech Talk Tour, que aconteceu em São Paulo no último dia 9 de janeiro, se refere ao Core Image, um framework que já era disponível no MacOS e agora pode ser usado pelos desenvolvedores de aplicativos para o iOS.

É importante ressaltar que este framework está disponível apenas a partir do iOS 5.0, o que torna o seu uso ainda limitado aos requisitos do aplicativo. Porém, de acordo com artigo do site CNET em novembro de 2011 a porcentagem de devices utilizando o iOS 5 já era de 40%, o que mostra que em pouco tempo os aplicativos lançados para essa versão já poderão ser baixados pela maior parte dos usuários.

Com certeza uma das características mais interessantes do Core Image para o iPhone é sua capacidade de reconhecimento de face, que vamos abordar neste artigo. Esta nova técnica faz com que possamos pensar em diversas aplicações utilizando este conceito, com baixo custo de implementação.

Vamos mostrar como fazer o reconhecimento de faces lendo diretamente do stream da câmera do iPhone. O código-fonte mostrado baseia-se no projeto SquareCam disponibilizado pela Apple como exemplo de uso de Reconhecimento de Faces, presente aqui.


Configuração da Camera

Primeiramente, iremos configurar a câmera utilizando o framework AVFoundation, disponível a partir do iOS 4, de modo que possamos ler diretamente o stream do dispositivo.

A configuração é feita para que tenhamos as seguintes instâncias:

  • AVCaptureSession – Este objeto representa uma sessão que coordena o fluxo de dados dos dispositivos de entrada AV para as saídas. Para isso, adicionamos os dispositivos de captura e saídas para esta sessão e iniciamos o fluxo de dados enviando uma mensagem startRunning e paramos com uma mensagem stopRunning.

  • AVCaptureDevice – É uma abstração de um dispositivo físico de captura que fornece uma entrada para um objeto AVCaptureSession. Há um objeto disponível para cada tipo de dispositivo de entrada. Por exemplo: no iPhone 3GS há uma entrada de vídeo, enquanto que no iPhone 4 há duas entradas.

  • AVCaptureDeviceInput – É uma subclasse de AVCaptureInput usada para adicionar um dispositivo de entrada em uma sessão (AVCaptureSession).

  • AVCaptureOutput – É uma classe abstrata usada para buscar uma saída da sessão (AVCaptureSession).
A imagem abaixo, retirada do AV Foundation Programming Guide da Apple mostra a interação entre estas instâncias e o fluxo de dados entre elas:

Vamos ver, em termos de código, como configurar a câmera. Utilizaremos o seguinte código, que foi reduzido do projeto SquareCam, para melhor visualização:

- (void)setupAVCapture
{
    AVCaptureSession *session = [AVCaptureSession new];
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
        [session setSessionPreset:AVCaptureSessionPreset640x480];
    else
        [session setSessionPreset:AVCaptureSessionPresetPhoto];
 
    // Select a video device, make an input
    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
 
    if ( [session canAddInput:deviceInput] )
        [session addInput:deviceInput];
 
    // Make a video data output
    videoDataOutput = [[AVCaptureVideoDataOutput alloc] init];
 
    // we want BGRA, both CoreGraphics and OpenGL work well with 'BGRA'
    NSDictionary *rgbOutputSettings = [NSDictionary dictionaryWithObject:
    [NSNumber numberWithInt:kCMPixelFormat_32BGRA] forKey:(id)kCVPixelBufferPixelFormatTypeKey];
    [videoDataOutput setVideoSettings:rgbOutputSettings];
    [videoDataOutput setAlwaysDiscardsLateVideoFrames:YES]; // discard if the data output queue is blocked (as we process the still image)
 
    videoDataOutputQueue = dispatch_queue_create("VideoDataOutputQueue", NULL);
    [videoDataOutput setSampleBufferDelegate:self queue:videoDataOutputQueue];
 
    if ( [session canAddOutput:videoDataOutput] )
        [session addOutput:videoDataOutput];
 
    previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
    [previewLayer setBackgroundColor:[[UIColor blackColor] CGColor]];
    [previewLayer setVideoGravity:AVLayerVideoGravityResizeAspect];
    CALayer *rootLayer = [previewView layer];
    [rootLayer setMasksToBounds:YES];
    [previewLayer setFrame:[rootLayer bounds]];
    [rootLayer addSublayer:previewLayer];
    [session startRunning];
 
}

Identificando um Rosto com um CIDetector

De acordo com o CIDetector Class Reference da Apple, um objeto CIDetector, disponível a partir do iOS 5 no framework CoreImage.framework, usa processamento de imagem para encontrar “features” em uma imagem.

Assim, o próximo passo para identificar o rosto no nosso stream de vídeo é configurar um CIDetector. Após adicionamos este framework no projeto, criamos uma instância dele para utilizarmos da seguinte forma:

NSDictionary *detectorOptions = [[NSDictionary alloc] initWithObjectsAndKeys:CIDetectorAccuracyLow, CIDetectorAccuracy, nil];
 
faceDetector = [[CIDetector detectorOfType:CIDetectorTypeFace context:nil options:detectorOptions] retain];

Em nossa inicialização da câmera feita anteriormente configuramos nosso controller para atuar como delegate do stream de vídeo (videoDataOutput) com a seguinte linha:

[videoDataOutput setSampleBufferDelegate:self queue:videoDataOutputQueue];

Desta forma, podemos implementar o seguinte método para ler o stream do vídeo:

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{}

Por fim, com uma instância de um CIDetector e um método que lê o stream da câmera, podemos identificar um rosto utilizando o seguinte:

// got an image
CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
CFDictionaryRef attachments = CMCopyDictionaryOfAttachments(kCFAllocatorDefault, sampleBuffer, kCMAttachmentMode_ShouldPropagate);
CIImage *ciImage = [[CIImage alloc] initWithCVPixelBuffer:pixelBuffer options:(NSDictionary *)attachments];
if (attachments)
    CFRelease(attachments);
NSDictionary *imageOptions = nil;
 
// '6' identifies device on vertical position
imageOptions = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:6] forKey:CIDetectorImageOrientation];
NSArray *features = [faceDetector featuresInImage:ciImage options:imageOptions];
[ciImage release];

No código acima, temos o array features onde cada elemento é uma instância de um CIFaceFeature, que identifica uma face encontrada no vídeo e permite encontrar diversas informações sobre ela.


CIFaceFeature de uma Imagem

Um objeto CIFaceFeature descreve uma face encontrada em uma imagem. Suas propriedades informam as posições dos olhos e da boca da face. Estas propriedades são as seguintes:

hasLeftEyePosition – Informa se a posição do olho esquerdo esta disponível
hasRightEyePosition – Informa se a posição do olho direito esta disponível
hasMouthPosition – Informa se a posição da boca esta disponível
leftEyePosition – Informa a posição do olho esquerdo
rightEyePosition – Informa a posição do olho direito
mouthPosition – Informa a posição da boca

Além disso, por herdar de um CIFeature, também possui as seguintes propriedades:

bounds – Um retângulo que contém a feature encontrada
type – O tipo de feature encontrado

A partir destas informações diversas ações podem ser tomadas, como inserir elementos visuais sobre a face encontrada.


Modo CIDetectorAccuracyLow Vs CIDetectorAccuracyHigh

Quando criamos nosso CIDetector, um parâmetro de configuração utilizado foi CIDetectorAccuracyLow, como pode ser visto a seguir:

NSDictionary *detectorOptions = [[NSDictionary alloc] initWithObjectsAndKeys:CIDetectorAccuracyLow, CIDetectorAccuracy, nil];

O motivo desse uso foi pelo fato de estarmos fazendo a detecção diretamente do stream de vídeo e, por isso, utilizar esta opção faz com a análise de cada frame seja mais rápida, porém tendo uma chance maior de não detectar uma face.

De modo geral, a opção CIDetectorAccuracyHigh é utilizada somente quando vamos analisar uma única imagem, o que permite que possamos ter um processamento um pouco mais lento, encontrando com mais facilidade as faces.

Como podemos ver, a partir do iOS 5 ficou bem mais fácil utilizar detecção de faces em aplicativos, o que nos permite pensar em diversas soluções que anteriormente poderiam ser consideradas inviáveis para um projeto. Porém, como dito, devemos ainda nos alertar quanto aos requisitos do projeto, uma vez que nem todos os usuários já possuem esta versão de iOS.

Este post também está disponível em inglês aqui.

permalink
, , , , , ,