Question

J'ai mis en place une base de données SQLite qui lit et écrit parfaitement les NSString . Je souhaite également stocker une image dans la base de données et la rappeler ultérieurement. J'ai un peu lu sur l'utilisation de NSData et sur le codage de l'image, mais je ne suis pas tout à fait sûr de la syntaxe de ce que je veux faire. Des extraits de code ou des exemples seraient grandement appréciés.

Mon processus actuel est le suivant: UIImagePickerController - > L'utilisateur choisit une image à partir de photos - > selectedImage est défini sur l'instance de UIImageView - > Je souhaite maintenant prendre cette image et la stocker dans la base de données

Je dois mentionner que cet appel sera éventuellement remplacé par un appel à un serveur distant. Je ne sais pas si cela fait une différence en ce qui concerne les performances.

Était-ce utile?

La solution

Une option (et généralement préférable lorsque vous travaillez en SQL) consiste à écrire l'image dans un fichier du système et à stocker le chemin d'accès (ou un autre type d'identificateur) dans la base de données.

Autres conseils

Vous devez convertir UIImage hébergé dans votre UIImageView en un BLOB binaire pour le stockage dans SQLite. Pour ce faire, vous pouvez utiliser les éléments suivants:

NSData *dataForImage = UIImagePNGRepresentation(cachedImage);
sqlite3_bind_blob(yourSavingSQLStatement, 2, [dataForImage bytes], [dataForImage length], SQLITE_TRANSIENT);

Ceci générera une représentation PNG de votre image, la stockera dans une instance de NSData, puis liera les octets de NSData en tant que BLOB pour le second argument de votre requête SQL. Utilisez UIImageJPEGRepresentation dans ce qui précède pour stocker dans ce format, si vous le souhaitez. Une colonne BLOB doit être ajoutée à la table appropriée dans votre base de données SQLite.

Pour récupérer cette image, vous pouvez utiliser les éléments suivants:

NSData *dataForCachedImage = [[NSData alloc] initWithBytes:sqlite3_column_blob(yourLoadingSQLStatement, 2) length: sqlite3_column_bytes(yourLoadingSQLStatement, 2)];       
self.cachedImage = [UIImage imageWithData:dataForCachedImage];
[dataForCachedImage release];

Apple recommande de ne pas stocker les BLOB dans des bases de données SQLite supérieures à environ 2 kilo-octets.

SQLite organise les bases de données en pages. Chaque page a une taille de 4 kilo-octets. Lorsque vous lisez des données à partir du fichier de base de données SQLite, ces pages sont chargées dans un cache de page interne. Sur l’iPhone, la taille par défaut du cache est de 1 Mo par défaut. Cela rend la lecture des enregistrements adjacents très rapide car ils seront probablement déjà dans le cache des pages.

Lorsque SQLite lit votre enregistrement de base de données en mémoire, il lit l'intégralité de l'enregistrement et toutes les pages qu'il occupe. Ainsi, si votre enregistrement contient un BLOB, il pourrait occuper de nombreuses pages et vous éjecterez les pages existantes du cache en les remplaçant par les pages de votre enregistrement BLOB.

Ce n’est pas si grave si vous ne faites que scanner et charger tous vos BLOBs pour en faire quelque chose (affichez-les par exemple). Mais si vous faisiez une requête dans laquelle vous vouliez simplement que certaines données se trouvent dans la même ligne que le BLOB, cette requête serait beaucoup plus lente que si l'enregistrement ne contenait pas le grand BLOB.

Donc, vous devriez au minimum stocker vos données BLOB dans un tableau séparé. Par exemple:

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 mieux encore, stockez les données BLOB en tant que fichiers en dehors de la base de données SQLite.

Notez qu'il est peut-être possible de modifier la taille du cache de pages avec les instructions SQL PRAGMA (si vous n'utilisez pas CoreData).

Ecriture d'image dans une base de données SQLite

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);
    }

Lecture à partir de la base de données SQLite:

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];   

vous devriez d’abord écrire une image sur le système de fichiers. puis prenez le chemin de l'image et stockez ce chemin de l'image (URL) sous forme de texte dans sqlite.

La meilleure pratique consiste à compresser l'image et à la stocker dans la base de données ou le système de fichiers. Si vous ne vous souciez pas de la résolution de l'image, vous pouvez continuer et même redimensionner l'image en utilisant:

   UIGraphicsBeginImageContext(newSize);  
   [image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];   
   UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();    
   UIGraphicsEndImageContext();

Ensuite, vous pouvez utiliser UIImageJPEGRepresentation pour les images au format jpeg avec la valeur "0". pour une compression maximale. Ou vous pouvez utiliser UIImagePNGRepresentation pour les images png

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top