1/* 2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3% % 4% % 5% % 6% W W BBBB M M PPPP % 7% W W B B MM MM P P % 8% W W W BBBB M M M PPPP % 9% WW WW B B M M P % 10% W W BBBB M M P % 11% % 12% % 13% Read/Write Wireless Bitmap (level 0) Image Format % 14% % 15% Software Design % 16% Cristy % 17% January 2000 % 18% % 19% % 20% Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization % 21% dedicated to making software imaging solutions freely available. % 22% % 23% You may not use this file except in compliance with the License. You may % 24% obtain a copy of the License at % 25% % 26% http://www.imagemagick.org/script/license.php % 27% % 28% Unless required by applicable law or agreed to in writing, software % 29% distributed under the License is distributed on an "AS IS" BASIS, % 30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 31% See the License for the specific language governing permissions and % 32% limitations under the License. % 33% % 34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 35% 36% 37*/ 38/* 39 Include declarations. 40*/ 41#include "MagickCore/studio.h" 42#include "MagickCore/attribute.h" 43#include "MagickCore/blob.h" 44#include "MagickCore/blob-private.h" 45#include "MagickCore/cache.h" 46#include "MagickCore/color-private.h" 47#include "MagickCore/colormap.h" 48#include "MagickCore/colorspace.h" 49#include "MagickCore/colorspace-private.h" 50#include "MagickCore/exception.h" 51#include "MagickCore/exception-private.h" 52#include "MagickCore/image.h" 53#include "MagickCore/image-private.h" 54#include "MagickCore/list.h" 55#include "MagickCore/magick.h" 56#include "MagickCore/memory_.h" 57#include "MagickCore/monitor.h" 58#include "MagickCore/monitor-private.h" 59#include "MagickCore/pixel-accessor.h" 60#include "MagickCore/quantum-private.h" 61#include "MagickCore/static.h" 62#include "MagickCore/string_.h" 63#include "MagickCore/module.h" 64 65/* 66 Forward declarations. 67*/ 68static MagickBooleanType 69 WriteWBMPImage(const ImageInfo *,Image *,ExceptionInfo *); 70 71/* 72%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 73% % 74% % 75% % 76% R e a d W B M P I m a g e % 77% % 78% % 79% % 80%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 81% 82% ReadWBMPImage() reads a WBMP (level 0) image file and returns it. It 83% allocates the memory necessary for the new Image structure and returns a 84% pointer to the new image. 85% 86% ReadWBMPImage was contributed by Milan Votava <votava@mageo.cz>. 87% 88% The format of the ReadWBMPImage method is: 89% 90% Image *ReadWBMPImage(const ImageInfo *image_info, 91% ExceptionInfo *exception) 92% 93% A description of each parameter follows: 94% 95% o image_info: the image info. 96% 97% o exception: return any errors or warnings in this structure. 98% 99*/ 100 101static MagickBooleanType WBMPReadInteger(Image *image,size_t *value) 102{ 103 int 104 byte; 105 106 *value=0; 107 do 108 { 109 byte=ReadBlobByte(image); 110 if (byte == EOF) 111 return(MagickFalse); 112 *value<<=7; 113 *value|=(unsigned int) (byte & 0x7f); 114 } while (byte & 0x80); 115 return(MagickTrue); 116} 117 118static Image *ReadWBMPImage(const ImageInfo *image_info, 119 ExceptionInfo *exception) 120{ 121 Image 122 *image; 123 124 int 125 byte; 126 127 MagickBooleanType 128 status; 129 130 register ssize_t 131 x; 132 133 register Quantum 134 *q; 135 136 ssize_t 137 y; 138 139 unsigned char 140 bit; 141 142 unsigned short 143 header; 144 145 /* 146 Open image file. 147 */ 148 assert(image_info != (const ImageInfo *) NULL); 149 assert(image_info->signature == MagickCoreSignature); 150 if (image_info->debug != MagickFalse) 151 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 152 image_info->filename); 153 assert(exception != (ExceptionInfo *) NULL); 154 assert(exception->signature == MagickCoreSignature); 155 image=AcquireImage(image_info,exception); 156 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); 157 if (status == MagickFalse) 158 { 159 image=DestroyImageList(image); 160 return((Image *) NULL); 161 } 162 if (ReadBlob(image,2,(unsigned char *) &header) == 0) 163 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 164 if (header != 0) 165 ThrowReaderException(CoderError,"OnlyLevelZerofilesSupported"); 166 /* 167 Initialize image structure. 168 */ 169 if (WBMPReadInteger(image,&image->columns) == MagickFalse) 170 ThrowReaderException(CorruptImageError,"CorruptWBMPimage"); 171 if (WBMPReadInteger(image,&image->rows) == MagickFalse) 172 ThrowReaderException(CorruptImageError,"CorruptWBMPimage"); 173 if ((image->columns == 0) || (image->rows == 0)) 174 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 175 if (DiscardBlobBytes(image,image->offset) == MagickFalse) 176 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", 177 image->filename); 178 if (AcquireImageColormap(image,2,exception) == MagickFalse) 179 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 180 if (image_info->ping != MagickFalse) 181 { 182 (void) CloseBlob(image); 183 return(GetFirstImageInList(image)); 184 } 185 status=SetImageExtent(image,image->columns,image->rows,exception); 186 if (status == MagickFalse) 187 return(DestroyImageList(image)); 188 /* 189 Convert bi-level image to pixel packets. 190 */ 191 for (y=0; y < (ssize_t) image->rows; y++) 192 { 193 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); 194 if (q == (Quantum *) NULL) 195 break; 196 bit=0; 197 byte=0; 198 for (x=0; x < (ssize_t) image->columns; x++) 199 { 200 if (bit == 0) 201 { 202 byte=ReadBlobByte(image); 203 if (byte == EOF) 204 ThrowReaderException(CorruptImageError,"CorruptImage"); 205 } 206 SetPixelIndex(image,(byte & (0x01 << (7-bit))) ? 1 : 0,q); 207 bit++; 208 if (bit == 8) 209 bit=0; 210 q+=GetPixelChannels(image); 211 } 212 if (SyncAuthenticPixels(image,exception) == MagickFalse) 213 break; 214 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y, 215 image->rows); 216 if (status == MagickFalse) 217 break; 218 } 219 (void) SyncImage(image,exception); 220 if (EOFBlob(image) != MagickFalse) 221 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", 222 image->filename); 223 (void) CloseBlob(image); 224 return(GetFirstImageInList(image)); 225} 226 227/* 228%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 229% % 230% % 231% % 232% R e g i s t e r W B M P I m a g e % 233% % 234% % 235% % 236%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 237% 238% RegisterWBMPImage() adds attributes for the WBMP image format to 239% the list of supported formats. The attributes include the image format 240% tag, a method to read and/or write the format, whether the format 241% supports the saving of more than one frame to the same file or blob, 242% whether the format supports native in-memory I/O, and a brief 243% description of the format. 244% 245% The format of the RegisterWBMPImage method is: 246% 247% size_t RegisterWBMPImage(void) 248% 249*/ 250ModuleExport size_t RegisterWBMPImage(void) 251{ 252 MagickInfo 253 *entry; 254 255 entry=AcquireMagickInfo("WBMP","WBMP","Wireless Bitmap (level 0) image"); 256 entry->decoder=(DecodeImageHandler *) ReadWBMPImage; 257 entry->encoder=(EncodeImageHandler *) WriteWBMPImage; 258 entry->flags^=CoderAdjoinFlag; 259 (void) RegisterMagickInfo(entry); 260 return(MagickImageCoderSignature); 261} 262 263/* 264%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 265% % 266% % 267% % 268% U n r e g i s t e r W B M P I m a g e % 269% % 270% % 271% % 272%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 273% 274% UnregisterWBMPImage() removes format registrations made by the 275% WBMP module from the list of supported formats. 276% 277% The format of the UnregisterWBMPImage method is: 278% 279% UnregisterWBMPImage(void) 280% 281*/ 282ModuleExport void UnregisterWBMPImage(void) 283{ 284 (void) UnregisterMagickInfo("WBMP"); 285} 286 287/* 288%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 289% % 290% % 291% % 292% W r i t e W B M P I m a g e % 293% % 294% % 295% % 296%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 297% 298% WriteWBMPImage() writes an image to a file in the Wireless Bitmap 299% (level 0) image format. 300% 301% WriteWBMPImage was contributed by Milan Votava <votava@mageo.cz>. 302% 303% The format of the WriteWBMPImage method is: 304% 305% MagickBooleanType WriteWBMPImage(const ImageInfo *image_info, 306% Image *image,ExceptionInfo *exception) 307% 308% A description of each parameter follows. 309% 310% o image_info: the image info. 311% 312% o image: The image. 313% 314% o exception: return any errors or warnings in this structure. 315% 316*/ 317 318static void WBMPWriteInteger(Image *image,const size_t value) 319{ 320 int 321 bits, 322 flag, 323 n; 324 325 register ssize_t 326 i; 327 328 unsigned char 329 buffer[5], 330 octet; 331 332 n=1; 333 bits=28; 334 flag=MagickFalse; 335 for (i=4; i >= 0; i--) 336 { 337 octet=(unsigned char) ((value >> bits) & 0x7f); 338 if ((flag == 0) && (octet != 0)) 339 { 340 flag=MagickTrue; 341 n=i+1; 342 } 343 buffer[4-i]=octet | (i && (flag || octet))*(0x01 << 7); 344 bits-=7; 345 } 346 (void) WriteBlob(image,(size_t) n,buffer+5-n); 347} 348 349static MagickBooleanType WriteWBMPImage(const ImageInfo *image_info, 350 Image *image,ExceptionInfo *exception) 351{ 352 MagickBooleanType 353 status; 354 355 register const Quantum 356 *p; 357 358 register ssize_t 359 x; 360 361 ssize_t 362 y; 363 364 unsigned char 365 bit, 366 byte; 367 368 /* 369 Open output image file. 370 */ 371 assert(image_info != (const ImageInfo *) NULL); 372 assert(image_info->signature == MagickCoreSignature); 373 assert(image != (Image *) NULL); 374 assert(image->signature == MagickCoreSignature); 375 if (image->debug != MagickFalse) 376 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 377 assert(exception != (ExceptionInfo *) NULL); 378 assert(exception->signature == MagickCoreSignature); 379 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception); 380 if (status == MagickFalse) 381 return(status); 382 (void) TransformImageColorspace(image,sRGBColorspace,exception); 383 /* 384 Convert image to a bi-level image. 385 */ 386 (void) SetImageType(image,BilevelType,exception); 387 (void) WriteBlobMSBShort(image,0); 388 WBMPWriteInteger(image,image->columns); 389 WBMPWriteInteger(image,image->rows); 390 for (y=0; y < (ssize_t) image->rows; y++) 391 { 392 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 393 if (p == (const Quantum *) NULL) 394 break; 395 bit=0; 396 byte=0; 397 for (x=0; x < (ssize_t) image->columns; x++) 398 { 399 if (GetPixelLuma(image,p) >= (QuantumRange/2.0)) 400 byte|=0x1 << (7-bit); 401 bit++; 402 if (bit == 8) 403 { 404 (void) WriteBlobByte(image,byte); 405 bit=0; 406 byte=0; 407 } 408 p+=GetPixelChannels(image); 409 } 410 if (bit != 0) 411 (void) WriteBlobByte(image,byte); 412 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, 413 image->rows); 414 if (status == MagickFalse) 415 break; 416 } 417 (void) CloseBlob(image); 418 return(MagickTrue); 419} 420