File size: 4,679 Bytes
9913017 | 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 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | // flow_io.cpp
//
// read and write our simple .flo flow file format
// ".flo" file format used for optical flow evaluation
//
// Stores 2-band float image for horizontal (u) and vertical (v) flow components.
// Floats are stored in little-endian order.
// A flow value is considered "unknown" if either |u| or |v| is greater than 1e9.
//
// bytes contents
//
// 0-3 tag: "PIEH" in ASCII, which in little endian happens to be the float 202021.25
// (just a sanity check that floats are represented correctly)
// 4-7 width as an integer
// 8-11 height as an integer
// 12-end data (width*height*2*4 bytes total)
// the float values for u and v, interleaved, in row order, i.e.,
// u[row0,col0], v[row0,col0], u[row0,col1], v[row0,col1], ...
//
// first four bytes, should be the same in little endian
#define TAG_FLOAT 202021.25 // check for this when READING the file
#define TAG_STRING "PIEH" // use this when WRITING the file
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "imageLib.h"
#include "flowIO.h"
// return whether flow vector is unknown
bool unknown_flow(float u, float v) {
return (fabs(u) > UNKNOWN_FLOW_THRESH)
|| (fabs(v) > UNKNOWN_FLOW_THRESH)
|| isnan(u) || isnan(v);
}
bool unknown_flow(float *f) {
return unknown_flow(f[0], f[1]);
}
// read a flow file into 2-band image
void ReadFlowFile(CFloatImage& img, const char* filename)
{
if (filename == NULL)
throw CError("ReadFlowFile: empty filename");
char *dot = strrchr(filename, '.');
if (strcmp(dot, ".flo") != 0)
throw CError("ReadFlowFile (%s): extension .flo expected", filename);
FILE *stream = fopen(filename, "rb");
if (stream == 0)
throw CError("ReadFlowFile: could not open %s", filename);
int width, height;
float tag;
if ((int)fread(&tag, sizeof(float), 1, stream) != 1 ||
(int)fread(&width, sizeof(int), 1, stream) != 1 ||
(int)fread(&height, sizeof(int), 1, stream) != 1)
throw CError("ReadFlowFile: problem reading file %s", filename);
if (tag != TAG_FLOAT) // simple test for correct endian-ness
throw CError("ReadFlowFile(%s): wrong tag (possibly due to big-endian machine?)", filename);
// another sanity check to see that integers were read correctly (99999 should do the trick...)
if (width < 1 || width > 99999)
throw CError("ReadFlowFile(%s): illegal width %d", filename, width);
if (height < 1 || height > 99999)
throw CError("ReadFlowFile(%s): illegal height %d", filename, height);
int nBands = 2;
CShape sh(width, height, nBands);
img.ReAllocate(sh);
//printf("reading %d x %d x 2 = %d floats\n", width, height, width*height*2);
int n = nBands * width;
for (int y = 0; y < height; y++) {
float* ptr = &img.Pixel(0, y, 0);
if ((int)fread(ptr, sizeof(float), n, stream) != n)
throw CError("ReadFlowFile(%s): file is too short", filename);
}
if (fgetc(stream) != EOF)
throw CError("ReadFlowFile(%s): file is too long", filename);
fclose(stream);
}
// write a 2-band image into flow file
void WriteFlowFile(CFloatImage img, const char* filename)
{
if (filename == NULL)
throw CError("WriteFlowFile: empty filename");
char *dot = strrchr(filename, '.');
if (dot == NULL)
throw CError("WriteFlowFile: extension required in filename '%s'", filename);
if (strcmp(dot, ".flo") != 0)
throw CError("WriteFlowFile: filename '%s' should have extension '.flo'", filename);
CShape sh = img.Shape();
int width = sh.width, height = sh.height, nBands = sh.nBands;
if (nBands != 2)
throw CError("WriteFlowFile(%s): image must have 2 bands", filename);
FILE *stream = fopen(filename, "wb");
if (stream == 0)
throw CError("WriteFlowFile: could not open %s", filename);
// write the header
fprintf(stream, TAG_STRING);
if ((int)fwrite(&width, sizeof(int), 1, stream) != 1 ||
(int)fwrite(&height, sizeof(int), 1, stream) != 1)
throw CError("WriteFlowFile(%s): problem writing header", filename);
// write the rows
int n = nBands * width;
for (int y = 0; y < height; y++) {
float* ptr = &img.Pixel(0, y, 0);
if ((int)fwrite(ptr, sizeof(float), n, stream) != n)
throw CError("WriteFlowFile(%s): problem writing data", filename);
}
fclose(stream);
}
/*
int main() {
try {
CShape sh(5, 1, 2);
CFloatImage img(sh);
img.ClearPixels();
img.Pixel(0, 0, 0) = -5.0f;
char *filename = "test.flo";
WriteFlowFile(img, filename);
ReadFlowFile(img, filename);
}
catch (CError &err) {
fprintf(stderr, err.message);
fprintf(stderr, "\n");
exit(1);
}
return 0;
}
*/
|