1 /* 2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 % % 4 % % 5 % % 6 % RRRR GGG FFFFF % 7 % R R G F % 8 % RRRR G GG FFF % 9 % R R G G F % 10 % R R GGG F % 11 % % 12 % % 13 % Read/Write LEGO Mindstorms EV3 Robot Graphics File % 14 % % 15 % Software Design % 16 % Brian Wheeler % 17 % August 2013 % 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 /* 41 Include declarations. 42 */ 43 #include "MagickCore/studio.h" 44 #include "MagickCore/attribute.h" 45 #include "MagickCore/blob.h" 46 #include "MagickCore/blob-private.h" 47 #include "MagickCore/cache.h" 48 #include "MagickCore/color-private.h" 49 #include "MagickCore/colormap.h" 50 #include "MagickCore/colorspace.h" 51 #include "MagickCore/colorspace-private.h" 52 #include "MagickCore/exception.h" 53 #include "MagickCore/exception-private.h" 54 #include "MagickCore/image.h" 55 #include "MagickCore/image-private.h" 56 #include "MagickCore/list.h" 57 #include "MagickCore/magick.h" 58 #include "MagickCore/memory_.h" 59 #include "MagickCore/monitor.h" 60 #include "MagickCore/monitor-private.h" 61 #include "MagickCore/pixel-accessor.h" 62 #include "MagickCore/quantum-private.h" 63 #include "MagickCore/static.h" 64 #include "MagickCore/string_.h" 65 #include "MagickCore/module.h" 66 #include "MagickCore/utility.h" 67 68 /* 70 Forward declarations. 71 */ 72 static MagickBooleanType 73 WriteRGFImage(const ImageInfo *,Image *,ExceptionInfo *); 74 75 /* 77 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 78 % % 79 % % 80 % % 81 % R e a d X B M I m a g e % 82 % % 83 % % 84 % % 85 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 86 % 87 % ReadRGFImage() reads an RGF bitmap image file and returns it. It 88 % allocates the memory necessary for the new Image structure and returns a 89 % pointer to the new image. 90 % 91 % The format of the ReadRGFImage method is: 92 % 93 % Image *ReadRGFImage(const ImageInfo *image_info,ExceptionInfo *exception) 94 % 95 % A description of each parameter follows: 96 % 97 % o image_info: the image info. 98 % 99 % o exception: return any errors or warnings in this structure. 100 % 101 */ 102 static Image *ReadRGFImage(const ImageInfo *image_info,ExceptionInfo *exception) 103 { 104 Image 105 *image; 106 107 int 108 bit; 109 110 MagickBooleanType 111 status; 112 113 register ssize_t 114 i, 115 x; 116 117 register Quantum 118 *q; 119 120 register unsigned char 121 *p; 122 123 ssize_t 124 y; 125 126 unsigned char 127 byte, 128 *data; 129 130 /* 131 Open image file. 132 */ 133 assert(image_info != (const ImageInfo *) NULL); 134 assert(image_info->signature == MagickCoreSignature); 135 if (image_info->debug != MagickFalse) 136 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 137 image_info->filename); 138 assert(exception != (ExceptionInfo *) NULL); 139 assert(exception->signature == MagickCoreSignature); 140 image=AcquireImage(image_info,exception); 141 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); 142 if (status == MagickFalse) 143 { 144 image=DestroyImageList(image); 145 return((Image *) NULL); 146 } 147 /* 148 Read RGF header. 149 */ 150 image->columns = (unsigned long) ReadBlobByte(image); 151 image->rows = (unsigned long) ReadBlobByte(image); 152 image->depth=8; 153 image->storage_class=PseudoClass; 154 image->colors=2; 155 /* 156 Initialize image structure. 157 */ 158 if (AcquireImageColormap(image,image->colors,exception) == MagickFalse) 159 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 160 /* 161 Initialize colormap. 162 */ 163 image->colormap[0].red=QuantumRange; 164 image->colormap[0].green=QuantumRange; 165 image->colormap[0].blue=QuantumRange; 166 image->colormap[1].red=(Quantum) 0; 167 image->colormap[1].green=(Quantum) 0; 168 image->colormap[1].blue=(Quantum) 0; 169 if (image_info->ping != MagickFalse) 170 { 171 (void) CloseBlob(image); 172 return(GetFirstImageInList(image)); 173 } 174 status=SetImageExtent(image,image->columns,image->rows,exception); 175 if (status == MagickFalse) 176 return(DestroyImageList(image)); 177 /* 178 Read hex image data. 179 */ 180 data=(unsigned char *) AcquireQuantumMemory(image->rows,image->columns* 181 sizeof(*data)); 182 if (data == (unsigned char *) NULL) 183 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 184 p=data; 185 for (i=0; i < (ssize_t) (image->columns * image->rows); i++) 186 { 187 *p++=ReadBlobByte(image); 188 } 189 190 /* 191 Convert RGF image to pixel packets. 192 */ 193 p=data; 194 for (y=0; y < (ssize_t) image->rows; y++) 195 { 196 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); 197 if (q == (Quantum *) NULL) 198 break; 199 bit=0; 200 byte=0; 201 for (x=0; x < (ssize_t) image->columns; x++) 202 { 203 if (bit == 0) 204 byte=(size_t) (*p++); 205 SetPixelIndex(image,(Quantum) ((byte & 0x01) != 0 ? 0x01 : 0x00),q); 206 bit++; 207 byte>>=1; 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 data=(unsigned char *) RelinquishMagickMemory(data); 220 (void) SyncImage(image,exception); 221 (void) CloseBlob(image); 222 return(GetFirstImageInList(image)); 223 } 224 225 /* 227 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 228 % % 229 % % 230 % % 231 % R e g i s t e r R G F I m a g e % 232 % % 233 % % 234 % % 235 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 236 % 237 % RegisterRGFImage() adds attributes for the RGF image format to 238 % the list of supported formats. The attributes include the image format 239 % tag, a method to read and/or write the format, whether the format 240 % supports the saving of more than one frame to the same file or blob, 241 % whether the format supports native in-memory I/O, and a brief 242 % description of the format. 243 % 244 % The format of the RegisterRGFImage method is: 245 % 246 % size_t RegisterRGFImage(void) 247 % 248 */ 249 ModuleExport size_t RegisterRGFImage(void) 250 { 251 MagickInfo 252 *entry; 253 254 entry=AcquireMagickInfo("RGF","RGF", 255 "LEGO Mindstorms EV3 Robot Graphic Format (black and white)"); 256 entry->decoder=(DecodeImageHandler *) ReadRGFImage; 257 entry->encoder=(EncodeImageHandler *) WriteRGFImage; 258 entry->flags^=CoderAdjoinFlag; 259 (void) RegisterMagickInfo(entry); 260 return(MagickImageCoderSignature); 261 } 262 263 /* 265 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 266 % % 267 % % 268 % % 269 % U n r e g i s t e r R G F I m a g e % 270 % % 271 % % 272 % % 273 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 274 % 275 % UnregisterRGFImage() removes format registrations made by the 276 % RGF module from the list of supported formats. 277 % 278 % The format of the UnregisterRGFImage method is: 279 % 280 % UnregisterRGFImage(void) 281 % 282 */ 283 ModuleExport void UnregisterRGFImage(void) 284 { 285 (void) UnregisterMagickInfo("RGF"); 286 } 287 288 /* 290 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 291 % % 292 % % 293 % % 294 % W r i t e R G F I m a g e % 295 % % 296 % % 297 % % 298 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 299 % 300 % WriteRGFImage() writes an image to a file in the X bitmap format. 301 % 302 % The format of the WriteRGFImage method is: 303 % 304 % MagickBooleanType WriteRGFImage(const ImageInfo *image_info, 305 % Image *image,ExceptionInfo *exception) 306 % 307 % A description of each parameter follows. 308 % 309 % o image_info: the image info. 310 % 311 % o image: The image. 312 % 313 % o exception: return any errors or warnings in this structure. 314 % 315 */ 316 static MagickBooleanType WriteRGFImage(const ImageInfo *image_info,Image *image, 317 ExceptionInfo *exception) 318 { 319 MagickBooleanType 320 status; 321 322 register const Quantum 323 *p; 324 325 register ssize_t 326 x; 327 328 size_t 329 bit, 330 byte; 331 332 ssize_t 333 y; 334 335 /* 336 Open output image file. 337 */ 338 assert(image_info != (const ImageInfo *) NULL); 339 assert(image_info->signature == MagickCoreSignature); 340 assert(image != (Image *) NULL); 341 assert(image->signature == MagickCoreSignature); 342 if (image->debug != MagickFalse) 343 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 344 assert(exception != (ExceptionInfo *) NULL); 345 assert(exception->signature == MagickCoreSignature); 346 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception); 347 if (status == MagickFalse) 348 return(status); 349 (void) TransformImageColorspace(image,sRGBColorspace,exception); 350 if((image->columns > 255L) || (image->rows > 255L)) 351 ThrowWriterException(ImageError,"Dimensions must be less than 255x255"); 352 /* 353 Write header (just the image dimensions) 354 */ 355 (void) WriteBlobByte(image,image->columns & 0xff); 356 (void) WriteBlobByte(image,image->rows & 0xff); 357 /* 358 Convert MIFF to bit pixels. 359 */ 360 (void) SetImageType(image,BilevelType,exception); 361 x=0; 362 y=0; 363 for (y=0; y < (ssize_t) image->rows; y++) 364 { 365 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 366 if (p == (const Quantum *) NULL) 367 break; 368 bit=0; 369 byte=0; 370 for (x=0; x < (ssize_t) image->columns; x++) 371 { 372 byte>>=1; 373 if (GetPixelLuma(image,p) < (QuantumRange/2.0)) 374 byte|=0x80; 375 bit++; 376 if (bit == 8) 377 { 378 /* 379 Write a bitmap byte to the image file. 380 */ 381 (void) WriteBlobByte(image,(unsigned char) byte); 382 bit=0; 383 byte=0; 384 } 385 p+=GetPixelChannels(image); 386 } 387 if (bit != 0) 388 (void) WriteBlobByte(image,(unsigned char) byte); 389 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, 390 image->rows); 391 if (status == MagickFalse) 392 break; 393 } 394 (void) CloseBlob(image); 395 return(MagickTrue); 396 } 397