1 // -*- mode: c++; c-set-style: "stroustrup"; tab-width: 4; -*-
2 //
3 // CReaderPFM.c
4 //
5 // Copyright (C) 2004 Koji Nakamaru
6 //
7 // This program is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either version 2, or (at your option)
10 // any later version.
11 //
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software Foundation,
19 // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 //
21 
22 #include "common.h"
23 #include "CReaderPFM.h"
24 
25 static const char *_magic[] = {
26 	"PF",
27 	"Pf",
28 	NULL,
29 };
30 
31 // public functions
32 
CReaderPFM()33 CReaderPFM::CReaderPFM()
34 : CReader(),
35   _is_color(true),
36   _is_swapped(false)
37 {
38 	magic = _magic;
39 }
40 
~CReaderPFM()41 CReaderPFM::~CReaderPFM()
42 {
43 }
44 
initialize(CFile * fp,char * magic)45 bool CReaderPFM::initialize(
46 	CFile *fp,
47 	char *magic)
48 {
49 	_is_color = (strcmp(magic, _magic[0]) == 0);
50 	char buf[256];
51 	if (fp->gets(buf, sizeof(buf)) == NULL
52 		|| buf[0] != '\n') {
53 		return false;
54 	}
55 	if (fp->gets(buf, sizeof(buf)) == NULL
56 		|| buf[strlen(buf) - 1] != '\n'
57 		|| sscanf(buf, "%d %d", &_w, &_h) != 2
58 		|| _w <= 0
59 		|| _h <= 0) {
60 		return false;
61 	}
62 	if (fp->gets(buf, sizeof(buf)) == NULL
63 		|| buf[strlen(buf) - 1] != '\n'
64 		|| sscanf(buf, "%f", &_scale) != 1
65 		|| _scale == 0.0f) {
66 		return false;
67 	}
68 	_is_swapped = (isLittleEndian() && _scale > 0.0 || ! isLittleEndian() && _scale < 0.0);
69 	return true;
70 }
71 
read(CFile * fp,CImage<float,4> * image)72 void CReaderPFM::read(
73 	CFile *fp,
74 	CImage<float, 4> *image)
75 {
76 	int c = (_is_color) ? 3 : 1;
77 	for (int y = 0; y < _h; y++) {
78 		float *data = image->pixel(0, 0) + (_h - 1 - y) * _w * 4;
79 		for (int x = 0; x < _w; x += 64) {
80 			int n0 = min(64, _w - x);
81 			int n;
82 			float tmp[c * 64];
83 			if ((n = (fp->read(tmp, c * sizeof(float) * n0) / (c * sizeof(float)))) == 0) {
84 				return;
85 			}
86 			image->lock();
87 			float *tp = tmp;
88 			if (_is_color) {
89 				for (int i = 0; i < n; i++) {
90 					swap4(tp);
91 					*data++ = *tp++;
92 					swap4(tp);
93 					*data++ = *tp++;
94 					swap4(tp);
95 					*data++ = *tp++;
96 					*data++ = 1.0;
97 				}
98 			} else {
99 				for (int i = 0; i < n; i++) {
100 					swap4(tp);
101 					*data++ = *tp;
102 					*data++ = *tp;
103 					*data++ = *tp++;
104 					*data++ = 1.0;
105 				}
106 			}
107 			image->setChanged(true);
108 			image->unlock();
109 			if (n < n0) {
110 				return;
111 			}
112 		}
113 	}
114 }
115 
116 // protected functions
117 
swap4(float * f)118 void CReaderPFM::swap4(
119 	float *f)
120 {
121 	if (! _is_swapped)
122 		return;
123 	uint8_t *p = (uint8_t *)&f;
124 	swap(p[0], p[3]);
125 	swap(p[1], p[2]);
126 }
127 
128 // private functions
129 // local functions
130