Чтение и запись изображений в базу данных SQLite для использования на iPhone
-
22-07-2019 - |
Вопрос
Я настроил базу данных 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