ImageMagick提取图像原始数据(ImageData/RawData)
我用的是ImageMagickWand的接口,因为这接口比Core接口更上层,所以官方文档推荐用。
抽取整个图像文件字节数据:
http://www.imagemagick.org/discourse-server/viewtopic.php?f=1&t=20664
抽取图像像素的字节数据:
http://www.imagemagick.org/discourse-server/viewtopic.php?f=6&t=12135
ImageMagick附带的convert工具命令使用:
convert [-option] inputfile outputfile
以下时常用option:
-colorspace
-size
-depth
以下是提取原始数据的命令:
convert -colorspace gray -depth 16 inputfile gray:filename.raw
.raw文件会在convert工具的当前目录下生成,.raw文件就是没有文件头的原始图像像素的字节文件。
以下时Demo:
1 // ImageMagick_use_test.cpp : Defines the entry point for the console application. 2 // 3 4 #include "stdafx.h" 5 #include "wand\MagickWand.h" 6 #include "magick\MagickCore.h" 7 #include "stdio.h" 8 #include "stdlib.h" 9 #include "conio.h" 10 #include "malloc.h" 11 12 #define OUT 13 14 void ThrowWandException(MagickWand* wand) 15 { 16 char *description; 17 18 ExceptionType severity; 19 char err_msg[125]; 20 21 description=MagickGetException(wand,&severity); 22 sprintf(err_msg,"%s\nError_Type is %d\n",description,severity); 23 //description=(char *) MagickRelinquishMemory(description); 24 25 printf(err_msg); 26 } 27 28 char* __stdcall GetGrayPixelFormat_16bit( const char* fileName, int width, int height, OUT char* pDestImage ); 29 30 bool __stdcall GetRGBPixelFormat_16bit( const char* fileName, int width, int height, OUT char* pRed, OUT char* pGreen, OUT char* pBlue); 31 32 int _tmain(int argc, _TCHAR* argv[]) 33 { 34 35 char *pDestImage = NULL; 36 char *pRed =NULL; 37 char *pGreen = NULL; 38 char *pBlue = NULL; 39 //Allocate 1024*5 Buffer in bytes 40 pDestImage = (char*)malloc(1920*1200*2); 41 pRed = (char*)malloc(1920*1200*2); 42 pGreen = (char*)malloc(1920*1200*2); 43 pBlue = (char*)malloc(1920*1200*2); 44 45 memset(pDestImage,0,1920*1200*2); 46 memset(pRed, 0, 1920*1200*2); 47 memset(pGreen, 0, 1920*1200*2); 48 memset(pBlue, 0, 1920*1200*2); 49 50 pDestImage = GetGrayPixelFormat_16bit( "C:\\Users\\Yajun Dou\\Desktop\\12.jpg", 1920, 1200, pDestImage); 51 52 if(pDestImage == NULL) 53 { 54 printf("GetGrayPixelFormat_16bit Failed!\n"); 55 } 56 57 if(GetRGBPixelFormat_16bit("C:\\Users\\Yajun Dou\\Desktop\\12.jpg",1920,1200,pRed,pGreen,pBlue)==false) 58 { 59 printf("GetRGBPixelFormat_16bit Failed!\n"); 60 } 61 62 free(pDestImage); 63 free(pRed); 64 free(pGreen); 65 free(pBlue); 66 67 68 return 0; 69 } 70 71 char* __stdcall GetGrayPixelFormat_16bit( const char* fileName, int width, int height, OUT char* pDestImage ) 72 { 73 MagickBooleanType status; 74 75 MagickWand *magick_wand; 76 77 char* pReturnDestImage = NULL; 78 char* pReturnDestImageData = NULL; 79 80 81 int IMageDepth; 82 83 //Initialize Magick Enviroment 84 85 MagickWandGenesis(); 86 magick_wand=NewMagickWand(); 87 88 //Read image 89 status=MagickReadImage(magick_wand,fileName); 90 if (status == MagickFalse) 91 ThrowWandException(magick_wand); 92 93 //得到图像深度 94 IMageDepth = (int)MagickGetImageDepth(magick_wand); 95 96 printf("The Current Image Depth is %d\n",IMageDepth); 97 98 99 //convert image to grayscale 100 status = MagickSetImageColorspace(magick_wand,GRAYColorspace); 101 102 if(status == MagickFalse) 103 ThrowWandException(magick_wand); 104 105 status = MagickTransformImageColorspace(magick_wand,GRAYColorspace); 106 107 if(status == MagickFalse) 108 ThrowWandException(magick_wand); 109 110 111 112 113 IMageDepth = (int)MagickGetImageDepth(magick_wand); 114 115 printf("The Current Image Depth is %d\n",IMageDepth); 116 117 118 //得到图像宽度和高度 119 int Height; 120 121 Height = (int)MagickGetImageHeight(magick_wand); 122 123 printf("The Current Image Height is %d\n",Height); 124 125 int Width; 126 127 Width = (int)MagickGetImageWidth(magick_wand); 128 129 printf("The Current Image Width is %d\n",Width); 130 131 //得到像素的通道数 132 int ImageChannels; 133 Image* pImage = NULL; 134 135 pImage = GetImageFromMagickWand(magick_wand); 136 137 if(pImage == NULL) 138 { 139 return NULL; 140 } 141 142 ImageChannels = pImage->channels; 143 144 /*printf("RedChannelDepth is %d\n",MagickGetImageChannelDepth(magick_wand,RedChannel)); 145 printf("GreenChannelDepth is %d\n",MagickGetImageChannelDepth(magick_wand,GreenChannel)); 146 printf("BlueChannelDepth is %d\n",MagickGetImageChannelDepth(magick_wand,BlueChannel)); 147 printf("GrayChannelDepth is %d\n",MagickGetImageChannelDepth(magick_wand,GrayChannel));*/ 148 149 150 151 if(Width != width || Height != height || IMageDepth != 16 || ImageChannels != 3) 152 { 153 154 if(MagickResizeImage(magick_wand,width,height,LanczosFilter,1.0) == MagickFalse) 155 { 156 ThrowWandException(magick_wand); 157 } 158 159 //设置图像深度 160 if(MagickSetImageDepth(magick_wand,16) == MagickFalse) 161 { 162 ThrowWandException(magick_wand); 163 } 164 //设置灰度通道深度 165 if(MagickSetImageChannelDepth(magick_wand,GrayChannel,16) == MagickFalse) 166 { 167 ThrowWandException(magick_wand); 168 } 169 170 } 171 172 173 174 // MagickWriteImages(magick_wand,"C:\\Users\\Yajun Dou\\Desktop\\12_trans1.bmp",MagickFalse); 175 176 177 IMageDepth = (int)MagickGetImageDepth(magick_wand); 178 179 printf("The Current Image Depth is %d\n",IMageDepth); 180 181 182 183 184 185 186 187 188 int ImageDataLength; 189 int ImageDataSize; 190 /* //MagickGetImageBlob函数得到的是整个图像文件的二进制字节流,并非图像数据 191 pReturnDestImage = (char*)MagickGetImageBlob(magick_wand,(size_t*)&ImageDataLength);*/ 192 MagickGetImagePixels(magick_wand,0,0,width,height,"I",ShortPixel,pDestImage); 193 194 195 196 197 198 magick_wand=DestroyMagickWand(magick_wand); 199 200 MagickWandTerminus(); 201 202 return pDestImage; 203 } 204 205 206 bool __stdcall GetRGBPixelFormat_16bit( const char* fileName, int width, int height, OUT char* pRed, OUT char* pGreen, OUT char* pBlue) 207 { 208 MagickBooleanType status; 209 210 MagickWand *magick_wand; 211 212 213 214 //Initialize Magick Enviroment 215 216 MagickWandGenesis(); 217 magick_wand=NewMagickWand(); 218 219 //Read image 220 status=MagickReadImage(magick_wand,fileName); 221 if (status == MagickFalse) 222 { 223 ThrowWandException(magick_wand); 224 return false; 225 } 226 227 //convert image to RGB three channels 228 status = MagickSetImageColorspace(magick_wand,RGBColorspace); 229 230 if(status == MagickFalse) 231 ThrowWandException(magick_wand); 232 233 status = MagickTransformImageColorspace(magick_wand,RGBColorspace); 234 235 if(status == MagickFalse) 236 ThrowWandException(magick_wand); 237 238 239 240 241 //得到图像深度 242 int IMageDepth; 243 244 245 IMageDepth = (int)MagickGetImageDepth(magick_wand); 246 247 printf("The Current Image Depth is %d\n",IMageDepth); 248 249 250 //得到图像宽度和高度 251 int Height; 252 253 Height = (int)MagickGetImageHeight(magick_wand); 254 255 printf("The Current Image Height is %d\n",Height); 256 257 int Width; 258 259 Width = (int)MagickGetImageWidth(magick_wand); 260 261 printf("The Current Image Width is %d\n",Width); 262 263 //得到像素的通道数 264 int ImageChannels; 265 Image* pImage = NULL; 266 267 pImage = GetImageFromMagickWand(magick_wand); 268 269 if(pImage == NULL) 270 { 271 return false; 272 } 273 274 ImageChannels = pImage->channels; 275 276 /*printf("RedChannelDepth is %d\n",MagickGetImageChannelDepth(magick_wand,RedChannel)); 277 printf("GreenChannelDepth is %d\n",MagickGetImageChannelDepth(magick_wand,GreenChannel)); 278 printf("BlueChannelDepth is %d\n",MagickGetImageChannelDepth(magick_wand,BlueChannel)); 279 printf("GrayChannelDepth is %d\n",MagickGetImageChannelDepth(magick_wand,GrayChannel));*/ 280 281 282 283 if(Width != width || Height != height) 284 { 285 286 if(MagickResizeImage(magick_wand,width,height,LanczosFilter,1.0) == MagickFalse) 287 { 288 ThrowWandException(magick_wand); 289 } 290 291 292 293 } 294 295 296 297 // MagickWriteImages(magick_wand,"C:\\Users\\Yajun Dou\\Desktop\\12_trans1.bmp",MagickFalse); 298 299 300 IMageDepth = (int)MagickGetImageDepth(magick_wand); 301 302 printf("The Current Image Depth is %d\n",IMageDepth); 303 304 305 306 307 308 309 310 311 312 313 int ImageDataLength; 314 int ImageDataSize; 315 /* //MagickGetImageBlob函数得到的是整个图像文件的二进制字节流,并非图像数据 316 pReturnDestImage = (char*)MagickGetImageBlob(magick_wand,(size_t*)&ImageDataLength);*/ 317 MagickGetImagePixels(magick_wand,0,0,width,height,"R",ShortPixel,pRed); 318 MagickGetImagePixels(magick_wand,0,0,width,height,"G",ShortPixel,pGreen); 319 MagickGetImagePixels(magick_wand,0,0,width,height,"B",ShortPixel,pBlue); 320 321 322 323 324 325 326 magick_wand=DestroyMagickWand(magick_wand); 327 328 MagickWandTerminus(); 329 330 return true; 331 332 333 }
TIPS:MagickWandGenesis()函数是对于整个进程(全局的初始化),一般要在主线程中调用,如果每个函数都调用MagickWandGenesis(),MagickWandTerminus();必然带来巨大性能开销。以上是Demo,所以没管那么多,如果糅合到项目中,必然不能这么写。ImageMagickGetImagePixels,后面的shortpixel是指提取16bit的图像数据,"R" "G"等是指示通道顺序,所以可以"RGB"连接起来写.最后一个参数是输出数据的字节数组。
另外还可以调用MagickExportImagePixels这个接口来得到图像数据。ImageMagickGetImagePixels这个接口貌似是过时的接口,虽然能用。这两个API的参数是一样的。
reference:
http://web.mit.edu/usmanm/MacData/afs/athena/contrib/graphics/share/ImageMagick/www/convert.html