1 /* PHOROS -- Photogrammetric Road Survey */
2 /* Copyright (C) 2016 Bert Burgemeister */
4 /* This program is free software; you can redistribute it and/or modify */
5 /* it under the terms of the GNU General Public License as published by */
6 /* the Free Software Foundation; either version 2 of the License, or */
7 /* (at your option) any later version. */
9 /* This program is distributed in the hope that it will be useful, */
10 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
11 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
12 /* GNU General Public License for more details. */
14 /* You should have received a copy of the GNU General Public License along */
15 /* with this program; if not, write to the Free Software Foundation, Inc., */
16 /* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
26 cplt_horiz(unsigned char *rawp
, png_bytep row
, int y
, int x
, int color
, int width
)
28 row
[3 * x
+ color
] = (rawp
[-1] + rawp
[1]) / 2;
32 cplt_vert(unsigned char *rawp
, png_bytep row
, int y
, int x
, int color
, int width
)
34 row
[3 * x
+ color
] = (rawp
[-width
] + rawp
[width
]) / 2;
38 cplt_squ(unsigned char *rawp
, png_bytep row
, int y
, int x
, int color
, int width
)
40 row
[3 * x
+ color
] = (rawp
[-1] + rawp
[1] + rawp
[-width
] + rawp
[width
]) / 4;
44 cplt_diag(unsigned char *rawp
, png_bytep row
, int y
, int x
, int color
, int width
)
46 row
[3 * x
+ color
] = (rawp
[-width
- 1] + rawp
[-width
+ 1] +
47 rawp
[width
- 1] + rawp
[width
+ 1]) / 4;
51 cplt_g_on_r(unsigned char *rawp
, png_bytep row
, int y
, int x
, int width
)
53 cplt_horiz(rawp
, row
, y
, x
, 0, width
);
54 cplt_vert(rawp
, row
, y
, x
, 2, width
);
58 cplt_g_on_b(unsigned char *rawp
, png_bytep row
, int y
, int x
, int width
)
60 cplt_horiz(rawp
, row
, y
, x
, 2, width
);
61 cplt_vert(rawp
, row
, y
, x
, 0, width
);
65 cplt_r(unsigned char *rawp
, png_bytep row
, int y
, int x
, int width
)
67 cplt_squ(rawp
, row
, y
, x
, 1, width
);
68 cplt_diag(rawp
, row
, y
, x
, 2, width
);
72 cplt_b(unsigned char *rawp
, png_bytep row
, int y
, int x
, int width
)
74 cplt_squ(rawp
, row
, y
, x
, 1, width
);
75 cplt_diag(rawp
, row
, y
, x
, 0, width
);
79 colrz_r(unsigned char *rawp
, png_bytep row
, int y
, int x
)
81 row
[3 * x
+ 0] = rawp
[0];
85 colrz_g(unsigned char *rawp
, png_bytep row
, int y
, int x
)
87 row
[3 * x
+ 1] = rawp
[0];
91 colrz_b(unsigned char *rawp
, png_bytep row
, int y
, int x
)
93 row
[3 * x
+ 2] = rawp
[0];
97 raise_color(png_bytep row
, int x
, double *colr_raisr
)
101 for (i
= 0; i
< 3; i
++) {
102 val
= round(row
[3 * x
+ i
] * colr_raisr
[i
]);
105 row
[3 * x
+ i
] = val
;
110 raise_noop(png_bytep row
, int x
, double *colr_raisr
)
114 /* structure to store in-memory PNG in */
122 write_png_data(png_structp png_ptr
, png_bytep data
, png_size_t length
)
124 struct mem_encode
*p
= (struct mem_encode
*)png_get_io_ptr(png_ptr
);
125 size_t nsize
= p
->size
+ length
;
126 /* allocate or grow buffer */
128 p
->buffer
= realloc(p
->buffer
, nsize
);
130 p
->buffer
= malloc(nsize
);
132 png_error(png_ptr
, "Write Error");
133 /* copy new bytes to end of buffer */
134 memcpy(p
->buffer
+ p
->size
, data
, length
);
139 flush_png(png_structp png_ptr
)
144 uncompressed2png(struct mem_encode
*mem_png
, int width
, int height
, int channels
,
145 int *bayerpat
, double *color_raiser
, unsigned char *uncompressed
)
148 png_structp png_ptr
= NULL
;
149 png_infop info_ptr
= NULL
;
150 png_bytep row
= NULL
;
151 void (*colrz_ev_ev
)(unsigned char *, png_bytep
, int, int) = NULL
;
152 void (*colrz_ev_od
)(unsigned char *, png_bytep
, int, int) = NULL
;
153 void (*colrz_od_ev
)(unsigned char *, png_bytep
, int, int) = NULL
;
154 void (*colrz_od_od
)(unsigned char *, png_bytep
, int, int) = NULL
;
155 void (*cplt_ev_ev
)(unsigned char *, png_bytep
, int, int, int) = NULL
;
156 void (*cplt_ev_od
)(unsigned char *, png_bytep
, int, int, int) = NULL
;
157 void (*cplt_od_ev
)(unsigned char *, png_bytep
, int, int, int) = NULL
;
158 void (*cplt_od_od
)(unsigned char *, png_bytep
, int, int, int) = NULL
;
159 void (*raise
)(unsigned char *, int, double *) = raise_noop
;
160 int x
, y
, x_ev
, x_od
, y_ev
, y_od
;
163 for (i
= 0; i
< 3; i
++)
164 if (fabs(color_raiser
[i
] - 1) > 0.00001)
167 if (bayerpat
[0] == 0x0000ff) { /* red */
168 colrz_ev_ev
= colrz_r
;
169 colrz_ev_od
= colrz_g
;
170 colrz_od_ev
= colrz_g
;
171 colrz_od_od
= colrz_b
;
173 cplt_ev_od
= cplt_g_on_r
;
174 cplt_od_ev
= cplt_g_on_b
;
176 } else if (bayerpat
[0] == 0xff0000) { /* blue */
177 colrz_ev_ev
= colrz_b
;
178 colrz_ev_od
= colrz_g
;
179 colrz_od_ev
= colrz_g
;
180 colrz_od_od
= colrz_r
;
182 cplt_ev_od
= cplt_g_on_b
;
183 cplt_od_ev
= cplt_g_on_r
;
185 } else if (bayerpat
[0] == 0x00ff00) { /* green */
186 if (bayerpat
[1] == 0x0000ff) { /* red */
187 colrz_ev_ev
= colrz_g
;
188 colrz_ev_od
= colrz_r
;
189 colrz_od_ev
= colrz_b
;
190 colrz_od_od
= colrz_g
;
191 cplt_ev_ev
= cplt_g_on_r
;
194 cplt_od_od
= cplt_g_on_b
;
195 } else if (bayerpat
[1] == 0xff0000) { /* blue */
196 colrz_ev_ev
= colrz_g
;
197 colrz_ev_od
= colrz_b
;
198 colrz_od_ev
= colrz_r
;
199 colrz_od_od
= colrz_g
;
200 cplt_ev_ev
= cplt_g_on_b
;
203 cplt_od_od
= cplt_g_on_r
;
205 retval
= 2; /* all green is not a Bayer pattern */
209 retval
= 3; /* first byte neither 0x00 nor 0xff */
213 png_ptr
= png_create_write_struct(PNG_LIBPNG_VER_STRING
, NULL
, NULL
, NULL
);
214 if (png_ptr
== NULL
) {
215 retval
= 11; /* Could not allocate write struct */
218 info_ptr
= png_create_info_struct(png_ptr
);
219 if (info_ptr
== NULL
) {
220 retval
= 12; /* Could not allocate info struct */
223 if (setjmp(png_jmpbuf(png_ptr
))) {
224 retval
= 13; /* Error during png creation */
227 mem_png
->buffer
= NULL
;
229 png_set_write_fn(png_ptr
, mem_png
, write_png_data
, flush_png
);
230 /* Write header (8 bit colour depth) */
231 row
= malloc(channels
* width
* sizeof(png_byte
));
236 /* Write image data */
238 png_set_IHDR(png_ptr
, info_ptr
, width
, height
,
239 8, PNG_COLOR_TYPE_RGB
, PNG_INTERLACE_NONE
,
240 PNG_COMPRESSION_TYPE_BASE
, PNG_FILTER_TYPE_BASE
);
241 png_write_info(png_ptr
, info_ptr
);
242 for (y_ev
= 0, y_od
= 1;
243 y_ev
< height
&& y_od
< height
;
244 y_ev
+= 2, y_od
+= 2) {
245 for (x_ev
= 0, x_od
= 1;
246 x_ev
< width
&& x_od
< width
;
247 x_ev
+= 2, x_od
+= 2) {
248 colrz_ev_ev(uncompressed
+ y_ev
* width
+ x_ev
,
250 colrz_ev_od(uncompressed
+ y_ev
* width
+ x_od
,
252 if (y_ev
> 0 && y_ev
< height
- 1) {
253 cplt_ev_ev(uncompressed
+ y_ev
* width
+ x_ev
,
254 row
, y_ev
, x_ev
, width
);
255 cplt_ev_od(uncompressed
+ y_ev
* width
+ x_od
,
256 row
, y_ev
, x_od
, width
);
258 raise(row
, x_ev
, color_raiser
);
259 raise(row
, x_od
, color_raiser
);
261 png_write_row(png_ptr
, row
);
262 for (x_ev
= 0, x_od
= 1;
263 x_ev
< width
&& x_od
< width
;
264 x_ev
+= 2, x_od
+= 2) {
265 colrz_od_ev(uncompressed
+ y_od
* width
+ x_ev
,
267 colrz_od_od(uncompressed
+ y_od
* width
+ x_od
,
269 if (y_od
< height
- 1) {
270 cplt_od_ev(uncompressed
+ y_od
* width
+ x_ev
,
271 row
, y_od
, x_ev
, width
);
272 cplt_od_od(uncompressed
+ y_od
* width
+ x_od
,
273 row
, y_od
, x_od
, width
);
275 raise(row
, x_ev
, color_raiser
);
276 raise(row
, x_od
, color_raiser
);
278 png_write_row(png_ptr
, row
);
280 } else if (channels
== 1) {
281 png_set_IHDR(png_ptr
, info_ptr
, width
, height
,
282 8, PNG_COLOR_TYPE_GRAY
, PNG_INTERLACE_NONE
,
283 PNG_COMPRESSION_TYPE_BASE
, PNG_FILTER_TYPE_BASE
);
284 png_write_info(png_ptr
, info_ptr
);
285 for (y
= 0; y
< height
; y
++) {
286 for (x
= 0; x
< width
; x
++) {
287 row
[x
] = uncompressed
[y
* width
+ x
];
289 png_write_row(png_ptr
, row
);
292 retval
= 6; /* wrong number of channels */
295 png_write_end(png_ptr
, NULL
);
297 if (info_ptr
!= NULL
) png_free_data(png_ptr
, info_ptr
, PNG_FREE_ALL
, -1);
298 if (png_ptr
!= NULL
) png_destroy_write_struct(&png_ptr
, NULL
);
299 if (row
!= NULL
) free(row
);
304 huffdecode(int width
, int height
, unsigned char *uncompressed
,
305 unsigned char hcode
[static 4 * 511], unsigned char hlen
[static 511],
306 unsigned char *compressed
)
315 int row
, column
, cidx
;
317 unsigned int rowhead
;
319 for (i
= 0; i
< 511; i
++)
320 if (hlen
[i
] > maxlen
)
322 if ((htable
= malloc((1 << maxlen
) * sizeof(struct huffval
))) == NULL
)
324 /* htable may well become too big to fit into memory. Maybe
325 we should act a bit smarter and handle longer huffman codes
327 for (i
= 0; i
< 511; i
++) {
329 code
= hcode
[4 * i
] << 24 | hcode
[4 * i
+ 1] << 16 |
330 hcode
[4 * i
+ 2] << 8 | hcode
[4 * i
+ 3];
331 code
<<= maxlen
- hlen
[i
];
332 htable
[code
].val
= i
- 255;
333 htable
[code
].len
= hlen
[i
];
334 for (j
= 0; j
< (1 << maxlen
- hlen
[i
]); j
++) {
335 htable
[code
| j
].val
= i
- 255;
336 htable
[code
| j
].len
= hlen
[i
];
341 for (i
= 0, m
= 1; i
< maxlen
; i
++, m
<<= 1)
344 for (row
= 0; row
< height
; row
++) {
345 rowhead
= compressed
[cidx
/ 8] << 16;
347 rowhead
|= compressed
[cidx
/ 8] << 8;
349 rowhead
|= compressed
[cidx
/ 8];
350 rowhead
>>= 8 - cidx
% 8;
351 uncompressed
[width
* row
] = (rowhead
>> 8) & 0xff;
352 uncompressed
[width
* row
+ 1] = rowhead
& 0xff;
353 for (column
= 2; column
< width
; column
++) {
354 div_t cidx_d
, maxlen_d
;
358 cidx_d
= div(cidx
, 8);
359 rem_bits
= maxlen
- (8 - cidx_d
.rem
);
360 cidx
+= 8 - cidx_d
.rem
;
361 maxlen_d
= div(maxlen
, 8);
362 hc
= compressed
[cidx_d
.quot
];
363 for (i
= rem_bits
; i
> 0; i
-= 8, cidx
+= 8) {
365 hc
|= compressed
[cidx
/ 8];
367 if ((r
= rem_bits
% 8) > 0) {
372 uncompressed
[width
* row
+ column
] =
373 uncompressed
[width
* row
+ column
- 2] - htable
[hc
].val
;
374 cidx
-= maxlen
- htable
[hc
].len
;
382 reverse(unsigned char *base
, size_t size
)
387 for (i
= 0, j
= size
- 1; i
< j
; i
++, j
--) {
395 brighten(unsigned char *base
, size_t size
)
398 unsigned char min
= UCHAR_MAX
, max
= 0, range
;
400 for (i
= 0; i
< size
; i
++) {
408 for (i
= 0; i
< size
; i
++)
409 base
[i
] = (base
[i
] - min
) * UCHAR_MAX
/ range
;
413 png2mem(char *path
, int start
, int len
, int width
, int height
,
414 int channels
, int *bayer_pattern
, int compr_mode
,
415 unsigned char *uncompressed
, unsigned char *compressed
,
416 struct mem_encode
*mem_png
,
417 int reversep
, int brightenp
, double *color_raiser
)
420 unsigned char hlen
[511], hcode
[511 * 4];
423 if ((in
= fopen(path
, "r")) == NULL
)
425 fseek(in
, start
, SEEK_CUR
);
426 if (compr_mode
== 1 || compr_mode
== 2) {
427 fread(hcode
, sizeof(hcode
[0]), 511 * 4, in
);
428 fread(hlen
, sizeof(hlen
[0]), 511, in
);
429 fread(compressed
, sizeof(compressed
[0]), len
, in
);
431 if ((retval
= huffdecode(width
, height
, uncompressed
, hcode
,
432 hlen
, compressed
)) != 0)
435 reverse(uncompressed
, width
* height
);
437 brighten(uncompressed
, width
* height
);
438 if ((retval
= uncompressed2png(mem_png
, width
, height
, channels
,
439 bayer_pattern
, color_raiser
,
443 } else if (compr_mode
== 0) { /* untested */
444 fread(uncompressed
, sizeof(uncompressed
[0]), width
* height
, in
);
447 reverse(uncompressed
, width
* height
);
449 brighten(uncompressed
, width
* height
);
450 if ((retval
= uncompressed2png(mem_png
, width
, height
, channels
,
451 bayer_pattern
, color_raiser
,
467 main(int argc
, char *argv
[])
470 unsigned char compressed
[1390353];
471 unsigned char uncompressed
[1700 * 1500];
472 int width
= 1700, height
= 1500;
473 struct mem_encode mp
;
475 setvbuf(stdout
, NULL
, _IONBF
, 0);
477 png2mem("mitsa005_CCD_Front_PULNIX_13.pictures", 2247 + 17, 1390353, width
, height
, 3, (int[2]){0x00ff00, 0x0000ff}, 2, uncompressed
, compressed
, &mp
, 0, 0, (double[3]){1, 1, 1});
478 fp
= fopen("o0.png", "wb");
480 fprintf(stderr
, "Could not open file %s for writing\n", "o0.png");
482 fwrite(mp
.buffer
, mp
.size
, sizeof(mp
.buffer
[0]), fp
);
484 png2mem("mitsa005_CCD_Front_PULNIX_13.pictures", 2247 + 17, 1390353, width
, height
, 3, (int[2]){0x00ff00, 0x0000ff}, 2, uncompressed
, compressed
, &mp
, 0, 1, (double[3]){1, 2.5, 1.5});
485 fp
= fopen("o1.png", "wb");
487 fprintf(stderr
, "Could not open file %s for writing\n", "o1.png");
489 fwrite(mp
.buffer
, mp
.size
, sizeof(mp
.buffer
[0]), fp
);