I repeated the test with ImageMagick 6.7.4-0:
rose@moose:/home_moose/rose/Txt/projects/MicroElectrodes/Test/GetOneAuthenticPixel_versus_MagickExportImagePixels(741)$ identify -version
Version: ImageMagick 6.7.4-0 2011-12-12 Q32
http://www.imagemagick.org
Copyright: Copyright (C) 1999-2011 ImageMagick Studio LLC
Features: OpenMP HDRI
But the behaviour of GetImageOption(image_info,"quantum:format") did not changed, the only way to determine the quantum format I found is to parse the output of IdentifyImage(img,T_FILE,MagickTrue) or MagickIdentifyImage(wand), which works but it is not very elegant.
Code: Select all
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <pcre.h>
#include <magick/MagickCore.h>
typedef struct {
ClassType storage_class;
const char *Class_str; // directly from identify
const char *image_type_str;
size_t height, width;
const char *Depth_str;
size_t depth_from_depth_str;
size_t quantum_depth_from_depth_str;
size_t depth;
//const char *quantum_depth_str;
size_t quantum_depth;
const char *color_space_string;
const char *compression_type_str;
size_t gray_channel_depth;
MagickBooleanType is_gray_image;
const char *quantum_format_str; // directly from identify
const char *quantum_format;
size_t n_imgs;
double x_resolution,y_resolution;
double gamma;
const char *gravity_type_str;
QuantumType quantum_type;
size_t quantum_extent;
MagickBooleanType is_high_dynamic_range;
const char *min_str, *max_str; // directly from identify
double minimum, maximum;
const char *mean_str, *stdev_str; // directly from identify
double mean, stdev;
ChannelFeatures *channel_features;
} Image_Info;
#define OVECCOUNT 30 /* should be a multiple of 3 */
//#define DEBUG 1
int main (int argc, char *argv[]) {
int rc,erroffset;
char *pat;
pcre *re;
const char *error;
int ovector[OVECCOUNT];
const char *Level1_Attribut, *Level2_Attribut;
MagickCoreGenesis(*argv,MagickTrue);
ExceptionInfo *exception=AcquireExceptionInfo();
ImageInfo *image_info=CloneImageInfo((ImageInfo *) NULL);
int magick_precision=GetMagickPrecision();
(void) strcpy(image_info->filename,argv[1]);
Image *imgs = ReadImages(image_info,exception);
if (exception->severity != UndefinedException) CatchException(exception);
if (imgs == (Image *) NULL) {
fprintf(stderr,"imgs is not defined\n"); exit(1);
}
printf("after ReadImage() magick_precision=%d imgs=%p imgs->next=%p\n",
magick_precision,imgs,imgs->next);
Image_Info *image_Info=(Image_Info *)malloc(sizeof(Image_Info));
MagickBooleanType constrain=MagickFalse;
image_Info->quantum_depth=GetImageQuantumDepth(imgs,constrain);
image_Info->quantum_format=GetImageOption(image_info,"quantum:format");
image_Info->depth=GetImageDepth(imgs,&imgs->exception);
ChannelType channel=GrayChannel;
image_Info->gray_channel_depth=GetImageChannelDepth(imgs,channel,
&imgs->exception);
image_Info->Class_str=0; char Class_str_aux[1024];
image_Info->Depth_str=0; char Depth_str_aux[1024];
image_Info->quantum_format_str=0; char quantum_format_str_aux[1024];
image_Info->min_str=0; char min_str_aux[1024];
image_Info->max_str=0; char max_str_aux[1024];
image_Info->mean_str=0; char mean_str_aux[1024];
image_Info->stdev_str=0; char stdev_str_aux[1024];
pid_t pid=getpid(); //Ermitteln des aktuellen Prozesses
fprintf(stderr,"pid=%d\n",pid);
char tmp_file[1024];
sprintf(tmp_file,"/tmp/image_identify_%d\n",pid);
FILE *T_FILE=fopen(tmp_file,"w");
if (T_FILE == NULL) {
fprintf(stderr,"ERROR opening %s for writing\n",tmp_file);
exit(EXIT_FAILURE);
}
const MagickBooleanType verbose=MagickTrue;
MagickBooleanType status=IdentifyImage(imgs,T_FILE,verbose);
fclose(T_FILE);
T_FILE=fopen(tmp_file,"r");
if (T_FILE == NULL) {
fprintf(stderr,"ERROR opening %s for reading\n",tmp_file);
exit(EXIT_FAILURE);
}
#define BUFLEN 1024
char *line = NULL;
char s0[BUFLEN+1],s1[BUFLEN+1],s2[BUFLEN+1];
size_t len=BUFLEN;
size_t read;
int Channel_stat=0, Gray_Channel=0;
while ((read = getline(&line, &len, T_FILE)) != -1) {
//printf("Retrieved line of length %zu : len=%lu\n", read,len);
if ( line[strlen(line)-1] == '\n' ) line[strlen(line)-1]=0;
#ifdef DEBUG
fprintf(stderr,"line=|%s|\n",line);
#endif
if(!(re=pcre_compile("^[\\s]*$",0,&error,&erroffset,NULL))) {
printf("PCRE compilation failed at offset %d: %s\n", erroffset, error);
exit(1);
}
if(pcre_exec(re,NULL,line,(int)strlen(line),0,0,ovector,OVECCOUNT)>=0) {
#ifdef DEBUG
fprintf(stderr,"Empty line found\n");
#endif
} else {
pat="([\\s]*)(.*)[\\s]*:[\\s]*(.*)[\\s]*$";
//pat="[\\s]*quantum:format[\\s]*:[\\s]*(.*)[\\s]*$";
//fprintf(stderr,"before testing pat=|%s| line=|%s|\n",pat,line);
if(!(re=pcre_compile(pat,0,&error,&erroffset,NULL))) {
fprintf(stderr,"PCRE compilation failed at offset %d: %s\n",erroffset,error);
exit(1);
}
rc = pcre_exec(re,NULL,line,(int)strlen(line),0,0,ovector,OVECCOUNT);
/* Matching failed: handle error cases */
if (rc < 0) {
switch(rc) {
case PCRE_ERROR_NOMATCH:
//fprintf(stderr,"No match in tmp_file=|%s| line=|%s|\n",tmp_file,line);
//exit(2);
break;
/*
Handle other special cases if you like
*/
default:
fprintf(stderr,"Matching error %d in tmp_file=|%s| line=|%s|\n",
rc,tmp_file,line);
exit(2);
break;
}
} else {
/* Match succeded */
#ifdef DEBUG
fprintf(stderr," Match succeeded\n");
#endif
/* The output vector wasn't big enough */
if (rc == 0) {
rc = OVECCOUNT/3;
fprintf(stderr,"ovector only has room for %d captured substrings\n",
rc-1);
}
#ifdef DEBUG
/* Show substrings stored in the output vector */
int i;
for(i=0; i<rc; i++) {
char *substring_start = line+ovector[2*i];
int substring_length = ovector[2*i+1]-ovector[2*i];
fprintf(stderr," %2d: |%.*s|\n",i,substring_length,substring_start);
}
#endif
strncpy(s0,line+ovector[2],ovector[2+1]-ovector[2]);
strncpy(s1,line+ovector[4],ovector[4+1]-ovector[4]);
strncpy(s2,line+ovector[6],ovector[6+1]-ovector[6]);
s0[ovector[2+1]-ovector[2]]=0;
s1[ovector[4+1]-ovector[4]]=0;
s2[ovector[6+1]-ovector[6]]=0;
#ifdef DEBUG
fprintf(stderr,"strlen(s0)=%4lu s1=|%s| s2=|%s|\n",strlen(s0),s1,s2);
#endif
if (strlen(s0)==2) {
Level1_Attribut=s1;
Channel_stat=0;
if (!strcmp(s1,"Channel statistics")) {
Channel_stat=1;
}
}
if (strlen(s0)==4) {
Level2_Attribut=s1;
if (Channel_stat==1) {
if (!strcmp(s1,"Gray")) {
Gray_Channel=1;
}
}
}
if (!strcmp(s1,"Class")) {
strcpy(Class_str_aux,s2);
image_Info->Class_str=Class_str_aux;
}
if (!strcmp(s1,"Depth")) {
char *pc=index(s2,'-');
if ( pc ) {
*pc=0;
char *endptr;
strcpy(Depth_str_aux,s2);
image_Info->Depth_str=Depth_str_aux;
if ((pc = index(s2,'/')) != NULL) {
*pc=0;
image_Info->depth_from_depth_str= strtol(pc+1,&endptr,10);
image_Info->quantum_depth_from_depth_str=strtol(s2,&endptr,10);
} else {
image_Info->quantum_depth_from_depth_str=strtol(s2,&endptr,10);
image_Info->depth_from_depth_str=
image_Info->quantum_depth_from_depth_str;
}
} else {
fprintf(stderr,"ERROR: unexpected 'Depth:' line\n");
exit(-1);
}
}
if (!strcmp(s1,"quantum:format")) {
strcpy(quantum_format_str_aux,s2);
image_Info->quantum_format_str=quantum_format_str_aux;
}
if (Channel_stat!=0 && !strcmp(s1,"min")) {
strcpy(min_str_aux,s2);
image_Info->min_str=min_str_aux;
}
if (Channel_stat!=0 && !strcmp(s1,"max")) {
strcpy(max_str_aux,s2);
image_Info->max_str=max_str_aux;
}
if (Channel_stat!=0 && !strcmp(s1,"mean")) {
strcpy(mean_str_aux,s2);
image_Info->mean_str=mean_str_aux;
}
if (Channel_stat!=0 && !strcmp(s1,"standard deviation")) {
strcpy(stdev_str_aux,s2);
image_Info->stdev_str=stdev_str_aux;
}
}
}
}
printf("option=%p (quantum:format)\n",image_Info->quantum_format);
printf("------ depth =%lu quantum_depth =%ld\n",
image_Info->depth,image_Info->quantum_depth);
printf(" depth_from_depth_str=%lu quantum_depth_from_depth_str=%lu\n",
image_Info->depth_from_depth_str,
image_Info->quantum_depth_from_depth_str);
printf(" gray channel_depth=%ld width=%ld height=%ld n_imgs=%lu\n",
image_Info->gray_channel_depth,
image_Info->width,image_Info->height,image_Info->n_imgs);
printf("quantum:format=|%s| quantum:format_str=|%s|\n",
image_Info->quantum_format?
image_Info->quantum_format:" is not defined",
image_Info->quantum_format_str?
image_Info->quantum_format_str:" is not defined");
printf("storage_class=%d Class_str=|%s| \n",image_Info->storage_class,
image_Info->Class_str?
image_Info->Class_str:" is not defined");
double max_value=(double)(2L<<(image_Info->quantum_depth_from_depth_str-1));
printf("image_Info->depth=%lu image_Info->quantum_depth_from_depth_str=%lu max_value=%f\n",
image_Info->depth,image_Info->quantum_depth_from_depth_str,max_value);
printf("min_str=|%s| mean_str=|%s| max_str=|%s| stdev=|%s|\n",
image_Info->min_str,image_Info->mean_str,
image_Info->max_str,image_Info->stdev_str);
image_info=DestroyImageInfo(image_info);
exception=DestroyExceptionInfo(exception);
MagickCoreTerminus();
return 0;
}
Now with ImageMagick 6.7.4-0 GetImageDepth() and MagickGetImageDepth() return both 29 Bit for my file input__29BitsGray-32Bits_quantum_format_float.tiff. But I did not found any way to identify from the MagickWand-API, that there is 32 Bit information in the file. MagickGetImageDepth() and MagickGetImageChannelDepth(wand,channel) return 29 Bit. I am missing a function MagickGetImageQuantumDepth() (in MagickCore I have GetImageQuantumDepth()). So I have to parse again the output of MagickIdentifyImage().
Code: Select all
#include <stdio.h>
#include <string.h>
#include <pcre.h>
#include <wand/magick_wand.h>
typedef struct {
ClassType storage_class;
const char *Class_str; // directly from identify
const char *image_type_str;
size_t height, width;
const char *Depth_str;
size_t depth_from_depth_str;
size_t quantum_depth_from_depth_str;
size_t depth;
//const char *quantum_depth_str;
size_t quantum_depth;
const char *color_space_string;
const char *compression_type_str;
size_t gray_channel_depth;
MagickBooleanType is_gray_image;
const char *quantum_format_str; // directly from identify
const char *quantum_format;
size_t n_imgs;
double x_resolution,y_resolution;
double gamma;
const char *gravity_type_str;
QuantumType quantum_type;
size_t quantum_extent;
MagickBooleanType is_high_dynamic_range;
const char *min_str, *max_str; // directly from identify
double minimum, maximum;
const char *mean_str, *stdev_str; // directly from identify
double mean, stdev;
ChannelFeatures *channel_features;
} Image_Info;
#define OVECCOUNT 30 /* should be a multiple of 3 */
//#define DEBUG 1
#define ThrowWandException(wand) { \
ExceptionType severity; \
char *description=MagickGetException(wand,&severity); \
(void) fprintf(stderr,"%s %s %ld %s\n",GetMagickModule(),description); \
description=(char *) MagickRelinquishMemory(description); \
exit(-1); \
}
int main (int argc, char *argv[]) {
int rc,erroffset;
char *pat;
pcre *re;
const char *error;
int ovector[OVECCOUNT];
const char *Level1_Attribut, *Level2_Attribut;
MagickWandGenesis();
MagickWand *wand=NewMagickWand();
int status=MagickReadImage(wand,argv[1]);
if (status == MagickFalse) ThrowWandException(wand);
Image_Info *image_Info=(Image_Info *)malloc(sizeof(Image_Info));
image_Info->storage_class= -1;
image_Info->height=MagickGetImageHeight(wand);
image_Info->width=MagickGetImageWidth(wand);
image_Info->depth=MagickGetImageDepth(wand);
image_Info->quantum_depth=-1;
ChannelType channel=GrayChannel;
image_Info->gray_channel_depth=MagickGetImageChannelDepth(wand,channel);
image_Info->quantum_format=MagickGetOption(wand,"quantum:format");
image_Info->Class_str=0; char Class_str_aux[1024];
image_Info->Depth_str=0; char Depth_str_aux[1024];
image_Info->quantum_format_str=0; char quantum_format_str_aux[1024];
image_Info->min_str=0; char min_str_aux[1024];
image_Info->max_str=0; char max_str_aux[1024];
image_Info->mean_str=0; char mean_str_aux[1024];
image_Info->stdev_str=0; char stdev_str_aux[1024];
char *identify_image=MagickIdentifyImage(wand);
#define BUFLEN 1024
char *line = (char *)malloc(BUFLEN+1);
char *pc, *old_pc=identify_image;
char s0[BUFLEN+1],s1[BUFLEN+1],s2[BUFLEN+1];
int Channel_stat, Gray_Channel;
while ((pc=index(old_pc,'\n'))!=NULL) {
//fprintf(stderr,"pc-old_pc=%ld\n",pc-old_pc);
strncpy(line,old_pc,pc-old_pc);
line[pc-old_pc]=0;
#ifdef DEBUG
fprintf(stderr,"line=|%s|\n",line);
#endif
if(!(re=pcre_compile("^[\\s]*$",0,&error,&erroffset,NULL))) {
printf("PCRE compilation failed at offset %d: %s\n", erroffset, error);
exit(1);
}
if(pcre_exec(re,NULL,line,(int)strlen(line),0,0,ovector,OVECCOUNT)>=0) {
#ifdef DEBUG
fprintf(stderr,"Empty line found\n");
#endif
} else {
pat="([\\s]*)(.*)[\\s]*:[\\s]*(.*)[\\s]*$";
//pat="[\\s]*quantum:format[\\s]*:[\\s]*(.*)[\\s]*$";
//fprintf(stderr,"before testing pat=|%s| line=|%s|\n",pat,line);
if(!(re=pcre_compile(pat,0,&error,&erroffset,NULL))) {
fprintf(stderr,"PCRE compilation failed at offset %d: %s\n",erroffset,error);
exit(1);
}
rc = pcre_exec(re,NULL,line,(int)strlen(line),0,0,ovector,OVECCOUNT);
/* Matching failed: handle error cases */
if (rc < 0) {
switch(rc) {
case PCRE_ERROR_NOMATCH:
//fprintf(stderr,"No match in tmp_file=|%s| line=|%s|\n",tmp_file,line);
//exit(2);
break;
/*
Handle other special cases if you like
*/
default:
fprintf(stderr,"Matching error %d using identify line=|%s|\n",
rc,line);
exit(2);
break;
}
} else {
/* Match succeded */
#ifdef DEBUG
fprintf(stderr," Match succeeded\n");
#endif
/* The output vector wasn't big enough */
if (rc == 0) {
rc = OVECCOUNT/3;
fprintf(stderr,"ovector only has room for %d captured substrings\n",
rc-1);
}
#ifdef DEBUG
/* Show substrings stored in the output vector */
int i;
for(i=0; i<rc; i++) {
char *substring_start = line+ovector[2*i];
int substring_length = ovector[2*i+1]-ovector[2*i];
fprintf(stderr," %2d: |%.*s|\n",i,substring_length,substring_start);
}
#endif
strncpy(s0,line+ovector[2],ovector[2+1]-ovector[2]);
strncpy(s1,line+ovector[4],ovector[4+1]-ovector[4]);
strncpy(s2,line+ovector[6],ovector[6+1]-ovector[6]);
s0[ovector[2+1]-ovector[2]]=0;
s1[ovector[4+1]-ovector[4]]=0;
s2[ovector[6+1]-ovector[6]]=0;
#ifdef DEBUG
fprintf(stderr,"strlen(s0)=%4lu s1=|%s| s2=|%s|\n",strlen(s0),s1,s2);
#endif
if (strlen(s0)==2) {
Level1_Attribut=s1;
Channel_stat=0;
if (!strcmp(s1,"Channel statistics")) {
Channel_stat=1;
}
}
if (strlen(s0)==4) {
Level2_Attribut=s1;
if (Channel_stat==1) {
if (!strcmp(s1,"Gray")) {
Gray_Channel=1;
}
}
}
if (!strcmp(s1,"Class")) {
strcpy(Class_str_aux,s2);
image_Info->Class_str=Class_str_aux;
}
if (!strcmp(s1,"Depth")) {
char *pc=index(s2,'-');
if ( pc ) {
*pc=0;
char *endptr;
strcpy(Depth_str_aux,s2);
image_Info->Depth_str=Depth_str_aux;
if ((pc = index(s2,'/')) != NULL) {
*pc=0;
image_Info->depth_from_depth_str= strtol(pc+1,&endptr,10);
image_Info->quantum_depth_from_depth_str=strtol(s2,&endptr,10);
} else {
image_Info->quantum_depth_from_depth_str=strtol(s2,&endptr,10);
image_Info->depth_from_depth_str=
image_Info->quantum_depth_from_depth_str;
}
} else {
fprintf(stderr,"ERROR: unexpected 'Depth:' line\n");
exit(-1);
}
}
if (!strcmp(s1,"quantum:format")) {
strcpy(quantum_format_str_aux,s2);
image_Info->quantum_format_str=quantum_format_str_aux;
}
if (Channel_stat!=0 && !strcmp(s1,"min")) {
strcpy(min_str_aux,s2);
image_Info->min_str=min_str_aux;
}
if (Channel_stat!=0 && !strcmp(s1,"max")) {
strcpy(max_str_aux,s2);
image_Info->max_str=max_str_aux;
}
if (Channel_stat!=0 && !strcmp(s1,"mean")) {
strcpy(mean_str_aux,s2);
image_Info->mean_str=mean_str_aux;
}
if (Channel_stat!=0 && !strcmp(s1,"standard deviation")) {
strcpy(stdev_str_aux,s2);
image_Info->stdev_str=stdev_str_aux;
}
}
}
old_pc=pc+1;
}
printf("option=%p (quantum:format)\n",image_Info->quantum_format);
printf("------ depth =%lu quantum_depth =%ld\n",
image_Info->depth,image_Info->quantum_depth);
printf(" depth_from_depth_str=%lu quantum_depth_from_depth_str=%lu\n",
image_Info->depth_from_depth_str,
image_Info->quantum_depth_from_depth_str);
printf(" gray channel_depth=%ld width=%ld height=%ld n_imgs=%lu\n",
image_Info->gray_channel_depth,
image_Info->width,image_Info->height,image_Info->n_imgs);
printf("quantum:format=|%s| quantum:format_str=|%s|\n",
image_Info->quantum_format?
image_Info->quantum_format:" is not defined",
image_Info->quantum_format_str?
image_Info->quantum_format_str:" is not defined");
printf("storage_class=%d Class_str=|%s| \n",image_Info->storage_class,
image_Info->Class_str?
image_Info->Class_str:" is not defined");
double max_value=(double)(2L<<(image_Info->quantum_depth_from_depth_str-1));
printf("image_Info->depth=%lu image_Info->quantum_depth_from_depth_str=%lu max_value=%f\n",
image_Info->depth,image_Info->quantum_depth_from_depth_str,max_value);
printf("min_str=|%s| mean_str=|%s| max_str=|%s| stdev=|%s|\n",
image_Info->min_str,image_Info->mean_str,
image_Info->max_str,image_Info->stdev_str);
if(wand != NULL) wand=DestroyMagickWand(wand);
MagickWandTerminus();
return 0;
}
Is there any shorter way to get these information (quantum_format for MagickCore, quantum_depth and quantum_format for MagickWand) without using the Identity functions and in particular in case of MagickCore without writing and reading of files to and from disk?