otb.c revision 1454be7db7a897f42cd40e4165f945d77196a6f8
1/* 2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3% % 4% % 5% % 6% OOO TTTTT BBBB % 7% O O T B B % 8% O O T BBBB % 9% O O T B B % 10% OOO T BBBB % 11% % 12% % 13% Read/Write On-The-Air Image Format % 14% % 15% Software Design % 16% John Cristy % 17% January 2000 % 18% % 19% % 20% Copyright 1999-2012 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/blob.h" 43#include "MagickCore/blob-private.h" 44#include "MagickCore/cache.h" 45#include "MagickCore/color-private.h" 46#include "MagickCore/colormap.h" 47#include "MagickCore/colorspace.h" 48#include "MagickCore/colorspace-private.h" 49#include "MagickCore/exception.h" 50#include "MagickCore/exception-private.h" 51#include "MagickCore/image.h" 52#include "MagickCore/image-private.h" 53#include "MagickCore/list.h" 54#include "MagickCore/magick.h" 55#include "MagickCore/memory_.h" 56#include "MagickCore/monitor.h" 57#include "MagickCore/monitor-private.h" 58#include "MagickCore/pixel-accessor.h" 59#include "MagickCore/quantum-private.h" 60#include "MagickCore/static.h" 61#include "MagickCore/string_.h" 62#include "MagickCore/module.h" 63 64/* 65 Forward declarations. 66*/ 67static MagickBooleanType 68 WriteOTBImage(const ImageInfo *,Image *,ExceptionInfo *); 69 70/* 71%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 72% % 73% % 74% % 75% R e a d O T B I m a g e % 76% % 77% % 78% % 79%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 80% 81% ReadOTBImage() reads a on-the-air (level 0) bitmap and returns it. It 82% allocates the memory necessary for the new Image structure and returns a 83% pointer to the new image. 84% 85% The format of the ReadOTBImage method is: 86% 87% Image *ReadOTBImage(const ImageInfo *image_info,ExceptionInfo *exception) 88% 89% A description of each parameter follows: 90% 91% o image_info: the image info. 92% 93% o exception: return any errors or warnings in this structure. 94% 95% 96*/ 97static Image *ReadOTBImage(const ImageInfo *image_info,ExceptionInfo *exception) 98{ 99#define GetBit(a,i) (((a) >> (i)) & 1L) 100 101 Image 102 *image; 103 104 int 105 byte; 106 107 MagickBooleanType 108 status; 109 110 register ssize_t 111 x; 112 113 register Quantum 114 *q; 115 116 ssize_t 117 y; 118 119 unsigned char 120 bit, 121 info, 122 depth; 123 124 /* 125 Open image file. 126 */ 127 assert(image_info != (const ImageInfo *) NULL); 128 assert(image_info->signature == MagickSignature); 129 if (image_info->debug != MagickFalse) 130 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 131 image_info->filename); 132 assert(exception != (ExceptionInfo *) NULL); 133 assert(exception->signature == MagickSignature); 134 image=AcquireImage(image_info,exception); 135 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); 136 if (status == MagickFalse) 137 { 138 image=DestroyImageList(image); 139 return((Image *) NULL); 140 } 141 /* 142 Initialize image structure. 143 */ 144 info=(unsigned char) ReadBlobByte(image); 145 if (GetBit(info,4) == 0) 146 { 147 image->columns=(size_t) ReadBlobByte(image); 148 image->rows=(size_t) ReadBlobByte(image); 149 } 150 else 151 { 152 image->columns=(size_t) ReadBlobMSBShort(image); 153 image->rows=(size_t) ReadBlobMSBShort(image); 154 } 155 if ((image->columns == 0) || (image->rows == 0)) 156 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 157 depth=(unsigned char) ReadBlobByte(image); 158 if (depth != 1) 159 ThrowReaderException(CoderError,"OnlyLevelZerofilesSupported"); 160 if (AcquireImageColormap(image,2,exception) == MagickFalse) 161 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 162 if (image_info->ping != MagickFalse) 163 { 164 (void) CloseBlob(image); 165 return(GetFirstImageInList(image)); 166 } 167 /* 168 Convert bi-level image to pixel packets. 169 */ 170 for (y=0; y < (ssize_t) image->rows; y++) 171 { 172 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); 173 if (q == (Quantum *) NULL) 174 break; 175 bit=0; 176 byte=0; 177 for (x=0; x < (ssize_t) image->columns; x++) 178 { 179 if (bit == 0) 180 { 181 byte=ReadBlobByte(image); 182 if (byte == EOF) 183 ThrowReaderException(CorruptImageError,"CorruptImage"); 184 } 185 SetPixelIndex(image,(byte & (0x01 << (7-bit))) ? 0x00 : 0x01,q); 186 bit++; 187 if (bit == 8) 188 bit=0; 189 q+=GetPixelChannels(image); 190 } 191 if (SyncAuthenticPixels(image,exception) == MagickFalse) 192 break; 193 if (image->previous == (Image *) NULL) 194 { 195 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y, 196 image->rows); 197 if (status == MagickFalse) 198 break; 199 } 200 } 201 (void) SyncImage(image,exception); 202 if (EOFBlob(image) != MagickFalse) 203 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", 204 image->filename); 205 (void) CloseBlob(image); 206 return(GetFirstImageInList(image)); 207} 208 209/* 210%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 211% % 212% % 213% % 214% R e g i s t e r O T B I m a g e % 215% % 216% % 217% % 218%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 219% 220% RegisterOTBImage() adds attributes for the OTB image format to 221% the list of supported formats. The attributes include the image format 222% tag, a method to read and/or write the format, whether the format 223% supports the saving of more than one frame to the same file or blob, 224% whether the format supports native in-memory I/O, and a brief 225% description of the format. 226% 227% The format of the RegisterOTBImage method is: 228% 229% size_t RegisterOTBImage(void) 230% 231*/ 232ModuleExport size_t RegisterOTBImage(void) 233{ 234 MagickInfo 235 *entry; 236 237 entry=SetMagickInfo("OTB"); 238 entry->decoder=(DecodeImageHandler *) ReadOTBImage; 239 entry->encoder=(EncodeImageHandler *) WriteOTBImage; 240 entry->adjoin=MagickFalse; 241 entry->description=ConstantString("On-the-air bitmap"); 242 entry->module=ConstantString("OTB"); 243 (void) RegisterMagickInfo(entry); 244 return(MagickImageCoderSignature); 245} 246 247/* 248%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 249% % 250% % 251% % 252% U n r e g i s t e r O T B I m a g e % 253% % 254% % 255% % 256%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 257% 258% UnregisterOTBImage() removes format registrations made by the 259% OTB module from the list of supported formats. 260% 261% The format of the UnregisterOTBImage method is: 262% 263% UnregisterOTBImage(void) 264% 265*/ 266ModuleExport void UnregisterOTBImage(void) 267{ 268 (void) UnregisterMagickInfo("OTB"); 269} 270 271/* 272%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 273% % 274% % 275% % 276% W r i t e O T B I m a g e % 277% % 278% % 279% % 280%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 281% 282% WriteOTBImage() writes an image to a file in the On-the-air Bitmap 283% (level 0) image format. 284% 285% The format of the WriteOTBImage method is: 286% 287% MagickBooleanType WriteOTBImage(const ImageInfo *image_info, 288% Image *image,ExceptionInfo *exception) 289% 290% A description of each parameter follows. 291% 292% o image_info: the image info. 293% 294% o image: The image. 295% 296% o exception: return any errors or warnings in this structure. 297% 298*/ 299static MagickBooleanType WriteOTBImage(const ImageInfo *image_info,Image *image, 300 ExceptionInfo *exception) 301{ 302#define SetBit(a,i,set) \ 303 a=(unsigned char) ((set) ? (a) | (1L << (i)) : (a) & ~(1L << (i))) 304 305 MagickBooleanType 306 status; 307 308 register const Quantum 309 *p; 310 311 register ssize_t 312 x; 313 314 ssize_t 315 y; 316 317 unsigned char 318 bit, 319 byte, 320 info; 321 322 /* 323 Open output image file. 324 */ 325 assert(image_info != (const ImageInfo *) NULL); 326 assert(image_info->signature == MagickSignature); 327 assert(image != (Image *) NULL); 328 assert(image->signature == MagickSignature); 329 if (image->debug != MagickFalse) 330 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 331 assert(exception != (ExceptionInfo *) NULL); 332 assert(exception->signature == MagickSignature); 333 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception); 334 if (status == MagickFalse) 335 return(status); 336 if (IsRGBColorspace(image->colorspace) == MagickFalse) 337 (void) TransformImageColorspace(image,RGBColorspace,exception); 338 /* 339 Convert image to a bi-level image. 340 */ 341 (void) SetImageType(image,BilevelType,exception); 342 info=0; 343 if ((image->columns >= 256) || (image->rows >= 256)) 344 SetBit(info,4,1); 345 (void) WriteBlobByte(image,info); 346 if ((image->columns >= 256) || (image->rows >= 256)) 347 { 348 (void) WriteBlobMSBShort(image,(unsigned short) image->columns); 349 (void) WriteBlobMSBShort(image,(unsigned short) image->rows); 350 } 351 else 352 { 353 (void) WriteBlobByte(image,(unsigned char) image->columns); 354 (void) WriteBlobByte(image,(unsigned char) image->rows); 355 } 356 (void) WriteBlobByte(image,1); /* depth */ 357 for (y=0; y < (ssize_t) image->rows; y++) 358 { 359 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 360 if (p == (const Quantum *) NULL) 361 break; 362 bit=0; 363 byte=0; 364 for (x=0; x < (ssize_t) image->columns; x++) 365 { 366 if (GetPixelIntensity(image,p) < ((Quantum) QuantumRange/2.0)) 367 byte|=0x1 << (7-bit); 368 bit++; 369 if (bit == 8) 370 { 371 (void) WriteBlobByte(image,byte); 372 bit=0; 373 byte=0; 374 } 375 p+=GetPixelChannels(image); 376 } 377 if (bit != 0) 378 (void) WriteBlobByte(image,byte); 379 if (image->previous == (Image *) NULL) 380 { 381 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, 382 image->rows); 383 if (status == MagickFalse) 384 break; 385 } 386 } 387 (void) CloseBlob(image); 388 return(MagickTrue); 389} 390