Wrong results of GetImageChannelRange after RotateImag

The MagickWand interface is a new high-level C API interface to ImageMagick core methods. We discourage the use of the core methods and encourage the use of this API instead. Post MagickWand questions, bug reports, and suggestions to this forum.
Post Reply
jrrose
Posts: 11
Joined: 2011-12-05T08:19:02-07:00
Authentication code: 8675308

Wrong results of GetImageChannelRange after RotateImag

Post by jrrose »

If I rotate an image I get values for image depth, minimum and maximum, which I does not expect. I use the following rotate-image_with_getChannelRange.c program:

Code: Select all

#include <stdio.h>
#include <stdlib.h>
#include <wand/MagickWand.h>

print_stat(MagickWand *wand, long long unsigned max_img_val, long long unsigned max_IM_val) {
  double minimum, maximum, mean,stdev;
  const char *fmt=" %-13s  depth=%2lu  min=%8.1lf(%5.3lf)  max=%8.1lf(%5.3lf)  mean=%8.1lf(%5.3lf)  stdev=%8.1lf(%5.3lf)\n";
  fprintf(stderr,"img_depth=%lu\n",MagickGetImageDepth(wand));

#define print_chan(S,c) { \
    MagickGetImageChannelRange(wand,c,&minimum,&maximum); \
    MagickGetImageChannelMean(wand,c,&mean,&stdev);	\
    fprintf(stderr,fmt,S,MagickGetImageChannelDepth(wand,c),\
               max_img_val*minimum/max_IM_val,minimum/max_IM_val, max_img_val*maximum/max_IM_val,maximum/max_IM_val,\
               max_img_val*mean/max_IM_val,mean/max_IM_val, max_img_val*stdev/max_IM_val,stdev/max_IM_val); \
  }
  print_chan("RedChannel:",RedChannel);
  print_chan("GreenChannel:",GreenChannel);
  print_chan("BlueChannel:",BlueChannel);
  print_chan("GrayChannel:",GrayChannel);
}

int main(int argc,char **argv) {

#define ThrowWandException(wand) { \
    description=MagickGetException(wand,&severity);\
    (void) fprintf(stderr,"%s %s %lu %s\n",GetMagickModule(),description); \
    description=(char *) MagickRelinquishMemory(description);\
    exit(-1);\
  }

  char *description;
  ExceptionType severity;
  MagickBooleanType status;

  MagickWandGenesis();
  MagickWand *wand=NewMagickWand();
  status=MagickReadImage(wand,argv[1]);
  if (status == MagickFalse) ThrowWandException(wand);

  size_t IM_quantum_depth;
  const char *IM_quantum_depth_str=GetMagickQuantumDepth(&IM_quantum_depth);
  size_t img_depth=MagickGetImageDepth(wand);
  const char *quantum_format=MagickGetImageProperty(wand,"quantum:format");
  fprintf(stderr,"IM_quantum_depth_str=|%s|  IM_quantum_depth=|%lu|  img_depth=%lu  quantum_format=|%s|\n",
             IM_quantum_depth_str,IM_quantum_depth,img_depth,quantum_format);

  long long unsigned max_IM_val=1ULL<<IM_quantum_depth;
  long long unsigned max_img_val=(1ULL<<img_depth)-1;
  fprintf(stderr,"1L<<IM_quantum_depth=%Lu  max_IM_val=$Lu  max_img_val=%Lu\n",
            1ULL<<IM_quantum_depth,max_IM_val,max_img_val);
  print_stat(wand, max_img_val, max_IM_val);

  double degree=5;
  MagickWand *rotated_wand = CloneMagickWand(wand);
  PixelWand *background_color=NewPixelWand();
  printf("\n\nbefore RotateImage:   degree=%f\n",degree);
  status=MagickRotateImage(rotated_wand, background_color, degree);
  fprintf(stderr,"after MagickRotateImage:  background_color=%s[%%s]\n",
            PixelGetColorAsString(background_color));
  if(status == MagickFalse) {
    fprintf(stderr,"%s: MagickRotateImage failed, for degree=%f\n",
               argv[0],degree);
    exit(-1);
  }
  print_stat(rotated_wand,max_img_val,max_IM_val);

  char out_f[1024];
  sprintf(out_f,"OutImages/%s",argv[2]);
  printf("\n\nbefore MagickWriteImages(rotated_wand,%s,):\n",out_f);
  status=MagickWriteImages(rotated_wand,out_f,MagickTrue);
  printf("\n\nafter MagickWriteImages(rotated_wand):\n");
  if (status == MagickFalse) ThrowWandException(rotated_wand);

  rotated_wand=DestroyMagickWand(rotated_wand);
  wand=DestroyMagickWand(wand);
  MagickWandTerminus();
  return(0);
}
Running the programm I get the output:

rose@moose:/home_moose/rose/Txt/src/Test/C/ImageMagick/Wand(406)$ rotate-image_with_getChannelRange lena.png lena_rotated.png
IM_quantum_depth_str=|Q32| IM_quantum_depth=|32| img_depth=8 quantum_format=|(null)|
1L<<IM_quantum_depth=4294967296 max_IM_val=$Lu max_img_val=4294967296
img_depth=8
RedChannel: depth= 8 min= 38.0(0.149) max= 255.0(1.000) mean= 180.0(0.706) stdev= 49.4(0.194)
GreenChannel: depth= 8 min= 0.0(0.000) max= 243.0(0.953) mean= 99.4(0.390) stdev= 52.6(0.206)
BlueChannel: depth= 8 min= 9.0(0.035) max= 234.0(0.918) mean= 105.3(0.413) stdev= 34.1(0.134)
GrayChannel: depth= 8 min= 38.0(0.149) max= 255.0(1.000) mean= 180.0(0.706) stdev= 49.4(0.194)


before RotateImage: degree=5.000000
after MagickRotateImage: background_color=rgb(0,0,0)[%s]
img_depth=8
RedChannel: depth=32 min= -16.6(-0.065) max= 271.0(1.063) mean= 152.6(0.599) stdev= 78.8(0.309)
GreenChannel: depth=32 min= -14.1(-0.055) max= 241.9(0.949) mean= 84.3(0.331) stdev= 60.0(0.235)
BlueChannel: depth=32 min= -11.9(-0.047) max= 228.5(0.896) mean= 89.3(0.350) stdev= 49.0(0.192)
GrayChannel: depth=32 min= -16.6(-0.065) max= 271.0(1.063) mean= 152.6(0.599) stdev= 78.8(0.309)
...

I.e., after rotation the minimal pixel values are negative and the maximal red value is larger than 255. The channel depths changed from 8 to 32.
If I test the result with identify, I see the following values:

rose@moose:/home_moose/rose/Txt/src/Test/C/ImageMagick/Wand(407)$ identify -verbose OutImages/lena_rotated.png
Image: OutImages/lena_rotated.png
Format: PNG (Portable Network Graphics)
Class: DirectClass
Geometry: 556x556+0+0
...
Channel depth:
red: 8-bit
green: 8-bit
blue: 8-bit
Channel statistics:
Red:
min: 0 (0)
max: 255 (1)
mean: 152.666 (0.598692)
standard deviation: 78.7507 (0.308826)
kurtosis: -0.538735
skewness: -0.857874
Green:
min: 0 (0)
max: 242 (0.94902)
mean: 84.341 (0.330749)
standard deviation: 60.0008 (0.235297)
kurtosis: -0.915871
skewness: 0.210762
Blue:
min: 0 (0)
max: 229 (0.898039)
mean: 89.3244 (0.350292)
standard deviation: 48.9691 (0.192036)
kurtosis: -0.278467
skewness: -0.307794
Image statistics:
Overall:
min: 0 (0)
max: 255 (1)
mean: 108.777 (0.426577)
standard deviation: 63.7697 (0.250077)
kurtosis: 0.151732
skewness: 0.0844437


I.e., the channel depths are again 8, the negative minima disapeared, the maxima are not larger than 255. Mean and stdev are the same I got. So the rotated output looks nice. If I try to repeate the same procedure with a 16 bit tiff, the writing of the rotated image fails:

rose@moose:/home_moose/rose/Txt/src/Test/C/ImageMagick/Wand(408)$ rotate-image_with_getChannelRange 12Anti9_HgF2_100V_21x5s_40x__p008.tiff 12Anti9_HgF2_100V_21x5s_40x__p008_rotated.tiff
IM_quantum_depth_str=|Q32| IM_quantum_depth=|32| img_depth=16 quantum_format=|(null)|
1L<<IM_quantum_depth=4294967296 max_IM_val=$Lu max_img_val=4294967296
img_depth=16
RedChannel: depth=16 min= 5.0(0.000) max= 65295.0(0.996) mean= 32804.1(0.501) stdev= 19002.5(0.290)
GreenChannel: depth=16 min= 5.0(0.000) max= 65295.0(0.996) mean= 32804.1(0.501) stdev= 19002.5(0.290)
BlueChannel: depth=16 min= 5.0(0.000) max= 65295.0(0.996) mean= 32804.1(0.501) stdev= 19002.5(0.290)
GrayChannel: depth=16 min= 5.0(0.000) max= 65295.0(0.996) mean= 32804.1(0.501) stdev= 19002.5(0.290)


before RotateImage: degree=5.000000
after MagickRotateImage: background_color=rgb(0,0,0)[%s]
img_depth=16
RedChannel: depth=32 min=-11444.1(-0.175) max= 74949.4(1.144) mean= 27685.1(0.422) stdev= 19288.0(0.294)
GreenChannel: depth=32 min=-11444.1(-0.175) max= 74949.4(1.144) mean= 27685.1(0.422) stdev= 19288.0(0.294)
BlueChannel: depth=32 min=-11444.1(-0.175) max= 74949.4(1.144) mean= 27685.1(0.422) stdev= 19288.0(0.294)
GrayChannel: depth=32 min=-11444.1(-0.175) max= 74949.4(1.144) mean= 27685.1(0.422) stdev= 19288.0(0.294)


before MagickWriteImages(rotated_wand,OutImages/12Anti9_HgF2_100V_21x5s_40x__p008_rotated.tiff,):
rotate-image_with_getChannelRange: tif_dirwrite.c:2084: TIFFWriteDirectoryTagCheckedRational: Assertion `value>=0.0' failed.
Abgebrochen


I will deeply appreciate any hint, how to handle this issue.
Last edited by jrrose on 2012-02-10T04:09:27-07:00, edited 1 time in total.
jrrose
Posts: 11
Joined: 2011-12-05T08:19:02-07:00
Authentication code: 8675308

Re: New strange results of GetImageChannelRange after Rotate

Post by jrrose »

BTW, can anybody give me a hint, which algorithms is used, that some pixel values become negative or larger than the former maximal value (255)?
Post Reply