1 /* PHOROS -- Photogrammetric Road Survey */
2 /* Copyright (C) 2016, 2017 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. */
28 cplt_horiz(unsigned char *rawp
, png_bytep row
, int y
, int x
, int color
, int width
)
30 row
[3 * x
+ color
] = (rawp
[-1] + rawp
[1]) / 2;
34 cplt_vert(unsigned char *rawp
, png_bytep row
, int y
, int x
, int color
, int width
)
36 row
[3 * x
+ color
] = (rawp
[-width
] + rawp
[width
]) / 2;
40 cplt_squ(unsigned char *rawp
, png_bytep row
, int y
, int x
, int color
, int width
)
42 row
[3 * x
+ color
] = (rawp
[-1] + rawp
[1] + rawp
[-width
] + rawp
[width
]) / 4;
46 cplt_diag(unsigned char *rawp
, png_bytep row
, int y
, int x
, int color
, int width
)
48 row
[3 * x
+ color
] = (rawp
[-width
- 1] + rawp
[-width
+ 1] +
49 rawp
[width
- 1] + rawp
[width
+ 1]) / 4;
53 cplt_g_on_r(unsigned char *rawp
, png_bytep row
, int y
, int x
, int width
)
55 cplt_horiz(rawp
, row
, y
, x
, 0, width
);
56 cplt_vert(rawp
, row
, y
, x
, 2, width
);
60 cplt_g_on_b(unsigned char *rawp
, png_bytep row
, int y
, int x
, int width
)
62 cplt_horiz(rawp
, row
, y
, x
, 2, width
);
63 cplt_vert(rawp
, row
, y
, x
, 0, width
);
67 cplt_r(unsigned char *rawp
, png_bytep row
, int y
, int x
, int width
)
69 cplt_squ(rawp
, row
, y
, x
, 1, width
);
70 cplt_diag(rawp
, row
, y
, x
, 2, width
);
74 cplt_b(unsigned char *rawp
, png_bytep row
, int y
, int x
, int width
)
76 cplt_squ(rawp
, row
, y
, x
, 1, width
);
77 cplt_diag(rawp
, row
, y
, x
, 0, width
);
81 colrz_r(unsigned char *rawp
, png_bytep row
, int y
, int x
)
83 row
[3 * x
+ 0] = rawp
[0];
87 colrz_g(unsigned char *rawp
, png_bytep row
, int y
, int x
)
89 row
[3 * x
+ 1] = rawp
[0];
93 colrz_b(unsigned char *rawp
, png_bytep row
, int y
, int x
)
95 row
[3 * x
+ 2] = rawp
[0];
99 raise_color(png_bytep row
, int x
, double *colr_raisr
)
103 for (i
= 0; i
< 3; i
++) {
104 val
= round(row
[3 * x
+ i
] * colr_raisr
[i
]);
107 row
[3 * x
+ i
] = val
;
112 raise_noop(png_bytep row
, int x
, double *colr_raisr
)
116 /* structure to store in-memory PNG in */
124 write_png_data(png_structp png_ptr
, png_bytep data
, png_size_t length
)
126 struct mem_encode
*p
= (struct mem_encode
*)png_get_io_ptr(png_ptr
);
127 size_t nsize
= p
->size
+ length
;
128 /* allocate or grow buffer */
130 p
->buffer
= realloc(p
->buffer
, nsize
);
132 p
->buffer
= malloc(nsize
);
134 png_error(png_ptr
, "Write Error");
135 /* copy new bytes to end of buffer */
136 memcpy(p
->buffer
+ p
->size
, data
, length
);
141 flush_png(png_structp png_ptr
)
146 uncompressed2png(struct mem_encode
*mem_png
, int width
, int height
, int channels
,
147 int *bayerpat
, double *color_raiser
, unsigned char *uncompressed
)
150 png_structp png_ptr
= NULL
;
151 png_infop info_ptr
= NULL
;
152 png_bytep row
= NULL
;
153 void (*colrz_ev_ev
)(unsigned char *, png_bytep
, int, int) = NULL
;
154 void (*colrz_ev_od
)(unsigned char *, png_bytep
, int, int) = NULL
;
155 void (*colrz_od_ev
)(unsigned char *, png_bytep
, int, int) = NULL
;
156 void (*colrz_od_od
)(unsigned char *, png_bytep
, int, int) = NULL
;
157 void (*cplt_ev_ev
)(unsigned char *, png_bytep
, int, int, int) = NULL
;
158 void (*cplt_ev_od
)(unsigned char *, png_bytep
, int, int, int) = NULL
;
159 void (*cplt_od_ev
)(unsigned char *, png_bytep
, int, int, int) = NULL
;
160 void (*cplt_od_od
)(unsigned char *, png_bytep
, int, int, int) = NULL
;
161 void (*raise
)(unsigned char *, int, double *) = raise_noop
;
162 int x
, y
, x_ev
, x_od
, y_ev
, y_od
;
165 for (i
= 0; i
< 3; i
++)
166 if (fabs(color_raiser
[i
] - 1) > 0.00001)
169 if (bayerpat
[0] == 0x0000ff) { /* red */
170 colrz_ev_ev
= colrz_r
;
171 colrz_ev_od
= colrz_g
;
172 colrz_od_ev
= colrz_g
;
173 colrz_od_od
= colrz_b
;
175 cplt_ev_od
= cplt_g_on_r
;
176 cplt_od_ev
= cplt_g_on_b
;
178 } else if (bayerpat
[0] == 0xff0000) { /* blue */
179 colrz_ev_ev
= colrz_b
;
180 colrz_ev_od
= colrz_g
;
181 colrz_od_ev
= colrz_g
;
182 colrz_od_od
= colrz_r
;
184 cplt_ev_od
= cplt_g_on_b
;
185 cplt_od_ev
= cplt_g_on_r
;
187 } else if (bayerpat
[0] == 0x00ff00) { /* green */
188 if (bayerpat
[1] == 0x0000ff) { /* red */
189 colrz_ev_ev
= colrz_g
;
190 colrz_ev_od
= colrz_r
;
191 colrz_od_ev
= colrz_b
;
192 colrz_od_od
= colrz_g
;
193 cplt_ev_ev
= cplt_g_on_r
;
196 cplt_od_od
= cplt_g_on_b
;
197 } else if (bayerpat
[1] == 0xff0000) { /* blue */
198 colrz_ev_ev
= colrz_g
;
199 colrz_ev_od
= colrz_b
;
200 colrz_od_ev
= colrz_r
;
201 colrz_od_od
= colrz_g
;
202 cplt_ev_ev
= cplt_g_on_b
;
205 cplt_od_od
= cplt_g_on_r
;
207 retval
= 2; /* all green is not a Bayer pattern */
211 retval
= 3; /* first byte neither 0x00 nor 0xff */
215 png_ptr
= png_create_write_struct(PNG_LIBPNG_VER_STRING
, NULL
, NULL
, NULL
);
216 if (png_ptr
== NULL
) {
217 retval
= 11; /* Could not allocate write struct */
220 info_ptr
= png_create_info_struct(png_ptr
);
221 if (info_ptr
== NULL
) {
222 retval
= 12; /* Could not allocate info struct */
225 if (setjmp(png_jmpbuf(png_ptr
))) {
226 retval
= 13; /* Error during png creation */
229 mem_png
->buffer
= NULL
;
231 png_set_write_fn(png_ptr
, mem_png
, write_png_data
, flush_png
);
232 row
= malloc(channels
* width
* sizeof(png_byte
));
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 uncompressedjpeg2png(struct mem_encode
*mem_png
, int width
, int height
,
305 int channels
, double *color_raiser
,
306 unsigned char *uncompressed
)
309 png_structp png_ptr
= NULL
;
310 png_infop info_ptr
= NULL
;
311 void (*raise
)(unsigned char *, int, double *) = raise_noop
;
315 for (i
= 0; i
< 3; i
++)
316 if (fabs(color_raiser
[i
] - 1) > 0.00001)
318 png_ptr
= png_create_write_struct(PNG_LIBPNG_VER_STRING
, NULL
, NULL
, NULL
);
319 if (png_ptr
== NULL
) {
320 retval
= 11; /* Could not allocate write struct */
323 info_ptr
= png_create_info_struct(png_ptr
);
324 if (info_ptr
== NULL
) {
325 retval
= 12; /* Could not allocate info struct */
328 if (setjmp(png_jmpbuf(png_ptr
))) {
329 retval
= 13; /* Error during png creation */
332 mem_png
->buffer
= NULL
;
334 png_set_write_fn(png_ptr
, mem_png
, write_png_data
, flush_png
);
336 for (i
= 0; i
< width
* height
; i
++)
337 raise(uncompressed
, i
, color_raiser
);
338 png_set_IHDR(png_ptr
, info_ptr
, width
, height
,
339 8, PNG_COLOR_TYPE_RGB
, PNG_INTERLACE_NONE
,
340 PNG_COMPRESSION_TYPE_BASE
, PNG_FILTER_TYPE_BASE
);
341 } else if (channels
== 1) {
342 png_set_IHDR(png_ptr
, info_ptr
, width
, height
,
343 8, PNG_COLOR_TYPE_GRAY
, PNG_INTERLACE_NONE
,
344 PNG_COMPRESSION_TYPE_BASE
, PNG_FILTER_TYPE_BASE
);
346 retval
= 6; /* wrong number of channels */
349 png_write_info(png_ptr
, info_ptr
);
350 for (y
= 0; y
< height
; y
++)
351 png_write_row(png_ptr
, uncompressed
+ y
* width
* channels
);
352 png_write_end(png_ptr
, NULL
);
354 if (info_ptr
!= NULL
) png_free_data(png_ptr
, info_ptr
, PNG_FREE_ALL
, -1);
355 if (png_ptr
!= NULL
) png_destroy_write_struct(&png_ptr
, NULL
);
360 huffdecode(int width
, int height
, unsigned char *uncompressed
,
361 unsigned char hcode
[static 4 * 511], unsigned char hlen
[static 511],
362 unsigned char *compressed
)
371 int row
, column
, cidx
;
373 unsigned int rowhead
;
375 for (i
= 0; i
< 511; i
++)
376 if (hlen
[i
] > maxlen
)
378 if ((htable
= malloc((1 << maxlen
) * sizeof(struct huffval
))) == NULL
)
380 /* htable may well become too big to fit into memory. Maybe
381 we should act a bit smarter and handle longer huffman codes
383 for (i
= 0; i
< 511; i
++) {
385 code
= hcode
[4 * i
] << 24 | hcode
[4 * i
+ 1] << 16 |
386 hcode
[4 * i
+ 2] << 8 | hcode
[4 * i
+ 3];
387 code
<<= maxlen
- hlen
[i
];
388 htable
[code
].val
= i
- 255;
389 htable
[code
].len
= hlen
[i
];
390 for (j
= 0; j
< (1 << maxlen
- hlen
[i
]); j
++) {
391 htable
[code
| j
].val
= i
- 255;
392 htable
[code
| j
].len
= hlen
[i
];
397 for (i
= 0, m
= 1; i
< maxlen
; i
++, m
<<= 1)
400 for (row
= 0; row
< height
; row
++) {
401 rowhead
= compressed
[cidx
/ 8] << 16;
403 rowhead
|= compressed
[cidx
/ 8] << 8;
405 rowhead
|= compressed
[cidx
/ 8];
406 rowhead
>>= 8 - cidx
% 8;
407 uncompressed
[width
* row
] = (rowhead
>> 8) & 0xff;
408 uncompressed
[width
* row
+ 1] = rowhead
& 0xff;
409 for (column
= 2; column
< width
; column
++) {
410 div_t cidx_d
, maxlen_d
;
414 cidx_d
= div(cidx
, 8);
415 rem_bits
= maxlen
- (8 - cidx_d
.rem
);
416 cidx
+= 8 - cidx_d
.rem
;
417 maxlen_d
= div(maxlen
, 8);
418 hc
= compressed
[cidx_d
.quot
];
419 for (i
= rem_bits
; i
> 0; i
-= 8, cidx
+= 8) {
421 hc
|= compressed
[cidx
/ 8];
423 if ((r
= rem_bits
% 8) > 0) {
428 uncompressed
[width
* row
+ column
] =
429 uncompressed
[width
* row
+ column
- 2] - htable
[hc
].val
;
430 cidx
-= maxlen
- htable
[hc
].len
;
438 reverse(unsigned char *base
, size_t size
)
443 for (i
= 0, j
= size
- 1; i
< j
; i
++, j
--) {
451 brighten(unsigned char *base
, size_t size
)
454 unsigned char min
= UCHAR_MAX
, max
= 0, range
;
456 for (i
= 0; i
< size
; i
++) {
464 for (i
= 0; i
< size
; i
++)
465 base
[i
] = (base
[i
] - min
) * UCHAR_MAX
/ range
;
468 struct imread_jpeg_error_mgr
{
469 struct jpeg_error_mgr pub
;
470 jmp_buf setjmp_buffer
;
473 typedef struct imread_jpeg_error_mgr
*imread_jpeg_error_ptr
;
476 imread_jpeg_error_exit (j_common_ptr cinfo
)
478 imread_jpeg_error_ptr myerr
= (imread_jpeg_error_ptr
) cinfo
->err
;
479 (*cinfo
->err
->output_message
) (cinfo
);
480 longjmp(myerr
->setjmp_buffer
, 1);
484 png2mem(char *path
, int start
, int len
, int width
, int height
,
485 int channels
, int *bayer_pattern
, int compr_mode
,
486 unsigned char *uncompressed
, unsigned char *compressed
,
487 struct mem_encode
*mem_png
,
488 int reversep
, int brightenp
, double *color_raiser
)
491 unsigned char hlen
[511], hcode
[511 * 4];
492 int htblsize
= 511 * (1 + 4);
495 if ((in
= fopen(path
, "r")) == NULL
)
497 fseek(in
, start
, SEEK_CUR
);
498 if (compr_mode
== 1 || compr_mode
== 2) {
499 fread(hcode
, sizeof(hcode
[0]), 511 * 4, in
);
500 fread(hlen
, sizeof(hlen
[0]), 511, in
);
501 fread(compressed
, sizeof(compressed
[0]), len
- htblsize
, in
);
503 if ((retval
= huffdecode(width
, height
, uncompressed
, hcode
,
504 hlen
, compressed
)) != 0)
507 reverse(uncompressed
, width
* height
);
509 brighten(uncompressed
, width
* height
);
510 if ((retval
= uncompressed2png(mem_png
, width
, height
, channels
,
511 bayer_pattern
, color_raiser
,
515 } else if (compr_mode
== 3) { /* JPEG */
516 struct jpeg_decompress_struct cinfo
;
517 struct imread_jpeg_error_mgr jerr
;
518 unsigned char *next_line
;
521 cinfo
.err
= jpeg_std_error(&jerr
.pub
);
522 jerr
.pub
.error_exit
= imread_jpeg_error_exit
;
523 if (setjmp(jerr
.setjmp_buffer
)) {
524 jpeg_destroy_decompress(&cinfo
);
525 return 71; /* JPEG decompression error */
527 jpeg_create_decompress(&cinfo
);
528 fread(compressed
, sizeof(compressed
[0]), len
, in
);
530 jpeg_mem_src(&cinfo
, compressed
, len
);
531 jpeg_read_header(&cinfo
, TRUE
);
532 if (cinfo
.image_width
* cinfo
.image_height
* cinfo
.num_components
>
533 width
* height
* channels
) {
534 return 72; /* JPEG bigger than expected */
535 jpeg_destroy_decompress(&cinfo
);
537 jpeg_start_decompress(&cinfo
);
538 next_line
= uncompressed
;
539 while (cinfo
.output_scanline
< cinfo
.output_height
) {
540 nsamples
= jpeg_read_scanlines(&cinfo
, (JSAMPARRAY
)&next_line
, 1);
541 next_line
+= nsamples
* cinfo
.image_width
* cinfo
.num_components
;
543 jpeg_finish_decompress(&cinfo
);
544 jpeg_destroy_decompress(&cinfo
);
546 return 73; /* JPEG reversing not implemented */
548 return 74; /* JPEG brightening not implemented */
549 if ((retval
= uncompressedjpeg2png(
550 mem_png
, cinfo
.image_width
, cinfo
.image_height
,
551 cinfo
.num_components
, color_raiser
,
555 } else if (compr_mode
== 0) { /* untested */
556 fread(uncompressed
, sizeof(uncompressed
[0]), width
* height
, in
);
559 reverse(uncompressed
, width
* height
);
561 brighten(uncompressed
, width
* height
);
562 if ((retval
= uncompressed2png(mem_png
, width
, height
, channels
,
563 bayer_pattern
, color_raiser
,
579 main(int argc
, char *argv
[])
582 unsigned char compressed
[1390353];
583 unsigned char uncompressed
[1700 * 1500];
584 int width
= 1700, height
= 1500;
585 struct mem_encode mp
;
587 setvbuf(stdout
, NULL
, _IONBF
, 0);
589 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});
590 fp
= fopen("o0.png", "wb");
592 fprintf(stderr
, "Could not open file %s for writing\n", "o0.png");
594 fwrite(mp
.buffer
, mp
.size
, sizeof(mp
.buffer
[0]), fp
);
596 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});
597 fp
= fopen("o1.png", "wb");
599 fprintf(stderr
, "Could not open file %s for writing\n", "o1.png");
601 fwrite(mp
.buffer
, mp
.size
, sizeof(mp
.buffer
[0]), fp
);