#include "pgfutils.h" #include "sqlite3.h" #include #include #include #include void usage() { std::cerr << "Usage: digikam_extract_thumbs /path/to/thumbnails-digikam.db /path/to/output/folder\n"; } sqlite3* open_db(std::string path) { sqlite3 *db; if(auto retval = sqlite3_open(path.c_str(), &db)) { std::ostringstream s; s << "Can't open database " << path << ": " << sqlite3_errmsg(db) << std::endl; throw std::runtime_error(s.str()); } return db; } int main(int argc, char* argv[]) { if(argc != 3) { std::cerr << "Incorrect amount of arguments.\n"; usage(); exit(1); } std::string sqlite_path(argv[1]); std::string output_path(argv[2]); auto db = open_db(sqlite_path); std::string query = "SELECT UniqueHashes.uniqueHash, Thumbnails.data FROM Thumbnails INNER JOIN UniqueHashes ON Thumbnails.id=UniqueHashes.thumbId;"; sqlite3_stmt *stmt; sqlite3_prepare_v2(db, query.c_str(), query.length(), &stmt, 0); int result = sqlite3_step(stmt); int i = 0; while(result == SQLITE_ROW) { const std::string unique_hash((const char*)sqlite3_column_text(stmt, 0)); int size = sqlite3_column_bytes(stmt, 1); const char* data_start = static_cast(sqlite3_column_blob(stmt, 1)); const char* data_end = data_start + size; //std::vector data(data_start, data_end); QByteArray qdata(data_start, size); QImage thumb; if(readPGFImageData(qdata, thumb, false)) { auto filename = output_path + "/" + unique_hash + ".jpg"; //std::cout << i << ": " << unique_hash << ": " << size << " bytes -> " << filename << std::endl; thumb.save(QString::fromStdString(filename)); } else { throw std::runtime_error("Failed to read PGF image.\n"); } result = sqlite3_step(stmt); i++; if(i % 100 == 0) { std::cout << i << "\n"; } } std::cout << "Done (" << i << " total)\n"; sqlite3_close(db); }