Ler e escrever imagens para um SQLite DB para uso iPhone
-
22-07-2019 - |
Pergunta
Eu configurei um SQLite DB que atualmente lê e escreve NSString
s perfeitamente. Eu também quero guardar uma imagem no banco de dados e recuperá-lo mais tarde. Eu li um pouco sobre o uso NSData
e que codifica a imagem, mas eu não sou inteiramente certo o que a sintaxe é para o que eu quero fazer. Quaisquer fragmentos de código ou exemplos seria muito apreciada.
Meu processo atual é assim:
UIImagePickerController
-> O utilizador escolhe a imagem de Fotografias -> chosenImage está definido como instância de UIImageView
-> Agora eu quero tirar essa imagem e armazená-lo no DB
Eu devo mencionar esta chamada acabará por ser substituída por uma chamada para um servidor remoto. Não sei se isso faz a diferença, tanto quanto o desempenho vai.
Solução
Uma opção (e geralmente preferido quando se trabalha em SQL) é escrever a imagem para um arquivo no sistema e armazenar o caminho (ou algum outro tipo de identificador) no banco de dados.
Outras dicas
Você vai precisar para converter o UIImage hospedado dentro do seu UIImageView em um BLOB binário para o armazenamento em SQLite. Para fazer isso, você pode usar o seguinte:
NSData *dataForImage = UIImagePNGRepresentation(cachedImage);
sqlite3_bind_blob(yourSavingSQLStatement, 2, [dataForImage bytes], [dataForImage length], SQLITE_TRANSIENT);
Isso irá gerar uma representação PNG da sua imagem, armazená-lo em uma instância NSData, e depois ligam os bytes do NSData como um BLOB para o segundo argumento na sua consulta SQL. Use UIImageJPEGRepresentation no exemplo acima à loja nesse formato, se quiser. Você precisará ter uma coluna BLOB adicionada à tabela apropriada em seu banco de dados SQLite.
Para recuperar esta imagem, você pode usar o seguinte:
NSData *dataForCachedImage = [[NSData alloc] initWithBytes:sqlite3_column_blob(yourLoadingSQLStatement, 2) length: sqlite3_column_bytes(yourLoadingSQLStatement, 2)];
self.cachedImage = [UIImage imageWithData:dataForCachedImage];
[dataForCachedImage release];
recomendação da Apple não é a loja de BLOB de em bancos de dados SQLite que são maiores do que ~ 2 kilobytes.
SQLite organiza bases de dados em páginas. Cada página é de 4 kilobytes de tamanho. Quando você ler dados a partir do arquivo de banco de dados SQLite ele carrega estas páginas em um cache de página interna. No iPhone Acho que este padrão de cache para 1 megabyte de tamanho. Isto torna a leitura registros adjacentes muito rápido, porque eles provavelmente estarão no cache da página já.
Quando SQLite lê seu registro de banco de dados na memória ele lê o registro inteiro e todas as páginas que ele ocupa. Portanto, se seu registro contém um BLOB, ele poderia ocupar muitas páginas e você será páginas existentes ejetar do cache e substitui-los com as páginas do seu recorde BLOB.
Este não é tão ruim se você está apenas a digitalização através e carregar todas as suas gotas de fazer alguma coisa com eles (exibi-los, por exemplo). Mas se diz que fez uma consulta em que você só queria obter alguns dados que está na mesma linha que o BLOB essa consulta seria muito mais lento do que se o registro não continha o grande BLOB.
Assim, no mínimo você deve armazenar seus dados BLOB em uma tabela separada. Por exemplo:
CREATE TABLE blobs ( id INTEGER PRIMARY KEY, data BLOB );
CREATE TABLE photos ( id INTEGER PRIMARY KEY, name TEXT, blob_id INTEGER,
FOREIGN KEY(blob_id) REFERENCES blobs(id) );
Ou ainda melhor, armazenar os dados BLOB como arquivos fora do banco de dados SQLite.
Note-se que pode ser possível ajustar o tamanho do cache página com declarações SQL PRAGMA (se você não estiver usando CoreData).
imagem Escrevendo para SQLite DB
if(myImage != nil){
NSData *imgData = UIImagePNGRepresentation(myImage);
sqlite3_bind_blob(update_stmtement, 6, [imgData bytes], [imgData length], NULL);
}
else {
sqlite3_bind_blob(update_stmtement, 6, nil, -1, NULL);
}
Leitura De SQLite DB:
NSData *data = [[NSData alloc] initWithBytes:sqlite3_column_blob(init_statement, 6) length:sqlite3_column_bytes(init_statement, 6)];
if(data == nil)
NSLog(@"No image found.");
else
self.pictureImage = [UIImage imageWithData:data];
você deve primeiro escrever imagem no sistema de arquivos. e em seguida, tomar o caminho da imagem e armazenar esse caminho da imagem (URL) como texto no sqlite.
A melhor prática é para compactar a imagem e armazená-lo no sistema de banco de dados ou arquivo. Se você não se preocupam com a resolução da imagem que você pode ir em frente e até mesmo redimensionar a imagem usando:
UIGraphicsBeginImageContext(newSize);
[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Depois que você pode usar UIImageJPEGRepresentation
para imagens JPEG com um valor de "0" para a compressão máxima. Ou você pode usar UIImagePNGRepresentation
para PNG