Чтение и запись изображений в базу данных SQLite для использования на iPhone

StackOverflow https://stackoverflow.com/questions/643682

Вопрос

Я настроил базу данных SQLite, которая в данный момент читает и записывает NSStringэто прекрасно.Я также хочу сохранить изображение в базе данных и вызвать его позже.Я немного почитал об использовании NSData и кодирую изображение, но я не совсем уверен, каков синтаксис для того, что я хочу сделать.Мы были бы весьма признательны за любые фрагменты кода или примеры.

Мой текущий процесс выглядит следующим образом:UIImagePickerController -> Пользователь выбирает изображение из фотографий -> Выбранному изображению присваивается значение экземпляра UIImageView -> Теперь я хочу взять это изображение и сохранить его в базе данных

Я должен упомянуть, что этот вызов в конечном итоге будет заменен вызовом на удаленный сервер.Не уверен, влияет ли это на производительность.

Это было полезно?

Решение

Одним из вариантов (и обычно предпочтительным при работе с SQL) является запись изображения в файл в системе и сохранение пути (или какого-либо другого идентификатора) в базе данных.

Другие советы

Вам нужно будет преобразовать UIImage, размещенный в вашем UIImageView, в двоичный двоичный объект для хранения в SQLite.Чтобы сделать это, вы можете использовать следующее:

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

Это сгенерирует представление вашего изображения в формате PNG, сохранит его в экземпляре NSData, а затем свяжет байты из NSData в виде большого двоичного объекта для второго аргумента в вашем SQL-запросе.Используйте UIImageJPEGRepresentation в приведенном выше примере для хранения в этом формате, если хотите.Вам нужно будет добавить столбец BLOB-объекта в соответствующую таблицу в вашей базе данных SQLite.

Чтобы получить это изображение, вы можете использовать следующее:

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

Рекомендация Apple заключается в том, чтобы не хранить большие двоичные объекты в базах данных SQLite размером более ~ 2 килобайт.

SQLite организует базы данных по страницам.Размер каждой страницы составляет 4 килобайта.Когда вы считываете данные из файла базы данных SQLite, он загружает эти страницы во внутренний кэш страниц.На iPhone, я думаю, размер этого кэша по умолчанию равен 1 мегабайту.Это делает чтение соседних записей очень быстрым, потому что они, вероятно, уже находятся в кэше страниц.

Когда SQLite считывает запись вашей базы данных в память, он считывает всю запись и все страницы, которые она занимает.Таким образом, если ваша запись содержит большой двоичный объект, он может занимать много страниц, и вы будете извлекать существующие страницы из кэша и заменять их страницами вашей большой двоичной объекта.

Это не так уж плохо, если вы просто просматриваете и загружаете все свои большие двоичные объекты, чтобы что-то с ними сделать (например, отобразить их).Но если, скажем, вы выполнили запрос, в котором просто хотели получить некоторые данные, находящиеся в той же строке, что и большой двоичный объект, этот запрос будет выполняться намного медленнее, чем если бы запись не содержала большого большого двоичного объекта.

Таким образом, как минимум, вы должны хранить свои BLOB-данные в отдельной таблице.Например:

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

Или, что еще лучше, храните большие двоичные объекты в виде файлов вне базы данных SQLite.

Обратите внимание, что, возможно, удастся настроить размер кэша страницы с помощью Инструкции SQL PRAGMA (если вы не используете CoreData).

Запись изображения в базу данных 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);
    }

Чтение из базы данных 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];   

сначала вы должны записать изображение в файловую систему.а затем возьмите путь к изображению и сохраните этот путь к изображению (URL) в виде ТЕКСТА в sqlite.

Лучше всего сжать изображение и сохранить его в базе данных или файловой системе.Если вас не волнует разрешение изображения, вы можете пойти дальше и даже изменить размер изображения, используя :

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

После этого вы можете использовать UIImageJPEGRepresentation для изображений в формате jpeg со значением "0" для максимального сжатия.Или вы можете использовать UIImagePNGRepresentation для изображений в формате png

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top