19#define LS_DB_SCHEMA_VERSION 4
31 const char *detail = db->
sql ? sqlite3_errmsg(db->
sql) :
"no connection";
32 snprintf(db->
error,
sizeof(db->
error),
"%s: %s", what, detail);
48 if(!path || !*path)
return NULL;
50 const int is_uri = strncmp(path,
"file:", 5) == 0;
51 const size_t len = strlen(path);
53 char *uri = (
char *)malloc(len * 3 + 64);
59 memcpy(uri, path, len);
64 memcpy(uri,
"file:", 5);
66 for(
size_t i = 0; i < len; i++)
68 const unsigned char c = (
unsigned char)path[i];
69 if(c ==
'?' || c ==
'#' || c ==
'%')
71 static const char hex[] =
"0123456789ABCDEF";
73 uri[w++] = hex[c >> 4];
74 uri[w++] = hex[c & 0xF];
81 const char *sep = strchr(uri,
'?') ?
"&" :
"?";
82 w += (size_t)snprintf(uri + w, 64,
"%smode=ro&immutable=1", sep);
102 const int rc = sqlite3_open_v2(uri, &db->
sql,
103 SQLITE_OPEN_READONLY | SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_URI,
112 sqlite3_stmt *st = NULL;
113 if(sqlite3_prepare_v2(db->
sql,
"PRAGMA user_version", -1, &st, NULL) == SQLITE_OK
114 && sqlite3_step(st) == SQLITE_ROW)
116 sqlite3_finalize(st);
129 if(db->
sql) sqlite3_close(db->
sql);
135 return (db && db->
error[0]) ? db->
error : NULL;
158 if(!out || out_size == 0)
return 0;
160 int pending_space = 0;
162 for(
const unsigned char *p = (
const unsigned char *)(in ? in :
""); *p; p++)
164 unsigned char c = *p;
165 if(c <=
' ' || c ==
'_' || c ==
'-' || c ==
'/' || c ==
'\\' || c ==
',' || c ==
'.'
166 || c ==
'(' || c ==
')' || c ==
'[' || c ==
']' || c ==
'\'' || c ==
'"' || c ==
':'
167 || c ==
';' || c ==
'+' || c ==
'*')
169 if(w > 0) pending_space = 1;
172 if(c >=
'A' && c <=
'Z') c = (
unsigned char)(c -
'A' +
'a');
176 if(w + 1 >= out_size)
break;
180 if(w + 1 >= out_size)
break;
196 {
"SELECT model, focal, t0, t1, t2 FROM calib_distortion WHERE lens_id = ?1 ORDER BY ord", 3 },
197 {
"SELECT model, focal, t0, t1, t2, t3, t4, t5 FROM calib_tca WHERE lens_id = ?1 ORDER BY ord", 6 },
198 {
"SELECT model, focal, aperture, distance, t0, t1, t2 FROM calib_vignetting WHERE lens_id = ?1 ORDER BY ord", 3 },
201 for(
int kind = 0; kind < 3; kind++)
203 sqlite3_stmt *st = NULL;
204 if(sqlite3_prepare_v2(db->
sql, q[kind].sql, -1, &st, NULL) != SQLITE_OK)
206 _db_err(db,
"prepare calibration");
209 sqlite3_bind_int64(st, 1, lens_id);
213 while(sqlite3_step(st) == SQLITE_ROW)
220 const int model = sqlite3_column_int(st, 0);
221 const float focal = (float)sqlite3_column_double(st, 1);
228 for(
int t = 0; t < 3; t++) c->
terms[t] = (
float)sqlite3_column_double(st, 2 + t);
235 for(
int t = 0; t < 6; t++) c->
terms[t] = (
float)sqlite3_column_double(st, 2 + t);
242 c->
aperture = (float)sqlite3_column_double(st, 2);
243 c->
distance = (float)sqlite3_column_double(st, 3);
244 for(
int t = 0; t < 3; t++) c->
terms[t] = (
float)sqlite3_column_double(st, 4 + t);
248 sqlite3_finalize(st);
257 "lens %lld has more than %d calibration entries of one kind",
262 if(kind == 0) out->
n_dist = n;
263 else if(kind == 1) out->
n_tca = n;
273 sqlite3_stmt *st = NULL;
274 if(sqlite3_prepare_v2(db->
sql,
275 "SELECT focal, real_focal FROM lens_real_focal WHERE lens_id = ?1"
276 " ORDER BY focal", -1, &st, NULL) != SQLITE_OK)
278 _db_err(db,
"prepare real focal");
281 sqlite3_bind_int64(st, 1, lens_id);
283 while(sqlite3_step(st) == SQLITE_ROW && n <
LS_MAX_CALIB)
289 sqlite3_finalize(st);
297 if(!db || !db->
sql || !out)
return -1;
298 memset(out, 0,
sizeof(*out));
300 sqlite3_stmt *st = NULL;
301 if(sqlite3_prepare_v2(db->
sql,
302 "SELECT type, crop_factor, aspect_ratio, center_x, center_y,"
303 " min_focal, max_focal FROM lens WHERE id = ?1",
304 -1, &st, NULL) != SQLITE_OK)
309 sqlite3_bind_int64(st, 1, lens_id);
311 if(sqlite3_step(st) != SQLITE_ROW)
313 sqlite3_finalize(st);
317 out->
crop_factor = (float)sqlite3_column_double(st, 1);
318 out->
aspect_ratio = (float)sqlite3_column_double(st, 2);
319 out->
center_x = (float)sqlite3_column_double(st, 3);
320 out->
center_y = (float)sqlite3_column_double(st, 4);
321 out->
min_focal = (float)sqlite3_column_double(st, 5);
322 out->
max_focal = (float)sqlite3_column_double(st, 6);
323 sqlite3_finalize(st);
334 char nmodel[512], nmaker[512];
340 sqlite3_stmt *st = NULL;
341 if(sqlite3_prepare_v2(db->
sql,
342 "SELECT l.id FROM lens l"
343 " JOIN lens_name m ON m.lens_id = l.id AND m.kind = 'model' AND m.norm = ?1"
344 " WHERE (?3 = 0 OR EXISTS (SELECT 1 FROM lens_name k"
345 " WHERE k.lens_id = l.id AND k.kind = 'maker' AND k.norm = ?2))"
346 " ORDER BY abs(l.crop_factor - ?4) ASC, l.id ASC LIMIT 1",
347 -1, &st, NULL) != SQLITE_OK)
349 _db_err(db,
"prepare lens lookup");
352 sqlite3_bind_text(st, 1, nmodel, -1, SQLITE_STATIC);
353 sqlite3_bind_text(st, 2, nmaker, -1, SQLITE_STATIC);
354 sqlite3_bind_int(st, 3, (maker && *nmaker) ? 1 : 0);
355 sqlite3_bind_double(st, 4, (crop > 0.f) ? (
double)crop : 0.0);
358 if(sqlite3_step(st) == SQLITE_ROW)
id = sqlite3_column_int64(st, 0);
359 sqlite3_finalize(st);
366 if(!db || !db->
sql || !model || !out)
return -1;
369 if(
id < 0)
return -1;
370 if(
id == 0)
return 0;
376 if(!db || !db->
sql || !model || !out)
return -1;
377 memset(out, 0,
sizeof(*out));
379 char nmodel[512], nmaker[512];
383 sqlite3_stmt *st = NULL;
384 if(sqlite3_prepare_v2(db->
sql,
385 "SELECT c.crop_factor, ifnull(c.mount_id, 0), c.id FROM camera c"
386 " JOIN camera_name m ON m.camera_id = c.id AND m.kind = 'model' AND m.norm = ?1"
387 " WHERE (?3 = 0 OR EXISTS (SELECT 1 FROM camera_name k"
388 " WHERE k.camera_id = c.id AND k.kind = 'maker' AND k.norm = ?2))"
389 " ORDER BY c.id ASC LIMIT 1",
390 -1, &st, NULL) != SQLITE_OK)
392 _db_err(db,
"prepare camera lookup");
395 sqlite3_bind_text(st, 1, nmodel, -1, SQLITE_STATIC);
396 sqlite3_bind_text(st, 2, nmaker, -1, SQLITE_STATIC);
397 sqlite3_bind_int(st, 3, (maker && *nmaker) ? 1 : 0);
400 if(sqlite3_step(st) == SQLITE_ROW)
402 out->
crop_factor = (float)sqlite3_column_double(st, 0);
403 out->
mount_id = sqlite3_column_int64(st, 1);
404 out->
id = sqlite3_column_int64(st, 2);
407 sqlite3_finalize(st);
413 if(!db || !db->
sql)
return -1;
414 if(mount_id <= 0)
return 0;
416 sqlite3_stmt *st = NULL;
418 if(sqlite3_prepare_v2(db->
sql,
419 "SELECT 1 FROM lens_mount lm WHERE lm.lens_id = ?1 AND ("
421 " OR EXISTS (SELECT 1 FROM mount_compat mc"
422 " WHERE mc.mount_id = ?2 AND mc.compat_id = lm.mount_id))"
424 -1, &st, NULL) != SQLITE_OK)
426 _db_err(db,
"prepare mount test");
429 sqlite3_bind_int64(st, 1, lens_id);
430 sqlite3_bind_int64(st, 2, mount_id);
431 const int fits = (sqlite3_step(st) == SQLITE_ROW) ? 1 : 0;
432 sqlite3_finalize(st);
438 if(!db || !db->
sql)
return -1;
440 sqlite3_stmt *st = NULL;
441 if(sqlite3_prepare_v2(db->
sql,
"SELECT id FROM lens ORDER BY id ASC", -1, &st, NULL) != SQLITE_OK)
443 _db_err(db,
"prepare lens list");
447 while(sqlite3_step(st) == SQLITE_ROW)
452 out_ids[n] = sqlite3_column_int64(st, 0);
456 sqlite3_finalize(st);
461 char *model,
size_t model_size)
463 if(!db || !db->
sql)
return -1;
464 if(maker && maker_size) maker[0] =
'\0';
465 if(model && model_size) model[0] =
'\0';
467 sqlite3_stmt *st = NULL;
468 if(sqlite3_prepare_v2(db->
sql,
"SELECT maker, model FROM lens WHERE id = ?1", -1, &st, NULL)
471 _db_err(db,
"prepare lens name");
474 sqlite3_bind_int64(st, 1, lens_id);
477 if(sqlite3_step(st) == SQLITE_ROW)
479 const char *a = (
const char *)sqlite3_column_text(st, 0);
480 const char *b = (
const char *)sqlite3_column_text(st, 1);
481 if(maker && maker_size && a)
483 snprintf(maker, maker_size,
"%s", a);
484 written += (int)strlen(maker);
486 if(model && model_size && b)
488 snprintf(model, model_size,
"%s", b);
489 written += (int)strlen(model);
492 sqlite3_finalize(st);
497 float *min_aperture,
float *max_aperture)
499 if(!db || !db->
sql)
return -1;
500 if(min_focal) *min_focal = 0.f;
501 if(max_focal) *max_focal = 0.f;
502 if(min_aperture) *min_aperture = 0.f;
503 if(max_aperture) *max_aperture = 0.f;
505 sqlite3_stmt *st = NULL;
506 if(sqlite3_prepare_v2(db->
sql,
507 "SELECT min_focal, max_focal, min_aperture, max_aperture"
508 " FROM lens WHERE id = ?1", -1, &st, NULL) != SQLITE_OK)
510 _db_err(db,
"prepare lens range");
513 sqlite3_bind_int64(st, 1, lens_id);
515 if(sqlite3_step(st) == SQLITE_ROW)
518 if(min_focal) *min_focal = (float)sqlite3_column_double(st, 0);
519 if(max_focal) *max_focal = (float)sqlite3_column_double(st, 1);
520 if(min_aperture) *min_aperture = (float)sqlite3_column_double(st, 2);
521 if(max_aperture) *max_aperture = (float)sqlite3_column_double(st, 3);
523 sqlite3_finalize(st);
529 if(!db || !db->
sql)
return -1;
530 if(out && out_size) out[0] =
'\0';
532 sqlite3_stmt *st = NULL;
533 if(sqlite3_prepare_v2(db->
sql,
534 "SELECT m.name FROM lens_mount lm JOIN mount m ON m.id = lm.mount_id"
535 " WHERE lm.lens_id = ?1 ORDER BY m.name", -1, &st, NULL) != SQLITE_OK)
537 _db_err(db,
"prepare lens mounts");
540 sqlite3_bind_int64(st, 1, lens_id);
544 while(sqlite3_step(st) == SQLITE_ROW)
546 const char *name = (
const char *)sqlite3_column_text(st, 0);
549 if(!out || out_size == 0)
continue;
553 const size_t need = strlen(name) + (used ? 2 : 0);
554 if(used + need >= out_size)
continue;
555 if(used) { memcpy(out + used,
", ", 2); used += 2; }
556 memcpy(out + used, name, strlen(name));
557 used += strlen(name);
560 sqlite3_finalize(st);
566 if(!db || !db->
sql)
return -1;
568 sqlite3_stmt *st = NULL;
569 if(sqlite3_prepare_v2(db->
sql,
"SELECT id FROM camera ORDER BY id", -1, &st, NULL)
572 _db_err(db,
"prepare camera list");
576 while(sqlite3_step(st) == SQLITE_ROW)
578 if(out_ids && n < max) out_ids[n] = sqlite3_column_int64(st, 0);
581 sqlite3_finalize(st);
582 return (out_ids && n > max) ? max : n;
586 char *model,
size_t model_size,
char *variant,
size_t variant_size)
588 if(!db || !db->
sql)
return -1;
589 if(maker && maker_size) maker[0] =
'\0';
590 if(model && model_size) model[0] =
'\0';
591 if(variant && variant_size) variant[0] =
'\0';
593 sqlite3_stmt *st = NULL;
594 if(sqlite3_prepare_v2(db->
sql,
"SELECT maker, model, variant FROM camera WHERE id = ?1",
595 -1, &st, NULL) != SQLITE_OK)
597 _db_err(db,
"prepare camera name");
600 sqlite3_bind_int64(st, 1, camera_id);
602 if(sqlite3_step(st) == SQLITE_ROW)
605 const char *a = (
const char *)sqlite3_column_text(st, 0);
606 const char *b = (
const char *)sqlite3_column_text(st, 1);
607 const char *c = (
const char *)sqlite3_column_text(st, 2);
608 if(maker && maker_size && a) snprintf(maker, maker_size,
"%s", a);
609 if(model && model_size && b) snprintf(model, model_size,
"%s", b);
610 if(variant && variant_size && c) snprintf(variant, variant_size,
"%s", c);
612 sqlite3_finalize(st);
618 if(!db || !db->
sql || !out)
return -1;
619 memset(out, 0,
sizeof(*out));
621 sqlite3_stmt *st = NULL;
622 if(sqlite3_prepare_v2(db->
sql,
"SELECT crop_factor, mount_id FROM camera WHERE id = ?1",
623 -1, &st, NULL) != SQLITE_OK)
625 _db_err(db,
"prepare camera by id");
628 sqlite3_bind_int64(st, 1, camera_id);
630 if(sqlite3_step(st) == SQLITE_ROW)
633 out->
crop_factor = (float)sqlite3_column_double(st, 0);
634 out->
mount_id = sqlite3_column_int64(st, 1);
637 sqlite3_finalize(st);
643 if(!db || !db->
sql || !out || out_size == 0)
return -1;
646 sqlite3_stmt *st = NULL;
647 if(sqlite3_prepare_v2(db->
sql,
"SELECT name FROM mount WHERE id = ?1", -1, &st, NULL)
650 _db_err(db,
"prepare mount name");
653 sqlite3_bind_int64(st, 1, mount_id);
655 if(sqlite3_step(st) == SQLITE_ROW)
657 const char *n = (
const char *)sqlite3_column_text(st, 0);
660 snprintf(out, out_size,
"%s", n);
664 sqlite3_finalize(st);
670 if(!db || !db->
sql)
return -1;
672 sqlite3_stmt *st = NULL;
673 if(sqlite3_prepare_v2(db->
sql,
674 "SELECT lens_id FROM lens_mount WHERE mount_id = ?1 ORDER BY lens_id",
675 -1, &st, NULL) != SQLITE_OK)
677 _db_err(db,
"prepare lenses for mount");
680 sqlite3_bind_int64(st, 1, mount_id);
682 while(sqlite3_step(st) == SQLITE_ROW)
684 if(out_ids && n < max) out_ids[n] = sqlite3_column_int64(st, 0);
687 sqlite3_finalize(st);
688 return (out_ids && n > max) ? max : n;
693 if(!db || !db->
sql || !key || !out || out_size == 0)
return -1;
696 sqlite3_stmt *st = NULL;
697 if(sqlite3_prepare_v2(db->
sql,
"SELECT value FROM meta WHERE key = ?1", -1, &st, NULL) != SQLITE_OK)
702 sqlite3_bind_text(st, 1, key, -1, SQLITE_STATIC);
705 if(sqlite3_step(st) == SQLITE_ROW)
707 const char *v = (
const char *)sqlite3_column_text(st, 0);
710 snprintf(out, out_size,
"%s", v);
711 n = (int)strlen(out);
714 sqlite3_finalize(st);
761 const char *p = norm ? norm :
"";
764 while(*p ==
' ') p++;
767 char *w = out_tokens + (size_t)n * stride;
770 while(*p && *p !=
' ' && len < stride - 1)
772 const int is_digit = (*p >=
'0' && *p <=
'9');
773 if(prev_digit >= 0 && is_digit != prev_digit)
break;
775 prev_digit = is_digit;
785 unsigned hash = 2166136261u;
786 for(
const char *c = token; *c; c++)
788 hash ^= (
unsigned char)*c;
798 const size_t need = 2 + (size_t)n * 5;
799 if(out_size < need)
return 0;
801 out[0] = (
unsigned char)(n & 0xFF);
802 out[1] = (
unsigned char)((n >> 8) & 0xFF);
803 for(
int i = 0; i < n; i++)
806 unsigned char *p = out + 2 + (size_t)i * 4;
807 p[0] = (
unsigned char)(h & 0xFF);
808 p[1] = (
unsigned char)((h >> 8) & 0xFF);
809 p[2] = (
unsigned char)((h >> 16) & 0xFF);
810 p[3] = (
unsigned char)((h >> 24) & 0xFF);
811 out[2 + (size_t)n * 4 + i] = (
unsigned char)strlen(toks[i]);
821 if(!blob || bytes < 2)
return 0;
823 int n = blob[0] | (blob[1] << 8);
825 if(bytes < 2 + n * 5)
return 0;
827 for(
int i = 0; i < n; i++)
829 const unsigned char *p = blob + 2 + (size_t)i * 4;
830 const unsigned h = (unsigned)p[0] | ((
unsigned)p[1] << 8)
831 | ((unsigned)p[2] << 16) | ((
unsigned)p[3] << 24);
833 out->
len[i] = blob[2 + (size_t)n * 4 + i];
834 out->
bloom |= 1ULL << (h & 63u);
844 for(
int i = 0; i < out->
n; i++)
848 out->
len[i] = (
unsigned char)strlen(out->
t[i]);
849 out->
bloom |= 1ULL << (hash & 63u);
867 if(pat->
n == 0 || cand->
n == 0)
return 0.f;
872 for(
int i = 0; i < pat->
n; i++)
874 const unsigned hi = pat->
h[i];
875 const int li = pat->
len[i];
878 for(
int j = 0; j < cand->
n; j++)
880 if(used[j])
continue;
887 if(hi == cand->
h[j] && li == cand->
len[j])
895 if(best_j >= 0 && best > 0.f)
902 const float forward = got / (float)pat->
n;
904 for(
int j = 0; j < cand->
n; j++)
if(!used[j]) unmatched++;
905 const float verbosity = (float)unmatched / (
float)cand->
n;
907 float score = 100.f * (forward - 0.15f * verbosity * forward);
908 if(score < 0.f) score = 0.f;
943 static const char *
const not_a_lens[]
944 = {
"adapter",
"reducer",
"booster",
"extender",
"converter",
"ext.",
"ext ", NULL };
945 for(
int i = 0; not_a_lens[i]; i++)
948 for(
const char *h = name; *h; h++)
950 const char *a = h, *b = not_a_lens[i];
951 while(*a && *b && ((*a | 32) == (*b | 32))) { a++; b++; }
956 for(
const char *c = name; *c; c++)
958 if(*c <
'0' || *c >
'9')
continue;
970 if(c != name && c[-1] !=
' ')
continue;
973 const float a = strtof(c, &end);
974 if(!end || end == c)
continue;
981 const float t = strtof(p + 1, &end2);
982 if(end2 && end2 != p + 1) { b = t; p = end2; }
984 while(*p ==
' ') p++;
985 if((p[0] ==
'm' || p[0] ==
'M') && (p[1] ==
'm' || p[1] ==
'M') && a > 0.f && b >= a)
1001 if(a == 0.f || b == 0.f)
return 0;
1002 const float r = a / b;
1003 return (r <= 0.99f || r >= 1.01f) ? -1 : +1;
1030 if(cam <= 0.01f || calib <= 0.f)
return 0.f;
1031 if(cam < calib * 0.96f)
return -1.f;
1033 if(cam >= calib * 1.41f)
return 2.f;
1034 if(cam >= calib * 1.31f)
return 4.f;
1035 if(cam >= calib * 1.21f)
return 6.f;
1036 if(cam >= calib * 1.11f)
return 8.f;
1037 if(cam >= calib * 1.01f)
return 10.f;
1038 if(cam >= calib)
return 5.f;
1045 if(!db || !db->
sql || !model || !out || max <= 0)
return -1;
1047 char nmodel[512], nmaker[512];
1054 if(pat.
n == 0)
return 0;
1078 for(
int i = 0; i < pat.
n; i++)
1080 if(i) in_list[w++] =
',';
1081 in_list[w++] =
'\'';
1082 for(
const char *c = pat.
t[i]; *c; c++)
1083 if(*c !=
'\'') in_list[w++] = *c;
1084 in_list[w++] =
'\'';
1092 char sqlbuf[
sizeof(in_list) + 256];
1093 snprintf(sqlbuf,
sizeof(sqlbuf),
1094 "SELECT token FROM token_df WHERE kind = 'model' AND token IN %s"
1095 " ORDER BY df ASC LIMIT 1", in_list);
1096 sqlite3_stmt *rq = NULL;
1097 if(sqlite3_prepare_v2(db->
sql, sqlbuf, -1, &rq, NULL) == SQLITE_OK)
1099 if(sqlite3_step(rq) == SQLITE_ROW)
1101 const char *t = (
const char *)sqlite3_column_text(rq, 0);
1102 if(t) snprintf(rarest,
sizeof(rarest),
"%s", t);
1104 sqlite3_finalize(rq);
1108 sqlite3_stmt *st = NULL;
1110 const char *mount_clause =
1112 ?
" AND EXISTS (SELECT 1 FROM lens_mount lm WHERE lm.lens_id = n.lens_id AND ("
1113 " lm.mount_id = ?1 OR EXISTS (SELECT 1 FROM mount_compat mc"
1114 " WHERE mc.mount_id = ?1 AND mc.compat_id = lm.mount_id)))"
1117 snprintf(sqlbuf,
sizeof(sqlbuf),
1118 "SELECT n.lens_id, n.tokens, n.kind FROM lens_name n"
1119 " WHERE n.lens_id IN (SELECT lens_id FROM lens_token"
1120 " WHERE kind = 'model' AND token = ?2)%s", mount_clause);
1122 snprintf(sqlbuf,
sizeof(sqlbuf),
1123 "SELECT n.lens_id, n.tokens, n.kind FROM lens_name n WHERE 1%s", mount_clause);
1125 if(sqlite3_prepare_v2(db->
sql, sqlbuf, -1, &st, NULL) != SQLITE_OK)
1130 if(rarest[0]) sqlite3_bind_text(st, 2, rarest, -1, SQLITE_STATIC);
1131 if(mount_id > 0) sqlite3_bind_int64(st, 1, mount_id);
1135 enum { SLOTS = 4096 };
1136 long long *ids = (
long long *)calloc(SLOTS,
sizeof(
long long));
1137 float *best = (
float *)calloc(SLOTS,
sizeof(
float));
1138 float *maker_bonus = (
float *)calloc(SLOTS,
sizeof(
float));
1139 if(!ids || !best || !maker_bonus)
1141 free(ids); free(best); free(maker_bonus);
1142 sqlite3_finalize(st);
1146 while(sqlite3_step(st) == SQLITE_ROW)
1148 const long long id = sqlite3_column_int64(st, 0);
1149 const unsigned char *blob = (
const unsigned char *)sqlite3_column_blob(st, 1);
1150 const int blob_bytes = sqlite3_column_bytes(st, 1);
1151 const char *kind = (
const char *)sqlite3_column_text(st, 2);
1152 if(!blob || !kind)
continue;
1161 if(!(cand.
bloom & ((kind[0] ==
'm' && kind[1] ==
'o') ? pat.
bloom : pat_maker.
bloom)))
1164 size_t slot = (size_t)
id % SLOTS;
1165 while(ids[slot] && ids[slot] !=
id) slot = (slot + 1) % SLOTS;
1168 if(kind[0] ==
'm' && kind[1] ==
'o')
1171 if(s > best[slot]) best[slot] = s;
1173 else if(pat_maker.
n)
1179 if(s > maker_bonus[slot]) maker_bonus[slot] = s;
1182 sqlite3_finalize(st);
1203 const float EXACT_TIE = 1e-4f;
1205 float q_minf = 0.f, q_maxf = 0.f;
1211 sqlite3_stmt *cq = NULL;
1212 if(crop > 0.01f || q_minf > 0.f)
1213 sqlite3_prepare_v2(db->
sql,
1214 "SELECT crop_factor, min_focal, max_focal FROM lens WHERE id = ?1",
1218 for(
size_t slot = 0; slot < SLOTS; slot++)
1220 if(!ids[slot] || best[slot] <= 0.f)
continue;
1221 float score = best[slot] + 0.10f * maker_bonus[slot];
1226 sqlite3_bind_int64(cq, 1, ids[slot]);
1227 if(sqlite3_step(cq) != SQLITE_ROW)
continue;
1228 const float calib = (float)sqlite3_column_double(cq, 0);
1229 const float c_minf = (float)sqlite3_column_double(cq, 1);
1230 const float c_maxf = (float)sqlite3_column_double(cq, 2);
1233 if(w < 0.f)
continue;
1235 score += w * EXACT_TIE;
1241 if(fmin < 0 || fmax < 0)
continue;
1242 if(fmin > 0) score += 10.f * EXACT_TIE;
1243 if(fmax > 0) score += 10.f * EXACT_TIE;
1248 while(at > 0 && out[at - 1].score < score)
1250 if(at < max) out[at] = out[at - 1];
1256 out[at].
score = score;
1261 if(cq) sqlite3_finalize(cq);
int ls_db_lenses_for_mount(ls_db_t *db, long long mount_id, long long *out_ids, int max)
The lenses made for one mount.
int ls_db_find_lens(ls_db_t *db, const char *maker, const char *model, float crop, ls_lens_t *out)
Find a lens by maker and model, and fill out with its coefficients.
int ls_db_match_lens(ls_db_t *db, const char *maker, const char *model, long long mount_id, float crop, ls_db_match_t *out, int max)
Find the lenses a free-text name most likely refers to.
int ls_db_meta(ls_db_t *db, const char *key, char *out, size_t out_size)
A meta value by key (built_utc, source, lensfun_db_version, ...).
void ls_db_close(ls_db_t *db)
Release a handle. Safe on NULL.
int ls_db_list_cameras(ls_db_t *db, long long *out_ids, int max)
Enumerate camera ids, for a GUI's camera picker.
int ls_db_list_lenses(ls_db_t *db, long long *out_ids, int max)
Enumerate lens ids, oldest-inserted first, for tests and for a GUI's lens picker.
static float _score_tokens(const ls_tokens_t *pat, const ls_tokens_t *cand)
How well pat's tokens are covered by cand's, 0..100.
int ls_db_tokenize(const char *norm, char *out_tokens, int max, int stride)
Split a normalised name on spaces, and split letter/digit runs apart.
int ls_db_lens_fits_mount(ls_db_t *db, long long lens_id, long long mount_id)
Does a lens fit a camera's mount, upstream's compatibility table included?
int ls_db_lens_by_id(ls_db_t *db, long long lens_id, ls_lens_t *out)
Load a lens by its database id, for a caller that already resolved one.
int ls_db_mount_name(ls_db_t *db, long long mount_id, char *out, size_t out_size)
A mount's name.
static int _digest_load(const unsigned char *blob, int bytes, ls_tokens_t *out)
Read a digest back into the arrays _score_tokens() compares.
static float _crop_score(const float cam, const float calib)
Upstream's crop-factor rule, as a bonus ADDED to a candidate's score.
int ls_db_lens_mounts(ls_db_t *db, long long lens_id, char *out, size_t out_size)
The mounts a lens is made for, joined with ", ".
int ls_db_lens_range(ls_db_t *db, long long lens_id, float *min_focal, float *max_focal, float *min_aperture, float *max_aperture)
The lens's focal and aperture range, for a picker that lists it.
static void _tokenize(const char *norm, ls_tokens_t *out)
int ls_db_schema_version(const ls_db_t *db)
Schema version of the open file, or -1. Bumped when the layout changes.
int ls_db_lens_name(ls_db_t *db, long long lens_id, char *maker, size_t maker_size, char *model, size_t model_size)
The lens's maker/model, as stored.
int ls_db_camera_by_id(ls_db_t *db, long long camera_id, ls_camera_t *out)
Load a camera by its database id, for a caller that already resolved one.
static int _compare_num(const float a, const float b)
Upstream's _lf_compare_num(): a numeric field as a filter, not a score.
size_t ls_db_token_digest(const char *norm, unsigned char *out, size_t out_size)
Pack a normalised name's tokens into the digest stored in lens_name.tokens.
unsigned ls_db_token_hash(const char *token)
FNV-1a of a token, the hash the stored digest and the matcher both use.
ls_db_t * ls_db_open(const char *path)
Open a database for reading.
int ls_db_find_camera(ls_db_t *db, const char *maker, const char *model, ls_camera_t *out)
Find a camera by maker and model.
static int _fill_calibrations(ls_db_t *db, long long lens_id, ls_lens_t *out)
#define LS_DB_SCHEMA_VERSION
static void _db_err(ls_db_t *db, const char *what)
int ls_db_camera_name(ls_db_t *db, long long camera_id, char *maker, size_t maker_size, char *model, size_t model_size, char *variant, size_t variant_size)
A camera's maker, model and variant, as stored.
size_t ls_db_normalize(const char *in, char *out, size_t out_size)
Case-fold ASCII, drop punctuation, collapse whitespace.
static long long _find_lens_id(ls_db_t *db, const char *maker, const char *model, float crop)
The lens id whose names match, preferring the calibration crop nearest crop.
static void _parse_focal_range(const char *name, float *minf, float *maxf)
Pull the focal range out of a lens NAME, the way upstream does.
const char * ls_db_error(const ls_db_t *db)
The last error on db, as a string owned by db, or NULL.
static char * _db_build_uri(const char *path)
Build the URI this library insists on, whatever the caller passed.
A read-only database, and an API with nothing behind it.
ls_calib_vig_t vig[LS_MAX_CALIB]
ls_calib_real_focal_t real_focal[LS_MAX_CALIB]
ls_calib_tca_t tca[LS_MAX_CALIB]
ls_calib_dist_t dist[LS_MAX_CALIB]
A tokenised name, with everything the comparison needs precomputed.
unsigned h[LS_MAX_TOKENS]
unsigned char len[LS_MAX_TOKENS]
char t[LS_MAX_TOKENS][LS_TOKEN_LEN]