1 // Copyright 2002 David Hilvert <dhilvert@auricle.dyndns.org>,
2 // <dhilvert@ugcs.caltech.edu>
4 /* This file is part of the Anti-Lamenessing Engine.
6 The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 The Anti-Lamenessing Engine is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with the Anti-Lamenessing Engine; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * image_rw.h: Read and write images.
26 #ifndef __image_rw_h__
27 #define __image_rw_h__
30 #include "image_ale_real.h"
31 #include "image_bayer_ale_real.h"
32 #include "image_accel.h"
34 #include "exposure/exposure.h"
35 #include "exposure/exposure_default.h"
40 * Private data members
46 * 0 = No type selected
55 static unsigned int num_bits
;
56 static unsigned int mcv
;
59 * Nearest-neighbor defined value radius.
61 static double nn_defined_radius
;
64 * Input and output exposure models
66 static exposure
**input_exposure
;
67 static exposure
*output_exposure
;
68 static int exposure_scale
;
71 * Default bayer pattern
73 static unsigned int bayer_default
;
76 * Image-specific bayer patterns.
78 static unsigned int *bayer_specific
;
81 * Pointer to the output filename
83 static const char *output_filename
;
86 * Variables relating to input image files and image data structures.
88 static const char **filenames
;
89 static unsigned int file_count
;
90 static ale_image
*images
;
91 static int *files_open
;
94 * The most recently closed image number.
96 static int latest_close_num
;
101 static double cache_size
;
104 * Number of cached files.
106 static unsigned int cache_count
;
109 * Private methods to init and shut down the file reader.
113 * Initialize the image file handler
115 static void init_image() {
117 InitializeMagick("ale");
122 * Destroy the image file handler
124 static void destroy_image() {
130 static ale_image
read_image_im(const char *filename
, exposure
*exp
, const char *name
,
131 unsigned int bayer
, int init_reference_gain
) {
132 static int warned
= 0;
135 if (MaxRGB
< 65535 && mcv
== 65535 && !warned
) {
136 fprintf(stderr
, "\n\n*** Warning: " MagickPackageName
" has not been compiled with 16 bit support.\n");
137 fprintf(stderr
, "*** Reading input using 8 bits per channel.\n");
138 fprintf(stderr
, "*** \n");
139 fprintf(stderr
, "*** (To silence this warning, specify option --8bpc)\n\n\n");
145 * Patterned after http://www.imagemagick.org/www/api.html
146 * and http://www.imagemagick.org/www/smile.c
149 ExceptionInfo exception
;
151 ImageInfo
*image_info
;
153 FILE *converted_f
= tmpfile();
154 const PixelPacket
*p
;
158 ale_real black_level
= exp
->get_black_level();
160 GetExceptionInfo(&exception
);
161 image_info
= CloneImageInfo((ImageInfo
*) NULL
);
163 strncpy(image_info
->filename
, filename
, MaxTextExtent
);
164 mi
= ReadImage(image_info
, &exception
);
165 if (exception
.severity
!= UndefinedException
) {
166 fprintf(stderr
, "\n\n");
167 CatchException(&exception
);
168 fprintf(stderr
, "\n");
170 if (mi
== (Image
*) NULL
)
173 im
= ale_new_image(accel::context(),
174 (bayer
== IMAGE_BAYER_NONE
) ? ALE_IMAGE_RGB
: ALE_IMAGE_Y
,
175 (image_info
->depth
<= 8) ? ALE_TYPE_UINT_8
:
176 ((image_info
->depth
<= 16) ? ALE_TYPE_UINT_16
:
177 ((image_info
->depth
<= 32) ? ALE_TYPE_UINT_32
: ALE_TYPE_UINT_64
)));
179 for (i
= 0; i
< mi
->rows
; i
++) {
180 p
= AcquireImagePixels(mi
, 0, i
, mi
->columns
, 1, &exception
);
182 if (exception
.severity
!= UndefinedException
)
183 CatchException(&exception
);
187 for (j
= 0; j
< mi
->columns
; j
++) {
189 Quantum ival
[3] = { p
->red
, p
->green
, p
->blue
};
191 for (int k
= 0; k
< 3; k
++) {
193 if (!ale_has_channel(i
, j
, k
, bayer
))
196 if (image_info
->depth
<= 8) {
197 cl_uchar c
= ival
[k
];
198 fwrite(&c
, sizeof(cl_uchar
), 1, converted_f
);
199 } else if (image_info
->depth
<= 16) {
200 cl_ushort c
= ival
[k
];
201 fwrite(&c
, sizeof(cl_ushort
), 1, converted_f
);
202 } else if (image_info
->depth
<= 32) {
204 fwrite(&c
, sizeof(cl_uint
), 1, converted_f
);
205 } else if (image_info
->depth
<= 64) {
206 cl_ulong c
= ival
[k
];
207 fwrite(&c
, sizeof(cl_ulong
), 1, converted_f
);
209 fprintf(stderr
, "error: unable to handle image depth %u\n", (unsigned int) image_info
->depth
);
218 ale_image_set_file_static(im
, mi
->columns
, mi
->rows
, converted_f
, 0, ppm_void_file_close
, converted_f
);
221 DestroyImageInfo(image_info
);
232 * Read an image from a file
234 static ale_image
read_image(const char *filename
, exposure
*exp
, const char *name
= "file",
235 unsigned int bayer
= IMAGE_BAYER_DEFAULT
, int init_reference_gain
= 0) {
238 if (bayer
== IMAGE_BAYER_DEFAULT
)
239 bayer
= bayer_default
;
241 if (is_eppm(filename
)) {
242 result
= read_ppm(filename
, exp
, bayer
, init_reference_gain
);
246 result
= read_image_im(filename
, exp
, name
, bayer
, init_reference_gain
);
248 result
= read_ppm(filename
, exp
, bayer
);
257 * Handle FILE_COUNT input files with names in array FILENAMES and
258 * output file OUTPUT_FILENAME. FILENAMES should be an array of char *
259 * that is never freed. OUTPUT_FILENAME should be a char * that is
262 * INPUT_EXPOSURE should be an array of FILE_COUNT exposure objects
263 * that is never freed. OUTPUT_EXPOSURE should be an exposure * that
266 static void init(unsigned int _file_count
, const char **_filenames
,
267 const char *_output_filename
, exposure
**_input_exposure
,
268 exposure
*_output_exposure
){
269 assert (_file_count
> 0);
273 filenames
= _filenames
;
274 file_count
= _file_count
;
275 output_filename
= _output_filename
;
276 input_exposure
= _input_exposure
;
277 output_exposure
= _output_exposure
;
279 images
= (ale_image
*)malloc(file_count
* sizeof(ale_image
));
280 bayer_specific
= (unsigned int *)malloc(file_count
* sizeof(unsigned int));
281 files_open
= (int *)calloc(file_count
, sizeof(int));
284 assert (bayer_specific
);
287 if (!images
|| !files_open
|| !bayer_specific
) {
288 fprintf(stderr
, "Unable to allocate memory for images.\n");
292 for (unsigned int i
= 0; i
< file_count
; i
++)
293 bayer_specific
[i
] = IMAGE_BAYER_DEFAULT
;
295 ui::get()->identify_output(output_filename
);
298 static void ppm_plain() {
302 static void ppm_raw() {
306 static void ppm_auto() {
310 fprintf(stderr
, "\n\n*** Error: --auto flag not supported on this build. ***\n"
311 "*** (Hint: Rebuild with IMAGEMAGICK=1) ***\n\n");
316 static void set_default_bayer(unsigned int b
) {
320 static void set_specific_bayer(unsigned int index
, unsigned int b
) {
321 assert (bayer_specific
);
322 bayer_specific
[index
] = b
;
325 static void depth16() {
330 static void depth8() {
335 static void destroy() {
336 assert (file_count
> 0);
340 static unsigned int count() {
341 assert (file_count
> 0);
345 static const char *name(unsigned int image
) {
346 assert (image
< file_count
);
348 return filenames
[image
];
351 static void def_nn(double _nn
) {
352 nn_defined_radius
= _nn
;
355 static const char *output_name() {
356 assert (file_count
> 0);
357 return output_filename
;
361 * Write an image to a file
363 static void write_image(const char *filename
, ale_image im
, int rezero
= 0, int exp_scale_override
= 0, double gamma
= 0.45) {
364 static int warned
= 0;
367 * Handle ALE-specific magical filenames.
370 if (!strcmp(filename
, "dump:")) {
371 FILE *image_data
= ale_image_retain_file(im
);
373 int format
= ale_image_get_format(im
);
374 int type
= ale_image_get_type(im
);
376 fprintf(stderr
, "Image dump: ");
377 for (unsigned int i
= 0; i
< ale_image_get_height(im
); i
++)
378 for (unsigned int j
= 0; j
< ale_image_get_width(im
); j
++) {
379 fprintf(stderr
, "(%d, %d): ", i
, j
);
381 fprintf(stderr
, "[");
383 for (unsigned int k
= 0; k
< ale_image_get_depth(im
); k
++) {
386 fprintf(stderr
, " ");
391 assert(fread(&data
, sizeof(cl_uchar
), 1, image_data
));
392 fprintf(stderr
, "%u", (unsigned int) data
);
396 assert(fread(&data
, sizeof(cl_ushort
), 1, image_data
));
397 fprintf(stderr
, "%u", (unsigned int) data
);
401 assert(fread(&data
, sizeof(cl_uint
), 1, image_data
));
402 fprintf(stderr
, "%u", (unsigned int) data
);
406 assert(fread(&data
, sizeof(cl_ulong
), 1, image_data
));
407 fprintf(stderr
, "%llu", data
);
411 assert(fread(&data
, sizeof(cl_float
), 1, image_data
));
412 fprintf(stderr
, "%f", (double) data
);
416 assert(fread(&data
, sizeof(double), 1, image_data
));
417 fprintf(stderr
, "%f", data
);
421 fprintf(stderr
, "] ");
423 fprintf(stderr
, "\n");
425 ale_image_release_file(im
, image_data
);
432 * If necessary, adjust mcv to match library limits.
435 if (MaxRGB
< 65535 && mcv
== 65535) {
436 fprintf(stderr
, "\n\n*** Warning: " MagickPackageName
" has not been compiled with 16 bit support.\n");
437 fprintf(stderr
, "*** Writing output using 8 bits per channel.\n");
438 fprintf(stderr
, "*** \n");
439 fprintf(stderr
, "*** (To silence this warning, specify option --8bpc)\n\n\n");
445 * We currently can't handle mcv greater than 65535 here.
448 assert(mcv
<= 65535);
451 fprintf(stderr
, "error: I don't know how to produce greater than 16-bit output.\n");
457 * Automatic exposure adjustment (don't blow out highlights)
460 ale_real minval
= (rezero
? (ale_real
) ale_image_minval(im
) : (ale_real
) 0);
463 pixel
minval_pixel(minval
, minval
, minval
);
466 if (exposure_scale
|| exp_scale_override
) {
467 ale_real new_maxval
= ale_image_maxval(im
);
469 if (new_maxval
> maxval
)
474 * Nearest-neighbor fill.
477 ale_image temp_image
= ale_image_nn_fill(im
, nn_defined_radius
);
480 * Unlinearize and quantize
483 ale_image quantized_image
= ale_new_image(accel::context(),
484 ale_image_get_format(temp_image
), (mcv
> 255) ?
485 ALE_TYPE_UINT_16
: ALE_TYPE_UINT_8
);
487 ale_image_map_1(quantized_image
, temp_image
, "\
488 SET_PIXEL(p, CLAMP(pow((GET_PIXEL(0, p) - (PIXEL(1, 1, 1) * %0f)) / (%1f - %0f), %2f)) * %3f)",
489 minval
, maxval
, gamma
, (double) ((mcv
> 255) ? 65535 : 255));
491 ale_image_release(temp_image
);
496 * Patterned after http://www.imagemagick.org/www/api.html
497 * and http://www.imagemagick.org/www/smile.c
500 ExceptionInfo exception
;
502 ImageInfo
*image_info
;
507 GetExceptionInfo(&exception
);
508 image_info
= CloneImageInfo((ImageInfo
*) NULL
);
509 strncpy(image_info
->filename
, filename
, MaxTextExtent
);
511 mi
= AllocateImage(image_info
);
512 if (mi
== (Image
*) NULL
)
513 MagickError(ResourceLimitError
,
514 "Unable to display image", "MemoryAllocationFailed");
516 mi
->columns
= ale_image_get_width(im
);
517 mi
->rows
= ale_image_get_height(im
);
520 * Set the output image depth
529 * Set compression type
533 mi
->compression
= NoCompression
;
534 image_info
->compression
= NoCompression
;
535 strncpy(mi
->magick
, "PNM", MaxTextExtent
);
536 strncpy(image_info
->magick
, "PNM", MaxTextExtent
);
537 } else if (ppm_type
== 1) {
538 strncpy(mi
->magick
, "PNM", MaxTextExtent
);
539 strncpy(image_info
->magick
, "PNM", MaxTextExtent
);
546 FILE *image_data
= ale_image_retain_file(quantized_image
);
548 for (i
= 0; i
< mi
->rows
; i
++) {
549 p
= SetImagePixels(mi
, 0, i
, mi
->columns
, 1);
553 for (j
= 0; j
< mi
->columns
; j
++) {
557 for (int k
= 0; k
< 3; k
++) {
559 val
[k
] = fgetc(image_data
);
561 assert(fread(&(val
[k
]), sizeof(cl_ushort
), 1, image_data
));
565 p
->red
= (Quantum
) val
[0];
566 p
->green
= (Quantum
) val
[1];
567 p
->blue
= (Quantum
) val
[2];
571 if (!SyncImagePixels(mi
))
575 ale_image_release_file(quantized_image
, image_data
);
577 if (!WriteImage(image_info
, mi
)) {
580 * Perhaps file type was unknown? Set to PNM by default.
583 strncpy(mi
->magick
, "PNM", MaxTextExtent
);
584 strncpy(image_info
->magick
, "PNM", MaxTextExtent
);
586 if (!WriteImage(image_info
, mi
)) {
587 fprintf(stderr
, "\n\n");
588 CatchException(&mi
->exception
);
589 fprintf(stderr
, "\n");
595 DestroyImageInfo(image_info
);
597 write_ppm(filename
, quantized_image
, mcv
, ppm_type
== 2);
600 ale_image_release(quantized_image
);
605 static void output(const image
*i
) {
606 assert (file_count
> 0);
607 write_image(output_name(), i
, output_exposure
);
610 static void vise_write(const char *p
, const char *s
, const image
*i
) {
611 static int count
= 0;
612 int length
= strlen(p
) + strlen(s
) + 8;
613 char *output_string
= (char *) malloc(length
* sizeof(char));
615 snprintf(output_string
, length
, "%s%08d%s", p
, count
, s
);
617 write_image(output_string
, i
, output_exposure
);
622 static exposure
&exp(int n
) {
623 return *input_exposure
[n
];
626 static const exposure
&const_exp(int n
) {
627 return *input_exposure
[n
];
630 static exposure
&exp() {
631 return *output_exposure
;
634 static void exp_scale() {
638 static void exp_noscale() {
642 static const exposure
&const_exp() {
643 return *output_exposure
;
646 static const unsigned int bayer(unsigned int n
) {
647 if (bayer_specific
[n
] == IMAGE_BAYER_DEFAULT
)
648 return bayer_default
;
650 return bayer_specific
[n
];
653 static const ale_image
open_simple(unsigned int n
) {
654 assert (n
< file_count
);
656 return read_image(filenames
[n
], input_exposure
[n
], "file", bayer(n
), (n
== 0));
659 static const ale_image
open(unsigned int n
) {
660 assert (n
< file_count
);
661 assert (!files_open
[n
]);
665 if (latest_close_num
>= 0 && n
== (unsigned int) latest_close_num
) {
666 latest_close_num
= -1;
673 ui::get()->loading_file();
674 ale_image i
= read_image(filenames
[n
], input_exposure
[n
], "file", bayer(n
), (n
== 0));
681 static void open_all() {
682 for (unsigned int n
= 0; n
< file_count
; n
++)
686 static ale_image
get_open(unsigned int n
) {
687 assert (files_open
[n
]);
693 * XXX: as far as I can tell, 'copy' is currently always used
694 * as a kind of 'retain', so that calls to this can probably be
695 * replaced by calls to an appropriate retain method.
698 static ale_image
copy(unsigned int n
, const char *name
) {
699 assert (n
< file_count
);
702 return images
[n
]->clone(name
);
704 image
*i
= read_image(filenames
[n
], input_exposure
[n
], name
, bayer(n
), (n
== 0));
712 * This method should be replaced by ale_sequence_release_image.
715 static void close(unsigned int image
) {
716 assert (image
< file_count
);
717 assert (files_open
[image
]);
719 files_open
[image
] = 0;
721 if (image
< cache_count
)
724 if (image
== cache_count
) {
725 double image_size
= ((double) images
[image
]->storage_size()) / pow(2, 20);
727 if (image_size
+ cache_size
< cache_size_max
) {
728 cache_size
+= image_size
;
730 ui::get()->cache(cache_size
, cache_size_max
);
733 ui::get()->cache_status(0);
737 if (latest_close_num
>= 0)
738 delete images
[latest_close_num
];
740 latest_close_num
= image
;
743 static void close_all() {
744 for (unsigned int n
= 0; n
< file_count
; n
++)