static TIFF *tifopenr(const char *tif, // TIFF file name bool *c, // return is complex? int *l, // return log2 tile size int *n, // return log2 height int *m, // return log2 width int *p) // return pixel size { TIFF *T; if ((T = TIFFOpen(tif, "r"))) { uint32 W = 0; uint32 L = 0; uint32 S = 0; uint16 P = 0; uint16 B = 0; uint16 G = 0; uint16 F = 0; TIFFGetField(T, TIFFTAG_IMAGEWIDTH, &W); TIFFGetField(T, TIFFTAG_IMAGELENGTH, &L); TIFFGetField(T, TIFFTAG_TILEWIDTH, &S); TIFFGetField(T, TIFFTAG_SAMPLESPERPIXEL, &P); TIFFGetField(T, TIFFTAG_BITSPERSAMPLE, &B); TIFFGetField(T, TIFFTAG_PLANARCONFIG, &G); TIFFGetField(T, TIFFTAG_SAMPLEFORMAT, &F); if (G == PLANARCONFIG_CONTIG) { if (F == SAMPLEFORMAT_IEEEFP) { if (B == 32) { if (ispow2(W) && ispow2(L)) { *c = (P % 2) ? false : true; *p = (P % 2) ? P : P / 2; *l = log2i(S); *n = log2i(L); *m = log2i(W); return T; } else apperr("TIFF image size must be power of 2"); } else apperr("TIFF must have 32 bits per sample"); } else apperr("TIFF must have floating point sample format"); } else apperr("TIFF must have contiguous planar configuration"); TIFFClose(T); } return 0; }
static int addfile(scm **V, int C, const char *name) { static int n = 0; static int c = 0; scm *s; if ((s = scm_ifile(name))) { if ((n == 0 && c == 0) || (n == scm_get_n(s) && c == scm_get_c(s))) { n = scm_get_n(s); c = scm_get_c(s); if ((scm_scan_catalog(s))) { V[C] = s; return ++C; } } else apperr("SCM TIFF '%s' has size %d chan %d." " Expected size %d chan %d.", name, scm_get_n(s), scm_get_c(s), n, c); scm_close(s); } return C; }
static bool proc(const char *dst, int l, int n, int m, int p, int op) { bool ok = false; img *s; int k; if ((n && m && p) || imgargs(dst, &n, &m, &p)) { if ((s = imgopen(dst, l, n, m, p))) { for (k = 0; k < s->p; k++) { float v = 0.0f; switch (op) { case 's': v = op_sum(s, k); break; case 'x': v = op_cmin(s, k); break; case 'X': v = op_cmax(s, k); break; case '0': v = op_rmin(s, k); break; case '1': v = op_rmax(s, k); break; } printf("%e\n", v); } imgclose(s); ok = true; } } else apperr("Failed to guess image parameters"); return ok; }
int isapad(void) { static int res = -1; static status_$t st; if (res == -1) { int strm; if (isatty(0)) strm = 0; if (isatty(1)) strm = 1; if (isatty(2)) strm = 2; else { res = 0; st.all = status_$ok; return(res); } res = stream_$isavt(&strm, &st); res = res ? 1 : 0; } else { if (st.all != status_$ok) stderror(ERR_SYSTEM, "stream_$isavt", apperr(&st)); } return(res); }
static int llib(Char *s) { short len = Strlen(s); status_$t st; char *t; loader_$inlib(t = short2str(s), len, &st); if (st.all != status_$ok) stderror(ERR_SYSTEM, t, apperr(&st)); }
bool scm_link_list(scm *s, long long c, long long p) { if (p) { ifd i; if (scm_read_ifd(s, &i, p)) { i.next = (uint64_t) c; if (scm_write_ifd(s, &i, p) > 0) { return true; } else apperr("%s: Failed to write previous IFD", s->name); } else apperr("%s: Failed to read previous IFD", s->name); } else { header h; hfd d; if (scm_read_header(s, &h)) { if (scm_read_hfd(s, &d, h.first_ifd)) { d.next = (uint64_t) c; if (scm_write_hfd(s, &d, h.first_ifd) > 0) { return true; } else apperr("%s: Failed to write preamble", s->name); } else apperr("%s: Failed to read preamble", s->name); } else apperr("%s: Failed to read preamble", s->name); } return false; }
/*ARGSUSED*/ void dorootnode(Char **v, struct command *c) { name_$dir_type_t dirtype = name_$node_dir_type; uid_$t uid; status_$t st; char *name; short namelen; setname(short2str(*v++)); name = short2str(*v); namelen = strlen(name); name_$resolve(name, &namelen, &uid, &st); if (st.all != status_$ok) stderror(ERR_SYSTEM, name, apperr(&st)); namelen = 0; name_$set_diru(&uid, "", &namelen, &dirtype, &st); if (st.all != status_$ok) stderror(ERR_SYSTEM, name, apperr(&st)); dohash(NULL, NULL); }
img *img_alloc(int w, int h, int c, int b, int g) { size_t n = (size_t) w * (size_t) h * (size_t) c * (size_t) b / 8; img *p = NULL; if ((p = (img *) calloc(1, sizeof (img)))) { if ((p->p = malloc(n))) { p->project = img_default; p->n = n; p->w = w; p->h = h; p->c = c; p->b = b; p->g = g; p->minimum_latitude = -0.5 * M_PI; p->maximum_latitude = 0.5 * M_PI; p->westernmost_longitude = 0.0 * M_PI; p->easternmost_longitude = 2.0 * M_PI; p->norm0 = 0.f; p->norm1 = 1.f; p->scaling_factor = 1.f; p->offset = 0.f; return p; } else apperr("Failed to allocate image buffer"); } else apperr("Failed to allocate image structure"); img_close(p); return NULL; }
bool scm_read_ifd(scm *s, ifd *d, long long o) { assert(s); assert(d); if (o && scm_read(s, d, sizeof (ifd), o)) { if (is_ifd(d)) { return true; } else apperr("%s is not an SCM TIFF", s->name); } return false; }
bool scm_read_header(scm *s, header *h) { assert(s); assert(h); if (scm_read(s, h, sizeof (header), 0)) { if (is_header(h)) { return true; } else apperr("%s is not an SCM TIFF", s->name); } return false; }
static bool imgtotif(bool c, // destination is complex? int e, // source is extended? int l, // source log2 tile size int n, // source log2 height int m, // source log2 width int p, // source pixel size const char *bin, // source image cache file name const char *tif) // destination TIFF image file name { img *d; TIFF *T; void *buf; int r = 0; if ((n && m && p) || imgargs(bin, &n, &m, &p)) { if ((d = imgopen(bin, l, n, m, p))) { if ((T = tifopenw(tif, c, n - e, m, p))) { if ((buf = malloc(TIFFScanlineSize(T)))) { for (r = 0; r < 1 << (n - e); r++) { if (c) imgtolinez(r, d, (float *) buf); else imgtoliner(r, d, (float *) buf); if (TIFFWriteScanline(T, buf, r, 0) == -1) break; } free(buf); } TIFFClose(T); } imgclose(d); } } else apperr("Failed to guess image parameters", bin); return (r == 1 << (n - e)); }
bool scm_init_ifd(scm *s, ifd *d) { if ((size_t) s->c * tifsizeof(scm_type(s)) <= sizeof (uint64_t)) { uint16_t f = (uint16_t) scm_form(s); uint16_t b = (uint16_t) s->b; uint64_t c = (uint64_t) s->c; scm_field(&d->image_width, 0x0100, 3, 1, (uint64_t) s->n + 2); scm_field(&d->image_length, 0x0101, 3, 1, (uint64_t) s->n + 2); scm_field(&d->samples_per_pixel, 0x0115, 3, 1, (uint64_t) s->c); scm_field(&d->rows_per_strip, 0x0116, 3, 1, (uint64_t) s->r); scm_field(&d->interpretation, 0x0106, 3, 1, scm_pint(s)); scm_field(&d->predictor, 0x013D, 3, 1, scm_hdif(s)); scm_field(&d->compression, 0x0103, 3, 1, 8); scm_field(&d->orientation, 0x0112, 3, 1, 2); scm_field(&d->configuration, 0x011C, 3, 1, 1); scm_field(&d->bits_per_sample, 0x0102, 3, c, 0); scm_field(&d->sample_format, 0x0153, 3, c, 0); scm_field(&d->strip_offsets, 0x0111, 0, 0, 0); scm_field(&d->strip_byte_counts, 0x0117, 0, 0, 0); scm_field(&d->page_number, 0x0129, 0, 0, 0); for (int k = 0; k < 4; ++k) { ((uint16_t *) &d->bits_per_sample.offset)[k] = (k < s->c) ? b : 0; ((uint16_t *) &d->sample_format .offset)[k] = (k < s->c) ? f : 0; } d->count = SCM_IFD_COUNT; d->next = 0; return true; } else apperr("%s: Unsupported pixel configuration (> 64 BPP)", s->name); return false; }
bool scm_init_hfd(scm *s, hfd *d) { if ((size_t) s->c * tifsizeof(scm_type(s)) <= sizeof (uint64_t)) { uint16_t f = (uint16_t) scm_form(s); uint16_t b = (uint16_t) s->b; uint64_t c = (uint64_t) s->c; scm_field(&d->image_width, 0x0100, 3, 1, (uint64_t) s->n + 2); scm_field(&d->image_length, 0x0101, 3, 1, (uint64_t) s->n + 2); scm_field(&d->samples_per_pixel, 0x0115, 3, 1, (uint64_t) s->c); scm_field(&d->rows_per_strip, 0x0116, 3, 1, (uint64_t) s->r); scm_field(&d->bits_per_sample, 0x0102, 3, c, 0); scm_field(&d->strip_offsets, 0x0111, 16, 0, 0); scm_field(&d->strip_byte_counts, 0x0117, 4, 0, 0); scm_field(&d->sample_format, 0x0153, 3, c, 0); scm_field(&d->description, 0x010E, 2, 0, 0); scm_field(&d->page_index, SCM_PAGE_INDEX, 0, 0, 0); scm_field(&d->page_offset, SCM_PAGE_OFFSET, 0, 0, 0); scm_field(&d->page_minimum, SCM_PAGE_MINIMUM, 0, 0, 0); scm_field(&d->page_maximum, SCM_PAGE_MAXIMUM, 0, 0, 0); for (int k = 0; k < 4; ++k) { ((uint16_t *) &d->bits_per_sample.offset)[k] = (k < s->c) ? b : 0; ((uint16_t *) &d->sample_format .offset)[k] = (k < s->c) ? f : 0; } d->count = SCM_HFD_COUNT; d->next = 0; return true; } else apperr("%s: Unsupported pixel configuration (> 64 BPP)", s->name); return false; }
int main(int argc, char **argv) { const char *exe = argv[0]; double t0; double t1; const char *p = NULL; const char *m = NULL; const char *o = NULL; const char *t = NULL; int n = 512; int d = 0; int b = -1; int g = -1; int A = 0; int h = 0; int l = 0; int T = 0; double E[4] = { 0.f, 0.f, 0.f , 0.f}; double L[3] = { 0.f, 0.f, 0.f }; double P[3] = { 0.f, 0.f, 0.f }; float N[2] = { 0.f, 0.f }; float R[2] = { 0.f, 1.f }; int c; int r = 0; t0 = now(); setexe(exe); opterr = 0; while ((c = getopt(argc, argv, "Ab:d:E:g:hL:l:m:n:N:o:p:P:Tt:R:w:")) != -1) switch (c) { case 'A': A = 1; break; case 'h': h = 1; break; case 'T': T = 1; break; case 'p': p = optarg; break; case 'm': m = optarg; break; case 'o': o = optarg; break; case 't': t = optarg; break; case 'n': sscanf(optarg, "%d", &n); break; case 'd': sscanf(optarg, "%d", &d); break; case 'b': sscanf(optarg, "%d", &b); break; case 'g': sscanf(optarg, "%d", &g); break; case 'l': sscanf(optarg, "%d", &l); break; case 'E': sscanf(optarg, "%lf,%lf,%lf,%lf", E + 0, E + 1, E + 2, E + 3); break; case 'L': sscanf(optarg, "%lf,%lf,%lf", L + 0, L + 1, L + 2); break; case 'P': sscanf(optarg, "%lf,%lf,%lf", P + 0, P + 1, P + 2); break; case 'N': sscanf(optarg, "%f,%f", N + 0, N + 1); break; case 'R': sscanf(optarg, "%f,%f", R + 0, R + 1); break; case '?': apperr("Bad option -%c", optopt); break; } argc -= optind; argv += optind; if (p == NULL || h) apperr("\nUsage: %s [options] input [...]\n" "\t\t-p process . . Select process\n" "\t\t-o output . . Output file\n" "\t\t-T . . . . . . Emit timing information\n\n" "\t%s -p extrema\n\n" "\t%s -p convert [options]\n" "\t\t-n n . . . . . Page size\n" "\t\t-d d . . . . . Tree depth\n" "\t\t-b b . . . . . Channel depth override\n" "\t\t-g g . . . . . Channel sign override\n" "\t\t-E w,e,s,n . . Equirectangular range\n" "\t\t-L c,d0,d1 . . Longitude blend range\n" "\t\t-P c,d0,d1 . . Latitude blend range\n" "\t\t-N n0,n1 . . . Normalization range\n" "\t\t-A . . . . . . Coverage alpha\n\n" "\t%s -p combine [-m mode]\n" "\t\t-m sum . . . . Combine by sum\n" "\t\t-m max . . . . Combine by maximum\n" "\t\t-m avg . . . . Combine by average\n" "\t\t-m blend . . . Combine by alpha blending\n\n" "\t%s -p mipmap [-m mode]\n\n" "\t\t-m sum . . . . Combine by sum\n" "\t\t-m max . . . . Combine by maximum\n" "\t\t-m avg . . . . Combine by average\n\n" "\t%s -p border\n\n" "\t%s -p finish [options]\n" "\t\t-t text . . . Image description text file\n" "\t\t-l l . . . . . Bounding volume oversample level\n\n" "\t%s -p normal [options]\n" "\t\t-R r0,r1 . . . Radius range\n", exe, exe, exe, exe, exe, exe, exe, exe); else if (strcmp(p, "extrema") == 0) r = extrema(argc, argv); else if (strcmp(p, "convert") == 0) r = convert(argc, argv, o, n, d, b, g, A, N, E, L, P); else if (strcmp(p, "rectify") == 0) r = rectify(argc, argv, o, n, N, E, L, P); else if (strcmp(p, "combine") == 0) r = combine(argc, argv, o, m); else if (strcmp(p, "mipmap") == 0) r = mipmap (argc, argv, o, m, A); else if (strcmp(p, "border") == 0) r = border (argc, argv, o); else if (strcmp(p, "finish") == 0) r = finish (argc, argv, t, l); else if (strcmp(p, "polish") == 0) r = polish (argc, argv); else if (strcmp(p, "normal") == 0) r = normal (argc, argv, o, R); else if (strcmp(p, "sample") == 0) r = sample (argc, argv, R, d); else apperr("Unknown process '%s'", p); t1 = now(); if (T) printhms(t1 - t0); return r; }