Requesting quantum format from MagickCore and MagickWand API

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
Post Reply
jrrose
Posts: 11
Joined: 2011-12-05T08:19:02-07:00
Authentication code: 8675308

Requesting quantum format from MagickCore and MagickWand API

Post by jrrose »

I have some pictures, where 'identify -verbose' says "quantum:format: floating-point". I want to save the pixels of these and other images with GetOneAuthenticPixel in MagickCore and with MagickExportImagePixels in MagickWand to a long or a double array. To do this, I want to decide from the MagickCore and MagickWand API, what is the quantum:format of my input images. I am looking for something like a function GetQuantumFormat(), I found only SetQuantumFormat() for MagickCore. I tried also:

QuantumInfo *quantum_info=AcquireQuantumInfo(image_info,img);
if (quantum_info->format == FloatingPointQuantumFormat) {
fprintf(stderr,"FloatingPointQuantumFormat found!\n");
}

But the compiler says:
print_tiff_asc_Core.c:119:38: error: dereferencing pointer to incomplete type

I have imagemagick-6.7.3.0 compiled under gentoo with the hdri q32 USE flags.
Any hint is deeply appreciated.
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: Requesting quantum format from MagickCore and MagickWand

Post by magick »

Every setter should have a getter. We added GetQuantumFormat() to ImageMagick 6.7.4-0 available as beta by sometime tomorrow. Look for a release within the next week or two.
jrrose
Posts: 11
Joined: 2011-12-05T08:19:02-07:00
Authentication code: 8675308

Re: Requesting quantum format from MagickCore and MagickWand

Post by jrrose »

Thanks magick,

I will wait for GetQuantumFormat(). But in the meantime is there any other solution to get information from the Core or Wand API whether a image has long or float pixel?

Regards Juergeen
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: Requesting quantum format from MagickCore and MagickWand

Post by magick »

Use
  • const char *option=GetImageOption(image_info,"quantum:format");
jrrose
Posts: 11
Joined: 2011-12-05T08:19:02-07:00
Authentication code: 8675308

Re: Requesting quantum format from MagickCore and MagickWand

Post by jrrose »

It seems that
const char *option=GetImageOption(image_info,"quantum:format");
does not work for me. I use the following source:

Code: Select all

#include <stdio.h>
#include <string.h>
#include <magick/MagickCore.h>

int main (int argc, char *argv[]) {
  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);
  size_t depth=GetImageDepth(imgs,&imgs->exception);
  ChannelType channel=GrayChannel;
  size_t gray_channel_depth=GetImageChannelDepth(imgs,channel,
									 &imgs->exception);
  MagickBooleanType constrain=MagickFalse;
  size_t quantum_depth=GetImageQuantumDepth(imgs,constrain);
  printf("depth=%lu  gray_channel_depth=%lu  quantum_depth=%lu\n",
	 depth,gray_channel_depth,quantum_depth);
  const char *quantum_format=GetImageOption(image_info,"quantum:format");
  printf("quantum_format=|%s|\n",
	 quantum_format?quantum_format:"'is not defined'");
  image_info=DestroyImageInfo(image_info);
  exception=DestroyExceptionInfo(exception);
  MagickCoreTerminus();
  return 0;
}
with MagickCore and

Code: Select all

#include <stdio.h>
#include <string.h>
#include <wand/magick_wand.h>

#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[]) {
  MagickWandGenesis();
  MagickWand *wand=NewMagickWand();
  int status=MagickReadImage(wand,argv[1]);
  if (status == MagickFalse) ThrowWandException(wand);
  size_t depth=MagickGetImageDepth(wand);
  ChannelType channel=GrayChannel;
  size_t gray_channel_depth=MagickGetImageChannelDepth(wand,channel);
  printf("depth=%lu  gray_channel_depth=%lu\n",
       depth,gray_channel_depth);
  const char *quantum_format=MagickGetOption(wand,"quantum:format");
  printf("quantum_format=|%s|\n",
      quantum_format?quantum_format:"'is not defined'");

  if(wand != NULL) wand=DestroyMagickWand(wand);
  MagickWandTerminus();
  return 0;
}
With MagickWand. I tested the programs resulting from both sources with three small files:
rose@moose:/home_moose/rose/Txt/projects/MicroElectrodes/Test/GetOneAuthenticPixel_versus_MagickExportImagePixels(471)$ ll input__*.tif*
-rw-r----- 1 rose rose 4183 6. Dez 14:34 input__16BitsGray-16Bits_quantum_format_long.tiff (http://141.89.194.24/~rose/input__16Bit ... _long.tiff)
-rw-r----- 1 rose rose 4629 8. Dez 17:48 input__29BitsGray-32Bits_quantum_format_float.tiff (http://141.89.194.24/~rose/input__29Bit ... float.tiff)
-rw-r----- 1 rose rose 14817 5. Dez 16:48 input__32BitsGray-32Bits_quantum_format_float.tiff (http://141.89.194.24/~rose/input__32Bit ... float.tiff)

using the script get_quantuminfo.sh:
rose@moose:/home_moose/rose/Txt/projects/MicroElectrodes/Test/GetOneAuthenticPixel_versus_MagickExportImagePixels(475)$ cat get_quantuminfo.sh

Code: Select all

#!/bin/bash

for f in input__*.tif* ; do
  echo "=================  f=$f =================";
  cmd='identify -verbose $f | grep quantum:format'
  echo "--------  before '$cmd' ------------";   eval $cmd 2>/dev/null
  cmd='./get_quantuminfo_Core $f'
  echo "--------  before '$cmd' ------------";   eval $cmd 2>/dev/null
  cmd='./get_quantuminfo_Wand $f'
  echo "--------  before '$cmd' ------------";   eval $cmd 2>/dev/null
done
The result is:
rose@moose:/home_moose/rose/Txt/projects/MicroElectrodes/Test/GetOneAuthenticPixel_versus_MagickExportImagePixels(477)$ ./get_quantuminfo.sh
================= f=input__16BitsGray-16Bits_quantum_format_long.tiff =================
-------- before 'identify -verbose $f | grep quantum:format' ------------
-------- before './get_quantuminfo_Core $f' ------------
after ReadImage() magick_precision=6 imgs=0x1d0ccf0 imgs->next=(nil)
depth=16 gray_channel_depth=16 quantum_depth=16
quantum_format=|'is not defined'|
-------- before './get_quantuminfo_Wand $f' ------------
depth=16 gray_channel_depth=16
quantum_format=||
================= f=input__29BitsGray-32Bits_quantum_format_float.tiff =================
-------- before 'identify -verbose $f | grep quantum:format' ------------
quantum:format: floating-point
-------- before './get_quantuminfo_Core $f' ------------
after ReadImage() magick_precision=6 imgs=0x6ebcf0 imgs->next=(nil)
depth=29 gray_channel_depth=29 quantum_depth=32
quantum_format=|'is not defined'|
-------- before './get_quantuminfo_Wand $f' ------------
depth=32 gray_channel_depth=29
quantum_format=||
================= f=input__32BitsGray-32Bits_quantum_format_float.tiff =================
-------- before 'identify -verbose $f | grep quantum:format' ------------
quantum:format: floating-point
-------- before './get_quantuminfo_Core $f' ------------
after ReadImage() magick_precision=6 imgs=0x1da0cf0 imgs->next=(nil)
depth=32 gray_channel_depth=32 quantum_depth=32
quantum_format=|'is not defined'|
-------- before './get_quantuminfo_Wand $f' ------------
depth=32 gray_channel_depth=32
quantum_format=||

I.e., "identify -verbose" finds that two files have the quantum:format: floating-point, while GetImageOption(image_info,"quantum:format") gives a Null-pointer and MagickGetOption(wand,"quantum:format") gives a
pointer to an empty string. What I am doing wrong?
Btw. in the case of the input file input__29BitsGray-32Bits_quantum_format_float.tiff using MagickCore, GetImageDepth() and GetImageChannelDepth() return 29Bits and GetImageQuantumDepth() returns 32Bits,
while using MagickWand MagickGetImageDepth() returns 32Bits and MagickGetImageChannelDepth() returns 29Bits. I.e., MagickWand MagickGetImageDepth() corresponds to GetImageQuantumDepth() and not to GetImageDepth(). Is this intentionally?
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: Requesting quantum format from MagickCore and MagickWand

Post by magick »

We patched ImageMagick 6.7.0-0 Beta so that MagickGetImageDepth() computes the depth as it already does for ImageMagick 7.0.0-0 alpha. Thanks.
jrrose
Posts: 11
Joined: 2011-12-05T08:19:02-07:00
Authentication code: 8675308

Re: Requesting quantum format from MagickCore and MagickWand

Post by jrrose »

But what about the main problem the identification of quantum:format?
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: Requesting quantum format from MagickCore and MagickWand

Post by magick »

That's in ImageMagick 6.7.4-0 Beta as well. We should have a release with the next week.
jrrose
Posts: 11
Joined: 2011-12-05T08:19:02-07:00
Authentication code: 8675308

Re: Requesting quantum format from MagickCore and MagickWand

Post by jrrose »

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?
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: Requesting quantum format from MagickCore and MagickWand

Post by magick »

This returns floating-point for us:
  • MagickGetImageProperty(wand,"quantum:format")
We'll add a patch to ImageMagick 6.7.4-1 Beta so that MagickGetImageDepth() returns the original image depth.
Post Reply