ROPO
Loading...
Searching...
No Matches
fmi_image.c
1
23/*#include <stdio.h> */
24#include <math.h>
25#include <stdlib.h>
26#include "fmi_image.h"
27#include "fmi_util.h"
28#include "rave_alloc.h"
29#include "rave_debug.h"
30/*img->array=NULL;*/
31
32char FmiImageFormatExtension[7][4]={
33 "xxx",
34 "pbm",
35 "pgm",
36 "ppm",
37 "pbm",
38 "pgm",
39 "ppm"
40};
41
42int FMI_IMAGE_COMMENT=YES;
43
44/*
45 void int_to_iris_rgb(int dbz,int *r,int *g,int *b){
46 *r=128.0+127.0*pseudo_sigmoi(0.05,dbz-96.0);
47 *g=255.0*pseudo_gauss(80.0,dbz-80.0);
48 *b=255.0*pseudo_gauss(24.0,dbz-48.0);
49 *r=pseudo_sigmoid(0.1,*r)*(*r);
50 *g=pseudo_sigmoid(0.1,*g)*(*g);
51 *b=pseudo_sigmoid(0.1,*b)*(*b);
52 }
53*/
54
56new_image(int sweep_count)
57{
58 FmiImage * result=NULL;
59 int i=0;
60
61 result = (FmiImage *)RAVE_MALLOC(sizeof(FmiImage) * sweep_count);
62 for(i=0; i<sweep_count; i++) {
63 result[i].heights=NULL;
64 result[i].array=NULL;
65 result[i].original=NULL;
66 result[i].original_nodata=255.0;
67 result[i].original_undetect=0.0;
68 result[i].original_gain=0.5;
69 result[i].original_offset=-32.0;
70 result[i].original_type = RaveDataType_UNDEFINED;
71 result[i].elevation_angle=0.0;
72 result[i].channels=0;
73 result[i].bin_depth=0.0;
74 result[i].type=NULL_IMAGE;
75 }
76 reset_image(result);
77 return result;
78}
79
80/*
81int max_value;
82
83*/
84
85void init_new_image(FmiImage* img) {
86 img->type = NULL_IMAGE;
87 img->format = UNDEFINED;
88 img->sweep_count = 0;
89 img->heights = NULL;
90 img->array = NULL;
91 img->original_type = RaveDataType_UNDEFINED;
92 img->original_nodata=255.0;
93 img->original_undetect=0.0;
94 img->original_gain=0.5;
95 img->original_offset=-32.0;
96 img->original = NULL;
97 img->elevation_angle = 0.0;
98 img->channels = 0;
99 img->bin_depth = 0;
100 img->max_value = 0;
101 img->width = 0;
102 img->height = 0;
103 img->volume = 0;
104 img->area = 0;
105 img->coord_overflow_handler_x = ZERO;
106 img->coord_overflow_handler_y = ZERO;
107 img->comment_string[0] = '\0';
108}
109
110int initialize_image(FmiImage *img){
111 img->type=TRUE_IMAGE;
112 img->area=img->width*img->height;
113 img->volume=img->area*img->channels;
114 img->array=(Byte *) RAVE_MALLOC(img->volume);
115 img->original=(double*) RAVE_MALLOC(img->volume*sizeof(double));
116 img->coord_overflow_handler_x=BORDER;
117 img->coord_overflow_handler_y=BORDER;
118 img->max_value=255;
119 img->comment_string[0]='\0';
120 return 1;
121}
122
123int initialize_horz_stripe(FmiImage *img,int width){
124 img->width=width;
125 img->height=1;
126 img->channels=1;
127 fmi_debug(2,"initialize_horz_image");
128 initialize_image(img);
129 img->coord_overflow_handler_y=TILE;
130 return 1;
131}
132
133int initialize_vert_stripe(FmiImage *img,int height){
134 img->width=1;
135 img->height=height;
136 img->channels=1;
137 fmi_debug(2,"initialize_horz_image");
138 initialize_image(img);
139 img->coord_overflow_handler_x=TILE;
140 return 1;
141}
142
143int link_image_segment(FmiImage *source,int start_row,int rows,FmiImage *linked){
144 /* int a=rows*source->width; */
145
146 fmi_debug(3,"link_image_segment");
147
148 if (start_row+rows > source->height*source->channels)
149 fmi_error("link_image_segment: segment overflow");
150
151 if (linked==source)
152 fmi_error("link_image_segment: dont-like self-linking");
153
154 if (linked->type==TRUE_IMAGE)
155 fmi_debug(3,"WARNING: true image to link image without reset (free)");
156
157 copy_image_properties(source,linked);
158 linked->channels=1;
159 linked->height=rows;
160 linked->area=linked->width*linked->height; /* safety */
161 linked->volume=linked->area*linked->channels;
162 linked->type=LINK_IMAGE;
163 linked->array=&(source->array[start_row*source->width]);
164 linked->heights=NULL;
165 if (FMI_DEBUG(2))
166 image_info(linked);
167 return 1;
168}
169
170void link_image_channel(FmiImage *source,int channel,FmiImage *linked){
171 link_image_segment(source,channel*source->height,1*source->height,linked);
172}
173
174void split_to_link_array(FmiImage *source,int segments,FmiImage *target){
175 int hs=0,ht,k;
176 if (segments==0)
177 fmi_error("split_to_link_array: zero channels?");
178 for (k=0;k<segments;k++){
179 ht = source->heights[k] * source->channels;
180 link_image_segment(source,hs,ht,&target[k]);
181 hs += ht;
182 }
183 target->sweep_count = segments;
184}
185
186void split_to_channels(FmiImage *target,int channels){
187 int hs;
188 if (channels<=0)
189 fmi_error("split_to_channels: zero channels?");
190 hs=(target->height*target->channels);
191 if (hs%channels!=0)
192 fmi_error("split_to_channels: height not divisible by #channels ");
193 else{
194 target->channels=channels;
195 target->height=hs/channels;
196 target->area=target->height*target->width;
197 }
198 fprintf(stderr,"split_to_channels: %d channels\n",channels);
199}
200
201
202
203/* channel-division independent */
204void concatenate_images_vert(FmiImage *source,int count,FmiImage *target){
205 register int i,j,k;
206 /* START FROM FIRST */
207 fmi_debug(3,"concat base");
208 copy_image_properties(source,target);
209 target->sweep_count = count;
210 target->heights = (int *)RAVE_MALLOC(sizeof(int) * count);
211 if (FMI_DEBUG(3)) image_info(target);
212 /* ADD THE REST */
213 for (k=1;k<count;k++){
214 if (FMI_DEBUG(3)) fprintf(stderr,"concatenating #%d\n",k);
215 if (FMI_DEBUG(3)) image_info(&source[k]);
216 if (source[k].width!=target->width)
217 fmi_error("concatenate_images: not implemented for variable width");
218 if (source[k].channels!=target->channels)
219 fmi_error("concatenate_images: not implemented for variable channel counts");
220 target->height+=source[k].height;
221 target->heights[k-1] = source[k].height;
222 }
223 fmi_debug(3,"to be concat");
224 if (FMI_DEBUG(3)) image_info(target);
225 initialize_image(target);
226 if (FMI_DEBUG(3)) image_info(target);
227 /* CONCATENATE */
228 j=0;
229 for (k=0;k<count;k++){
230 for (i=0;i<source[k].volume;i++)
231 target->array[j+i]=source[k].array[i];
232 j+=source[k].volume;
233 }
234}
235
236/* NO IMAGE ARRAY SIZE CONTROL */
237/* SEGMENTATION FAULT RISK */
238/*
239 int reclaim_channels(FmiImage *img,int channels){
240 img->channels=channels;
241 img->volume=img->area*img->channels;
242 return 1;
243 }
244*/
245
246int copy_image_properties(FmiImage *sample,FmiImage *target){
247 target->width = sample->width;
248 target->height = sample->height;
249 target->channels = sample->channels;
250 target->max_value = sample->max_value;
251 target->sweep_count = sample->sweep_count;
252 target->bin_depth = sample->bin_depth;
253 target->elevation_angle = sample->elevation_angle;
254 target->original_nodata = sample->original_nodata;
255 target->original_undetect = sample->original_undetect;
256 target->original_gain = sample->original_gain;
257 target->original_offset = sample->original_offset;
258 target->original_type = sample->original_type;
259
260 if(sample->heights == NULL)
261 target->heights = NULL;
262 else
263 {
264 target->heights = (int*)RAVE_MALLOC(sample->sweep_count * sizeof(int));
265 memcpy(target->heights, sample->heights, sample->sweep_count * sizeof(int));
266 }
267
268 /* target->format=sample->format; olis ehk� OK */
269 target->coord_overflow_handler_x=sample->coord_overflow_handler_x;
270 target->coord_overflow_handler_y=sample->coord_overflow_handler_y;
271
272 target->area=target->width*target->height;
273 target->volume=target->channels*target->area;
274
275 return 1;
276}
277
278int check_image_properties(FmiImage *sample,FmiImage *target){
279 /*register int h; */
280 if (target->width!=sample->width){
281 /* h=target->coord_overflow_handler_x; */
282 /*if ((h!=WRAP)&&(h!=TILE)){ */
283 fmi_debug(2,"check_image_properties: unequal widths");
284 return 0;
285 /*} */
286 }
287 if (target->height!=sample->height){
288 /* h=target->coord_overflow_handler_y; */
289 /* if ((h!=WRAP)&&(h!=TILE)){ */
290 fmi_debug(2,"check_image_properties: unequal heights");
291 return 0;
292 /*} */
293 }
294 if (target->channels!=sample->channels){
295 fmi_debug(2,"check_image_properties: unequal channel counts");
296 return 0;}
297
298 target->max_value=sample->max_value;
299 target->area=target->width*target->height;
300 target->volume=target->channels*target->area;
301 target->original_nodata = sample->original_nodata;
302 target->original_undetect = sample->original_undetect;
303 target->original_gain = sample->original_gain;
304 target->original_offset = sample->original_offset;
305 target->original_type = sample->original_type;
306 return 1;
307}
308
309int canonize_image(FmiImage *sample,FmiImage *target){
310
311 fmi_debug(2,"canonize_image?");
312 if (!check_image_properties(sample,target)){
313 fmi_debug(2,"canonize_image: YES");
314 copy_image_properties(sample, target);
315 initialize_image(target);
316 }
317 fmi_debug(2,"canonize_image END");
318 return 1;
319}
320
321void reset_image(FmiImage *image){
322 switch (image->type){
323 case TRUE_IMAGE:
324 RAVE_FREE(image->array);
325 RAVE_FREE(image->original);
326 case NULL_IMAGE:
327 case LINK_IMAGE:
328 image->width=0;
329 image->height=0;
330 image->channels=0;
331 image->max_value=0;
332 image->sweep_count=0;
333 image->bin_depth=0.0;
334 image->elevation_angle=0.0;
335 image->original_type = RaveDataType_UNDEFINED;
336 image->original_nodata = 255.0;
337 image->original_undetect = 0.0;
338 image->original_gain = 0.5;
339 image->original_offset = -32.0;
340 RAVE_FREE(image->array);
341 RAVE_FREE(image->original);
342 RAVE_FREE(image->heights);
343 image->type=NULL_IMAGE;
344 return;
345 default:
346 fprintf(stderr," IMAGE TYPE:%d\n",image->type);
347 fmi_error("reset_image: unknown image type");
348 }
349}
350
351int legal_coords(FmiImage *img,int x,int y){
352 if (x<0) return 0;
353 if (y<0) return 0;
354 if (x>=img->width) return 0;
355 if (y>=img->height) return 0;
356 return 1;
357}
358
359void handle_coord_overflow(FmiImage *img,int *x,int *y){
360 /* WRAP = quick TILE "ONCE" */
361 if (*x<0)
362 switch (img->coord_overflow_handler_x){
363 case MIRROR: *x=-*x; break;
364 case WRAP : *x=*x+img->width; break;
365 case TILE : *x=*x%img->width; break;
366 case BORDER: *x=0; break;
367 default: fmi_error("get: coord x underflow");}
368 if (*x>=img->width)
369 switch (img->coord_overflow_handler_x){
370 case MIRROR: *x=2*img->width-*x; break;
371 case WRAP : *x=*x-img->width; break;
372 case TILE : *x=*x%img->width; break;
373 case BORDER: *x=img->width-1; break;
374 default: fmi_error("get: coord x overflow");}
375 if (*y<0)
376 switch (img->coord_overflow_handler_y){
377 case MIRROR: *y=-*y; break;
378 case WRAP : *y=*y+img->height; break;
379 case TILE : *y=*y%img->height; break;
380 case BORDER: *y=0; break;
381 default: fmi_error("get: coord y underflow");}
382 if (*y>=img->height)
383 switch (img->coord_overflow_handler_y){
384 case MIRROR: *y=2*img->height-*y; break;
385 case WRAP : *y=*y-img->height; break;
386 case TILE : *y=*y%img->height; break;
387 case BORDER: *y=img->height-1; break;
388 default: fmi_error("get: coord y overflow");}
389}
390
391Byte get_pixel_direct(FmiImage *img,int address){
392 return img->array[address];
393}
394
395void put_pixel(FmiImage *img,int x,int y,int channel,Byte c){
396 handle_coord_overflow(img,&x,&y);
397 img->array[channel*img->area + y*img->width + x]=c;
398 /* return 1; */
399}
400
401void put_pixel_orig(FmiImage *img,int x,int y,int channel,double c){
402 handle_coord_overflow(img,&x,&y);
403 img->original[channel*img->area + y*img->width + x]=c;
404 /* return 1; */
405}
406
407void put_pixel_direct(FmiImage *img,int address,Byte c){
408 img->array[address]=c;
409}
410
411void put_pixel_direct_inc(FmiImage *img,int address){
412 if (img->array[address]<255)
413 ++(img->array[address]);
414}
415
416void put_pixel_or(FmiImage *img,int x,int y,int channel,Byte c){
417 static Byte *location;
418 handle_coord_overflow(img,&x,&y);
419 location=&(img->array[channel*img->area + y*img->width + x]);
420 *location=*location|c;
421}
422
423void put_pixel_and(FmiImage *img,int x,int y,int channel,Byte c){
424 static Byte *location;
425 handle_coord_overflow(img,&x,&y);
426 location=&(img->array[channel*img->area + y*img->width + x]);
427 *location=*location&c;
428}
429
430void put_pixel_min(FmiImage *img,int x,int y,int channel,Byte c){
431 static Byte *location;
432 handle_coord_overflow(img,&x,&y);
433 location=&(img->array[channel*img->area + y*img->width + x]);
434 if (c<*location) *location=c;
435}
436
437void put_pixel_max(FmiImage *img,int x,int y,int channel,Byte c){
438 static Byte *location;
439 handle_coord_overflow(img,&x,&y);
440 location=&(img->array[channel*img->area + y*img->width + x]);
441 if (c>*location) *location=c;
442}
443
444Byte get_pixel(FmiImage *img,int x,int y,int channel){
445 /* return (img->array[y*img->width+x][channel]); */
446 handle_coord_overflow(img,&x,&y);
447 return (img->array[channel*img->area + y*img->width + x]);
448}
449
450double get_pixel_orig(FmiImage *img,int x,int y,int channel){
451 /* return (img->array[y*img->width+x][channel]); */
452 handle_coord_overflow(img,&x,&y);
453 return (img->original[channel*img->area + y*img->width + x]);
454}
455
456void fill_image(FmiImage *img,Byte c){
457 register int i;
458 img->area=img->width*img->height;
459 img->volume=img->area*img->channels;
460 for (i=0;i<img->volume;i++)
461 img->array[i]=c;
462}
463
464void fill_image_orig(FmiImage *img,double c){
465 register int i;
466 img->area=img->width*img->height;
467 img->volume=img->area*img->channels;
468 for (i=0;i<img->volume;i++)
469 img->original[i]=c;
470}
471
472
473void image_fill_random(FmiImage *img,Byte mean,Byte amplitude){
474 register int i;
475 img->area=img->width*img->height;
476 img->volume=img->area*img->channels;
477 for (i=0;i<img->volume;i++)
478 img->array[i]=mean+(amplitude*(rand()&255))/256;
479}
480
481void invert_image(FmiImage *img){
482 register int i;
483 img->area=img->width*img->height;
484 img->volume=img->area*img->channels;
485 for (i=0;i<img->volume;i++)
486 img->array[i]=img->array[i]^255;
487}
488
489void limit_image_intensities(FmiImage *img,Byte min,Byte max){
490 register int i;
491 img->area=img->width*img->height;
492 img->volume=img->area*img->channels;
493 for (i=0;i<img->volume;i++){
494 if (img->array[i]<min) img->array[i]=min;
495 else if (img->array[i]>max) img->array[i]=max;}
496}
497
498void translate_intensity(FmiImage *img,Byte from,Byte to){
499 register int i;
500 img->area=img->width*img->height;
501 img->volume=img->area*img->channels;
502 for (i=0;i<img->volume;i++)
503 if (img->array[i]==from) img->array[i]=to;
504}
505
506
507void add_image(FmiImage *source,FmiImage *source2,FmiImage *target){
508 register int i;
509 int sum;
510 if (check_image_properties(source,source2)==0)
511 fmi_error("subtract_image: incompatible images");
512 canonize_image(source,target);
513 for (i=0;i<target->volume;i++){
514 sum=source->array[i]+source2->array[i];
515 target->array[i]=(sum<=254 ? sum : 254);}
516}
517
518void subtract_image(FmiImage *source,FmiImage *source2,FmiImage *target){
519 register int i;
520 if (check_image_properties(source,source2)==0)
521 fmi_error("subtract_image: incompatible images");
522 canonize_image(source,target);
523 for (i=0;i<target->volume;i++)
524 target->array[i]=(source->array[i]>source2->array[i]) ? source->array[i]-source2->array[i] : 0;
525}
526
527void subtract_image128(FmiImage *source,FmiImage *source2,FmiImage *target){
528 register int i;
529 /* int sum; */
530 if (check_image_properties(source,source2)==0)
531 fmi_error("subtract_image: incompatible images");
532 canonize_image(source,target);
533 for (i=0;i<target->volume;i++)
534 target->array[i]=(255+source->array[i]-source2->array[i])/2;
535}
536
537
538void average_images(FmiImage *source,FmiImage *source2,FmiImage *target){
539 register int i;
540 int sum;
541 if (check_image_properties(source,source2)==0)
542 fmi_error("subtract_image: incompatible images");
543 canonize_image(source,target);
544 for (i=0;i<target->volume;i++){
545 sum=(source->array[i]+source2->array[i])/2;
546 target->array[i]=(sum<=254 ? sum : 254);}
547}
548
549
550void multiply_image255(FmiImage *source,FmiImage *source2,FmiImage *target){
551 register int i,c;
552 if (check_image_properties(source,source2)==0)
553 fmi_error("multiply_image255: incompatible images");
554 canonize_image(source,target);
555 for (i=0;i<target->volume;i++){
556 c=source->array[i]*source2->array[i]/255;
557 target->array[i]=MIN(c,255);}
558}
559
560void multiply_image255_flex(FmiImage *source,FmiImage *source2,FmiImage *target){
561 register int i,j,c;
562 canonize_image(source,target);
563 for (i=0;i<source->width;i++)
564 for (j=0;j<source->height;j++){
565 c=get_pixel(source,i,j,0)*get_pixel(source2,i,j,0)/255;
566 put_pixel(target,i,j,0,MIN(c,255));
567 }
568}
569
570void multiply_image255_sigmoid(FmiImage *source,FmiImage *source2,FmiImage *target){
571 register int i;
572 const int half_width=128*128;
573 if (check_image_properties(source,source2)==0)
574 fmi_error("multiply_image255_sigmoid: incompatible images");
575 canonize_image(source,target);
576 for (i=0;i<target->volume;i++)
577 target->array[i]=pseudo_sigmoid(half_width,source->array[i]*source2->array[i]);
578}
579
580
581void max_image(FmiImage *source,FmiImage *source2,FmiImage *target){
582 register int i;
583 if (check_image_properties(source,source2)==0)
584 fmi_error("subtract_image: incompatible images");
585 canonize_image(source,target);
586 for (i=0;i<target->volume;i++)
587 target->array[i]=(source->array[i]>source2->array[i]) ? source->array[i] : source2->array[i];
588}
589
590void min_image(FmiImage *source,FmiImage *source2,FmiImage *target){
591 register int i;
592 if (check_image_properties(source,source2)==0)
593 fmi_error("subtract_image: incompatible images");
594 canonize_image(source,target);
595 for (i=0;i<target->volume;i++)
596 target->array[i]=(source->array[i]<source2->array[i]) ? source->array[i] : source2->array[i];
597}
598
599void multiply_image_scalar255(FmiImage *img,int coeff){
600 register int i;
601 int temp;
602 for (i=0;i<img->volume;i++){
603 temp=img->array[i]*coeff/255;
604 img->array[i]=MIN(temp,255);}
605}
606
607void semisigmoid_image(FmiImage *source,int half_width){
608 register int i;
609 for (i=0;i<source->volume;i++)
610 source->array[i]=pseudo_sigmoid(half_width,source->array[i]);
611}
612
613void semisigmoid_image_inv(FmiImage *source,int half_width){
614 register int i;
615 for (i=0;i<source->volume;i++)
616 source->array[i]=255-pseudo_sigmoid(half_width,source->array[i]);
617}
618
619/* slope = half-width */
620void sigmoid_image(FmiImage *source,int threshold,int slope){
621 register int i;
622
623 if (slope>0){
624 for (i=0;i<source->volume;i++)
625 source->array[i]=128+pseudo_sigmoid(slope,source->array[i]-threshold)/2;
626 return;}
627
628 if (slope<0){
629 for (i=0;i<source->volume;i++)
630 source->array[i]=128-pseudo_sigmoid(-slope,source->array[i]-threshold)/2;
631 return;}
632
633 if (slope==0){
634 for (i=0;i<source->volume;i++)
635 source->array[i]=(source->array[i]>threshold)*255;
636 return;}
637
638}
639
640void gaussian_image(FmiImage *source,int mean,int half_width){
641 register int i;
642 for (i=0;i<source->volume;i++)
643 source->array[i]=pseudo_gauss(half_width,source->array[i]-mean);
644}
645
646void copy_image(FmiImage *source,FmiImage *target){
647 register int i;
648 fmi_debug(4," copy_image");
649 canonize_image(source,target);
650 for (i=0;i<source->volume;i++)
651 target->array[i]=source->array[i];
652}
653
654
655void extract_channel(FmiImage *source,int channel,FmiImage *target){
656 register int i,j;
657 fmi_debug(3,__FILE__);
658 fmi_debug(3," extract_channel");
659 fmi_debug(4," extract_channel: initialize");
660 /* fmi_debug(1,__LINE__); */
661 if (channel>=source->channels) fmi_error("extracting nonexistent channel");
662 copy_image_properties(source,target);
663 target->channels=1;
664 initialize_image(target);
665 fmi_debug(4," extract_channel: extraction");
666 for (i=0;i<source->width;i++)
667 for (j=0;j<source->height;j++)
668 put_pixel(target,i,j,0,get_pixel(source,i,j,channel));
669 /* put_pixel(target,i,j,0,85); */
670 /*get_pixel(source,i,j,channel); T�M� SOI */
671 fmi_debug(4," extract_channel: ...extracted");
672}
673
674void write_channel(FmiImage *source,int channel,FmiImage *target){
675 register int i,j;
676 fmi_debug(2,__FILE__);
677 fmi_debug(2," write_channel");
678 /* fmi_debug(1,__LINE__); */
679 if (channel>=target->channels) fmi_error("extracting nonexistent channel");
680 /* copy_image_properties(source,target); */
681 /*target->channels=1; */
682 /*initialize_image(target); */
683 for (i=0;i<source->width;i++)
684 for (j=0;j<source->height;j++)
685 put_pixel(target,i,j,channel,get_pixel(source,i,j,0));
686}
687
688
689void insert(FmiImage *source,FmiImage *target,int i0, int j0){
690 register int i,j,k;
691 fmi_debug(2,"insert");
692 if (source->channels==target->channels)
693 for (k=0;k<source->channels;k++)
694 for (i=0;i<source->width;i++)
695 for (j=0;j<source->height;j++)
696 put_pixel(target,i0+i,j0+j,k,get_pixel(source,i,j,k));
697 else
698 if (source->channels==1)
699 for (k=0;k<target->channels;k++)
700 for (i=0;i<source->width;i++)
701 for (j=0;j<source->height;j++)
702 put_pixel(target,i0+i,j0+j,k,get_pixel(source,i,j,0));
703 else{
704 fprintf(stderr,"channels = %d vs %d",source->channels,target->channels);
705 fmi_error("insert: channel number conflict");}
706}
707
708void compose2x2(FmiImage *source_ul,FmiImage *source_ur,FmiImage *source_ll,FmiImage *source_lr,FmiImage *target){
709 /*register int i,j; */
710 int t1,t2,tw,th;
711
712 fmi_debug(1,"compose2x2");
713 t1=source_ul->width+source_ur->width;
714 t2=source_ll->width+source_lr->width;
715 target->width=MAX(t1,t2);
716 tw=target->width;
717
718 t1=source_ul->height+source_ll->height;
719 t2=source_ur->height+source_lr->height;
720 target->height=MAX(t1,t2);
721 th=target->height;
722
723 target->channels=MAX(source_ul->channels,source_ur->channels);
724 target->channels=MAX(target->channels,source_ll->channels);
725 target->channels=MAX(target->channels,source_lr->channels);
726 initialize_image(target);
727 /* fmi_debug(1,"compose2x2 target:"); */
728 if (FMI_DEBUG(3)) image_info(target);
729 fill_image(target,251);
730
731 insert(source_ul,target,0,0);
732 insert(source_ur,target,tw-source_ur->width,0);
733 insert(source_ll,target,0,th-source_ll->height);
734 insert(source_lr,target,tw-source_lr->width,th-source_lr->height);
735}
736
737void compose3x2(FmiImage *source_ul,FmiImage *source_um,FmiImage *source_ur,FmiImage *source_ll,FmiImage *source_lm,FmiImage *source_lr,FmiImage *target){
738 int t1,t2,t3,tw,th;
739
740 fmi_debug(1,"compose2x2");
741 t1=source_ul->width+source_um->width+source_ur->width;
742 t2=source_ll->width+source_lm->width+source_lr->width;
743 target->width=MAX(t1,t2);
744 tw=target->width;
745
746 t1=source_ul->height+source_ll->height;
747 t2=source_um->height+source_lm->height;
748 t3=source_ur->height+source_lr->height;
749 t2=MAX(t1,t2);
750 target->height=MAX(t2,t3);
751 th=target->height;
752
753 target->channels=MAX(source_ul->channels,source_ur->channels);
754 target->channels=MAX(target->channels,source_um->channels);
755 target->channels=MAX(target->channels,source_ll->channels);
756 target->channels=MAX(target->channels,source_lm->channels);
757 target->channels=MAX(target->channels,source_lr->channels);
758 initialize_image(target);
759 fmi_debug(1,"compose3x2 target:");
760 if (FMI_DEBUG(3)) image_info(target);
761 fill_image(target,251);
762
763 insert(source_ul,target,0,0);
764 insert(source_um,target,source_ul->width,0);
765 insert(source_ur,target,tw-source_ur->width,0);
766 insert(source_ll,target,0,th-source_ll->height);
767 insert(source_lm,target,source_ll->width,th-source_lr->height);
768 insert(source_lr,target,tw-source_lr->width,th-source_lr->height);
769}
770
771#define STRLENGTH 256
772
773/*
774 FmiImageFormat detect_image_format_by_extension(char *filename){
775 return PPM_RAW;
776 }
777*/
778
779FmiImageFormat process_image_header(FmiImage *img,FILE *fp){
780 int c;
781 char str[MAX_COMMENT_LENGTH];
782 /* FmiImageFormat format; */
783 /* DETECT FILE FORMAT FROM MAGIC NUMBER */
784 c=getc(fp);
785 if ((char)c=='P'){
786 c=getc(fp);
787 img->format=(FmiImageFormat)(c-'0');
788 /* if (img->channels==0) */
789 switch (img->format){
790 case PBM_ASC:
791 case PBM_RAW:
792 case PGM_ASC:
793 case PGM_RAW:
794 img->channels=1;
795 break;
796 case PPM_ASC:
797 case PPM_RAW:
798 img->channels=3;
799 break;
800 default: fmi_error("Not a PNM image");}
801
802 if (FMI_DEBUG(2)) fprintf(stderr,"Image type: P%c (%d)\n",c,img->format);
803
804 /* scan to next line */
805 do
806 c=getc(fp);
807 while ((c==' ')||(c=='\t')||(c=='\n'));
808 ungetc(c,fp);
809
810 /* READ (OPTIONAL) COMMENTS */
811 /* strp=comment_string; */
812 /*l=0; */
813 img->comment_string[0]='\0';
814 while ((c=getc(fp))=='#'){
815 /* getline(str,256,fp);
816 printf(str);
817 */
818 /* fgets(str,MAX_COMMENT_LENGTH-strlen(img->comment_string),fp); */
819 /* strcat(img->comment_string,str); */
820 fgets(str,MAX_COMMENT_LENGTH-1,fp);
821 if (strlen(img->comment_string)+strlen(str)<MAX_COMMENT_LENGTH)
822 strcat(img->comment_string,str);
823 else {
824 fmi_debug(1,"read_image, image comment overflow");
825 if (FMI_DEBUG(2))
826 fprintf(stderr,"%s\n",str);
827 }
828 }
829 /* printf(img->comment_string); */
830 /*printf("channels %d\n",img->channels); */
831 /*printf("%c\n",c); */
832 /* fmi_debug(0,"kaUnimplemented image format"); */
833 ungetc(c,fp);
834 /* fmi_debug(0," ungetc"); */
835
836 /* READ WIDTH, HEIGHT, MAXVAL */
837 fscanf(fp,"%d %d",&(img->width),&(img->height));
838 if ((img->format==PBM_RAW)||(img->format==PBM_ASC))
839 img->max_value=1;
840 else
841 fscanf(fp,"%d",&(img->max_value));
842
843 if (FMI_DEBUG(3)) image_info(img);
844
845 /* scan to next line */
846 do
847 c=getc(fp);
848 while ((c==' ')||(c=='\t')||(c=='\n'));
849 ungetc(c,fp);}
850 else
851 fmi_error("Unimplemented image format");
852
853 return img->format;
854}
855
856
857void read_image(char *filename,FmiImage *img){
858 /*int i,j,k,c; */
859 /*char str[STRLENGTH]; */
860 FmiImageFormat format;
861 FILE *fp;
862
863 if (FMI_DEBUG(2)){
864 fprintf(stderr," reading file: ");fflush(stderr);
865 fprintf(stderr,"%s\n",filename);
866 }
867
868 if (strcmp(filename,"-")==0)
869 fp = stdin;
870 else
871 fp = fopen(filename,"r");
872 if (fp==NULL) fmi_error("read_image: file error");
873
874 format=process_image_header(img,fp);
875 img->format=format;
876 initialize_image(img);
877 switch (format){
878 case PGM_ASC:
879 case PBM_ASC:
880 case PPM_ASC:
881 case PGM_RAW:
882 case PBM_RAW:
883 case PPM_RAW:
884 read_pnm_image(fp,img,format);
885 break;
886 default:
887 fmi_error("read_image: unimplemented image format");}
888}
889
890void read_pnm_image(FILE *fp,FmiImage *img,FmiImageFormat format){
891 register int i,j,k;
892 Byte c;
893 int l;
894 switch (format){
895 case PBM_RAW:
896 for (j=0;j<img->height;j++){
897 c=getc(fp);
898 k=128;
899 for (i=0;i<img->width;i++){
900 if (k<1){
901 k=128;
902 c=getc(fp);}
903 put_pixel(img,i,j,0,((c&k)>0)?1:254);
904 /* put_pixel(img,i,j,0,(i&j>0)?55:22); */
905 /* put_pixel(img,i,j,0,(i&j>0)?55:22); */
906 k=k>>1;}
907 }
908 break;
909 case PGM_RAW:
910 for (j=0;j<img->height;j++)
911 for (i=0;i<img->width;i++)
912 put_pixel(img,i,j,0,getc(fp));
913 break;
914 case PGM_ASC:
915 for (j=0;j<img->height;j++)
916 for (i=0;i<img->width;i++){
917 fscanf(fp,"%d",&l);
918 /*printf("%d\n",l); */
919 put_pixel(img,i,j,0,(Byte)l);
920 }
921 break;
922 case PPM_RAW:
923 for (j=0;j<img->height;j++)
924 for (i=0;i<img->width;i++)
925 for (k=0;k<3;k++){
926 put_pixel(img,i,j,k,getc(fp));
927 }
928 break;
929 case PPM_ASC:
930 for (j=0;j<img->height;j++)
931 for (i=0;i<img->width;i++)
932 for (k=0;k<3;k++){
933 fscanf(fp,"%d",&l);
934 /*printf("%d\n",l); */
935 put_pixel(img,i,j,0,(Byte)k);
936 }
937 break;
938 default:
939 fmi_error("Error: unimplemented image file type");}
940 fclose(fp);
941}
942
943void write_image(char *filename,FmiImage *img,FmiImageFormat format){
944 char *actual_filename;
945 FILE *fp;
946 fmi_debug(1,"write_image: ");
947 fmi_debug(2,filename);
948 /* if (strcmp(filename,"-")==0) */
949 /* fp = stderr;...? */
950
951 if (file_extension(filename)!=NULL)
952 actual_filename=filename;
953 else {
954 actual_filename=(char *)RAVE_MALLOC(strlen(filename)+5);
955 strcpy(actual_filename,filename);
956 strcat(actual_filename,".");
957 strncat(actual_filename,FmiImageFormatExtension[format],4);
958 }
959 fmi_debug(1,actual_filename);
960 fp = fopen(actual_filename,"w");
961 if (fp){
962 if ((format>=PGM_ASC)&&(format<=PPM_RAW))
963 write_pnm_image(fp,img,format);
964 else
965 fmi_error("Unsupported image format.");
966 fclose(fp);
967 fmi_debug(2,"write_image: ok");
968 }
969 else
970 fmi_error("Failed opening file for writing.");
971 RAVE_FREE(actual_filename); /* segmentation fault? UUSI! */
972}
973
974void dump_comments(FILE *fp,char *comment,char *begin_code,char *end_code,int line_length){
975 int i,l,len;
976 char c;
977 if (comment==NULL)
978 return;
979 len=strlen(comment);
980 l=0;
981 for (i=0;i<=len;i++){
982 if (l==0)
983 fprintf(fp, "%s", begin_code);
984 c=comment[i];
985 if (l==line_length-1){
986 fprintf(fp,"%c\\%s",c,end_code);
987 l=0;}
988 else
989 if ((c=='\n')||(i==len)){
990 /* if ((l==line_length-1)||(i==len-1)){ */
991 fprintf(fp, "%s", end_code);
992 l=0;}
993 else {
994 fputc(c,fp);
995 l++;}
996 }
997}
998
999void write_pnm_image(FILE *fp,FmiImage *img,FmiImageFormat format){
1000 register int i,j,k;
1001 unsigned char c;
1002 /* MAGIC NUMBER, see man pnm */
1003 fprintf(fp,"P%d\n",format);
1004
1005 /* COMMENTS */
1006 trchr(fmi_util_comment,'\\','\n');
1007 dump_comments(fp,fmi_util_comment, "# ","\n",1023);
1008 if (strlen(img->comment_string)>0)
1009 dump_comments(fp,img->comment_string,"# [","]\n",1023);
1010 dump_comments(fp,fmi_util_command_line, "# ","\n",1023);
1011 if (FMI_IMAGE_COMMENT)
1012 /* fprintf(fp,"# CREATOR: %s (c) Markus.Peura@fmi.fi\n",FMI_IMAGE_VER); */
1013 fprintf(fp,"# CREATOR: %s\n",FMI_IMAGE_VER);
1014 /* if (fmi_util_command_line[0]!='\0') */
1015 /* fprintf(fp,"# %s\n",fmi_util_command_line); */
1016
1017
1018 /* IMAGE DIMENSIONS */
1019 fprintf(fp,"%d %d\n",img->width,img->height);
1020 fprintf(fp,"%d\n",img->max_value);
1021
1022 switch (format){
1023 case PBM_RAW:
1024 if (img->channels!=1)
1025 fmi_error("write_pnm_image: PBM implies 1 channel");
1026 for (j=0;j<img->height;j++){
1027 c=0;
1028 k=128;
1029 for (i=0;i<img->width;i++){
1030 c=(c|(((get_pixel(img,i,j,0)&128)==0)?0:k));
1031 if (k==1){
1032 fputc(c,fp);
1033 c=0;
1034 k=128;}
1035 k=k>>1;}
1036 }
1037 break;
1038 case PGM_RAW:
1039 if (img->channels!=1)
1040 fmi_error("write_pnm_image: PGM implies 1 channel");
1041 for (j=0;j<img->height;j++)
1042 for (i=0;i<img->width;i++)
1043 fputc(get_pixel(img,i,j,0),fp);
1044 break;
1045 case PPM_RAW:
1046 if (img->channels!=3)
1047 fmi_error("write_pnm_image: PPM implies 3 channels");
1048 for (j=0;j<img->height;j++)
1049 for (i=0;i<img->width;i++)
1050 for (k=0;k<3;k++)
1051 fputc(get_pixel(img,i,j,k),fp);
1052 break;
1053 default:
1054 break;
1055 }
1056
1057}
1058
1059
1060void image_info(FmiImage *img){
1061 if (FMI_DEBUG(1)) {
1062 fprintf(stderr," type: ");
1063 switch (img->type){
1064 case NULL_IMAGE: fprintf(stderr,"NULL_IMAGE\n"); break;
1065 case TRUE_IMAGE: fprintf(stderr,"TRUE_IMAGE\n"); break;
1066 case LINK_IMAGE: fprintf(stderr,"LINK_IMAGE\n"); break;
1067 }
1068 fprintf(stderr," channels: %d\n",img->channels);
1069 fprintf(stderr," width: %d\n",img->width);
1070 fprintf(stderr," height: %d\n",img->height);
1071 fprintf(stderr," area: %d\n",img->area);
1072 fprintf(stderr," volume: %d\n",img->volume);
1073 fprintf(stderr," max_val: %d\n",img->max_value);
1074 fflush(stderr);
1075 }
1076}
1077
1078
1079
1080
1081/* TRANSFORMS */
1082void expand_channel_to_rgb(FmiImage *source,int channel,FmiImage *target){
1083 register int i,j,k;
1084 Byte c;
1085 fmi_debug(1,"fmi_image.c: expand_channel_to_rgb");
1086
1087 copy_image_properties(source,target);
1088 target->channels=3;
1089 initialize_image(target);
1090
1091 for (i=0;i<source->width;i++)
1092 for (j=0;j<source->height;j++){
1093 c=get_pixel(source,i,j,channel);
1094 for (k=0;k<3;k++)
1095 put_pixel(target,i,j,k,c);
1096 }
1097}
1098
1099void map_channel_to_colors(FmiImage *source,int channel,FmiImage *target,int map_size,ColorMap map){
1100 register int i,j,k;
1101 Byte l,c;
1102 fmi_debug(4,"fmi_image.c: map_channel_to_channels");
1103 if (map_size>255) fmi_error("map_channel_to_channels: too many levels");
1104
1105 /*
1106 for (l=0;l<map_size;l++) {
1107 printf(" %d %d \n",l,map[l][0]); fflush(stdout);}
1108 */
1109
1110 copy_image_properties(source,target);
1111 target->channels=3;
1112 initialize_image(target);
1113
1114 for (i=0;i<source->width;i++)
1115 for (j=0;j<source->height;j++){
1116 c=get_pixel(source,i,j,channel);
1117 for (l=0;l<map_size;l++){
1118 if (map[l][0]>=c){
1119 for (k=0;k<3;k++)
1120 put_pixel(target,i,j,k,map[l][k+1]);
1121 break;}
1122 }
1123 }
1124}
1125
1126void map_channel_to_256_colors(FmiImage *source,int channel,FmiImage *target,ColorMap256 map){
1127 register int i,j,k;
1128 /*Byte l,c; */
1129 fmi_debug(4,"fmi_image.c: map_channel_to_256_colors");
1130
1131 /*
1132 for (l=0;l<map_size;l++) {
1133 printf(" %d %d \n",l,map[l][0]); fflush(stdout);}
1134 */
1135
1136 copy_image_properties(source,target);
1137 target->channels=3;
1138 initialize_image(target);
1139
1140 for (i=0;i<source->width;i++)
1141 for (j=0;j<source->height;j++)
1142 for (k=0;k<3;k++)
1143 put_pixel(target,i,j,k,map[get_pixel(source,i,j,channel)][k]);
1144
1145}
1146
1147void map_256_colors_to_gray(FmiImage *source,FmiImage *target,ColorMap256 map){
1148 register int i,j,l;
1149 Byte r,g,b;
1150 fmi_debug(4,"fmi_image.c: map_256_colors_to_gray");
1151 copy_image_properties(source,target);
1152 target->channels=1;
1153 initialize_image(target);
1154 fill_image(target,0);
1155
1156 for (i=0;i<source->width;i++)
1157 for (j=0;j<source->height;j++){
1158 r=get_pixel(source,i,j,0);
1159 g=get_pixel(source,i,j,1);
1160 b=get_pixel(source,i,j,2);
1161 for (l=0;l<256;l++)
1162 if ((map[l][0]==r)&&(map[l][1]==g)&&(map[l][2]==b)){
1163 put_pixel(target,i,j,0,l);
1164 break;}
1165 }
1166
1167}
1168
1169void read_colormap256(char *filename,ColorMap256 map){
1170 FILE *fp;
1171 int c;
1172 fmi_debug(4,"read_colormap256");
1173 fmi_debug(5,filename);
1174 fp = fopen(filename,"r");
1175 if (!fp) fmi_error("read_colormap256: file read error");
1176
1177 if ((c=getc(fp))=='#'){
1178 do {
1179 /* printf("koe%c",c); */
1180 while ((char)(c=getc(fp))!='\n'){
1181 /* printf("%c",c); */
1182 if (c==EOF) fmi_error("read_colormap256: only comments?");
1183 }
1184 } while ((c=getc(fp))=='#');
1185 /* printf("Comment: %c\n",c); */
1186 /* fflush(stdout); */
1187 ungetc(c,fp);
1188 }
1189
1190 fmi_debug(5,"read_colormap256: colors");
1191 /* MAIN LOOP */
1192 while (fscanf(fp,"%d",&c)!=EOF)
1193 fscanf(fp,"%d %d %d\n",(int*)&map[c][0],(int*)&map[c][1],(int*)&map[c][2]);
1194 fclose(fp);
1195 fmi_debug(5,"read_colormap256 complete");
1196}
1197
1198
1199void to_cart(FmiImage *source,FmiImage *target,Byte outside_fill){
1200 int i,j,k,i0,j0,max_radius,di,dj,radius,a;
1201 target->width=source->width;
1202 target->height=source->width; /* yes, width, -> square */
1203 target->heights=NULL;
1204 target->max_value=255;
1205 target->channels=source->channels;
1206 initialize_image(target);
1207 /* initialize_image(source); */
1208
1209
1210 fmi_debug(3,"to_cart");
1211 /* printf("area %d\n",source->area); fflush(stdout); */
1212
1213 max_radius=target->width;
1214 i0=target->width/2;
1215 j0=target->height/2; /* =i0 */
1216
1217 for (i=0;i<target->width;i++){
1218 di=i-i0;
1219 for (j=0;j<target->height;j++){
1220 dj=j-j0;
1221 radius=2*(int)sqrt((double)(di*di+dj*dj));
1222 for (k=0;k<target->channels;k++){
1223 if (radius<=max_radius){
1224 if (radius>0){
1225 a=180*atan2(di,-dj)/3.14;
1226 if (a<0) a+=360;
1227 put_pixel(target,i,j,k,get_pixel(source,radius,a,k));
1228 /* put_pixel(target,i,j,k,get_pixel(source,radius,a,k)); */
1229 }
1230 } else put_pixel(target,i,j,k,255);
1231 }
1232 }
1233 }
1234}
1235
1236
1237void clear_histogram(Histogram hist){
1238 register int i;
1239 for (i=0;i<HISTOGRAM_SIZE;i++) hist[i]=0;
1240}
1241
1242void calc_histogram(FmiImage *source,Histogram hist){
1243 register int i;
1244 clear_histogram(hist);
1245 for (i=0;i<source->volume;i++)
1246 ++hist[source->array[i]];
1247}
1248
1249void output_histogram(FILE *fp,Histogram hist){
1250 register int i;
1251 for (i=0;i<HISTOGRAM_SIZE;i++)
1252 /* fprintf(fp,"%d\n",hist[i]); */
1253 fprintf(fp,"%d\t%ld\n",i,hist[i]);
1254}
1255
1256void write_histogram(char *filename,Histogram hist){
1257 FILE *fp;
1258 fp=fopen(filename,"w");
1259 output_histogram(fp,hist);
1260 fclose(fp);
1261}
1262
1263void dump_histogram(Histogram hist){
1264 output_histogram(stdout,hist);
1265}
1266
1267
1268
1269/*Mask mask_speck1={3,3,"koke"}; NO ERROR */
1270/*Mask mask_speck1={3,3, {'k','o','k','e','\0'} }; ERROR! */
double * original
Definition fmi_image.h:154