Reading and writing images to an SQLite DB for iPhone use Reading and writing images to an SQLite DB for iPhone use sqlite sqlite

Reading and writing images to an SQLite DB for iPhone use


You'll need to convert the UIImage hosted within your UIImageView into a binary BLOB for storage in SQLite. To do that, you can use the following:

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

This will generate a PNG representation of your image, store it in an NSData instance, and then bind the bytes from the NSData as a BLOB for the second argument in your SQL query. Use UIImageJPEGRepresentation in the above to store in that format, if you like. You will need to have a BLOB column added to the appropriate table in your SQLite database.

To retrieve this image, you can use the following:

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


One option (and generally preferred when working in SQL) is to write the image to a file on the system and store the path (or some other kind of identifier) in the database.


Apple's recommendation is not to store BLOB's in SQLite databases that are bigger than ~2 kilobytes.

SQLite organizes databases into pages. Each page is 4 kilobytes in size. When you read data from the SQLite database file it loads these pages into an internal page cache. On the iPhone I think this cache defaults to 1 megabyte in size. This makes reading adjacent records very fast because they will probably be in the page cache already.

When SQLite reads your database record into memory it reads the entire record and all of the pages that it occupies. So if your record contains a BLOB, it could occupy many pages and you will be ejecting existing pages from the cache and replacing them with your BLOB record's pages.

This isn't so bad if you're just scanning through and loading all your BLOBS to do something with them (display them for example). But if say you did a query where you just wanted to get some data that is in the same row as the BLOB this query would be much slower than if the record did not contain the large BLOB.

So at a minimum you should store your BLOB data in a separate table. Eg:

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

Or better yet, store the BLOB data as files outside of the SQLite database.

Note that it may be possible to tweak the page cache size with SQL PRAGMA statements (if you're not using CoreData).