summaryrefslogtreecommitdiff
path: root/tests/harness/stitchdump.cxx
blob: cd015e734187e03608fab0c92e3c3d68b3f76fae (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// Golden dump: Stitch::resample pipeline through the original C++ Panorama +
// ScanImage (no FLTK GUI; PPM input wrapped in Fl_RGB_Image).
// Usage: stitchdump <img.ppm> <projtype> <center> <pitch> <roll> <scale>
//                    <k0> <k1> <x0> <w> <h> <from> <to> <bicubic>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#include <algorithm>

#include <FL/Fl.H>
#include <FL/Fl_RGB_Image.H>

#include "Panorama.H"
#include "ScanImage.H"

#define MAX_VALUE 65025

// minimal P6 PPM reader
static unsigned char *read_ppm(const char *path, int *w, int *h) {
    FILE *f = fopen(path, "rb");
    if (!f) return NULL;
    int c;
    if (fgetc(f) != 'P' || fgetc(f) != '6' || (c = fgetc(f), !isspace(c))) {
        fclose(f); return NULL;
    }
    int skip = 0;
    while (!skip) {
        c = fgetc(f);
        if (c == '#') { while ((c = fgetc(f)) != '\n' && c != EOF); continue; }
        if (c == ' ' || c == '\n' || c == '\t' || c == '\r') continue;
        skip = 1;
        ungetc(c, f);
    }
    (void)c;
    if (fscanf(f, "%d %d %*d", w, h) != 2) { fclose(f); return NULL; }
    fgetc(f); // single whitespace
    unsigned char *buf = (unsigned char*)malloc((size_t)(*w) * (*h) * 3);
    if (fread(buf, 1, (size_t)(*w) * (*h) * 3, f) != (size_t)(*w) * (*h) * 3) {
        free(buf); fclose(f); return NULL;
    }
    fclose(f);
    return buf;
}

int main(int argc, char **argv) {
    if (argc < 15) {
        fprintf(stderr, "usage: stitchdump <img.ppm> <projtype> <center> <pitch> "
                "<roll> <scale> <k0> <k1> <x0> <w> <h> <from> <to> <bicubic>\n");
        return 1;
    }
    int iw = 0, ih = 0;
    unsigned char *px = read_ppm(argv[1], &iw, &ih);
    if (!px) { fprintf(stderr, "cannot read %s\n", argv[1]); return 1; }

    Fl_RGB_Image img(px, iw, ih, 3);

    Panorama pan;
    pan.set_projection((ProjectionLSQ::Projection_t) atoi(argv[2]));
    pan.set_center_angle(atof(argv[3]));
    pan.set_nick_angle(atof(argv[4]));
    pan.set_tilt_angle(atof(argv[5]));
    pan.set_scale(atof(argv[6]));
    pan.parms.k0 = atof(argv[7]);
    pan.parms.k1 = atof(argv[8]);
    pan.parms.x0 = atof(argv[9]);

    int w = atoi(argv[10]), h = atoi(argv[11]);
    double view_start = atof(argv[12]) * M_PI / 180.0;
    double view_end = atof(argv[13]) * M_PI / 180.0;
    ScanImage::mode_t mode = atoi(argv[14]) ? ScanImage::BICUBIC : ScanImage::NEAREST;

    double step_view = (view_end - view_start) / w;
    int y_off = h / 2;
    double radius = (double) w / (view_end - view_start);

    for (int y = 0; y < h; y++) {
        double a_nick = atan((double)(y_off - y) / radius);
        for (int x = 0; x < w; x++) {
            double a_view = view_start + x * step_view;
            int hit = 0, r = 0, g = 0, b = 0;
            double px2, py2;
            if (pan.get_coordinates(a_view, a_nick, &px2, &py2) == 0) {
                int rr, gg, bb;
                if (ScanImage::get_pixel(&img, mode,
                        px2 + ((double) img.w()) / 2.0,
                        py2 + ((double) img.h()) / 2.0,
                        &rr, &gg, &bb) == 0) {
                    hit = 1;
                    r = std::max(std::min(rr, MAX_VALUE), 0);
                    g = std::max(std::min(gg, MAX_VALUE), 0);
                    b = std::max(std::min(bb, MAX_VALUE), 0);
                }
            }
            printf("%d %d %d %d %d %d\n", x, y, hit, r, g, b);
        }
    }

    free(px);
    return 0;
}