otb.c revision e7e40559f0408c5f987aec5c1a51c30b0456509f
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-2010 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 "magick/studio.h" 42#include "magick/blob.h" 43#include "magick/blob-private.h" 44#include "magick/cache.h" 45#include "magick/color-private.h" 46#include "magick/colormap.h" 47#include "magick/colorspace.h" 48#include "magick/exception.h" 49#include "magick/exception-private.h" 50#include "magick/image.h" 51#include "magick/image-private.h" 52#include "magick/list.h" 53#include "magick/magick.h" 54#include "magick/memory_.h" 55#include "magick/monitor.h" 56#include "magick/monitor-private.h" 57#include "magick/quantum-private.h" 58#include "magick/static.h" 59#include "magick/string_.h" 60#include "magick/module.h" 61 62/* 63 Forward declarations. 64*/ 65static MagickBooleanType 66 WriteOTBImage(const ImageInfo *,Image *); 67 68/* 69%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 70% % 71% % 72% % 73% R e a d O T B I m a g e % 74% % 75% % 76% % 77%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 78% 79% ReadOTBImage() reads a on-the-air (level 0) bitmap and returns it. It 80% allocates the memory necessary for the new Image structure and returns a 81% pointer to the new image. 82% 83% The format of the ReadOTBImage method is: 84% 85% Image *ReadOTBImage(const ImageInfo *image_info,ExceptionInfo *exception) 86% 87% A description of each parameter follows: 88% 89% o image_info: the image info. 90% 91% o exception: return any errors or warnings in this structure. 92% 93% 94*/ 95static Image *ReadOTBImage(const ImageInfo *image_info,ExceptionInfo *exception) 96{ 97#define GetBit(a,i) (((a) >> (i)) & 1L) 98 99 Image 100 *image; 101 102 int 103 byte; 104 105 long 106 y; 107 108 MagickBooleanType 109 status; 110 111 register IndexPacket 112 *indexes; 113 114 register long 115 x; 116 117 register PixelPacket 118 *q; 119 120 unsigned char 121 bit, 122 info, 123 depth; 124 125 /* 126 Open image file. 127 */ 128 assert(image_info != (const ImageInfo *) NULL); 129 assert(image_info->signature == MagickSignature); 130 if (image_info->debug != MagickFalse) 131 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 132 image_info->filename); 133 assert(exception != (ExceptionInfo *) NULL); 134 assert(exception->signature == MagickSignature); 135 image=AcquireImage(image_info); 136 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); 137 if (status == MagickFalse) 138 { 139 image=DestroyImageList(image); 140 return((Image *) NULL); 141 } 142 /* 143 Initialize image structure. 144 */ 145 info=(unsigned char) ReadBlobByte(image); 146 if (GetBit(info,4) == 0) 147 { 148 image->columns=(unsigned long) ReadBlobByte(image); 149 image->rows=(unsigned long) ReadBlobByte(image); 150 } 151 else 152 { 153 image->columns=(unsigned long) ReadBlobMSBShort(image); 154 image->rows=(unsigned long) ReadBlobMSBShort(image); 155 } 156 if ((image->columns == 0) || (image->rows == 0)) 157 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 158 depth=(unsigned char) ReadBlobByte(image); 159 if (depth != 1) 160 ThrowReaderException(CoderError,"OnlyLevelZerofilesSupported"); 161 if (AcquireImageColormap(image,2) == MagickFalse) 162 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 163 if (image_info->ping != MagickFalse) 164 { 165 (void) CloseBlob(image); 166 return(GetFirstImageInList(image)); 167 } 168 /* 169 Convert bi-level image to pixel packets. 170 */ 171 for (y=0; y < (long) image->rows; y++) 172 { 173 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); 174 if (q == (PixelPacket *) NULL) 175 break; 176 indexes=GetAuthenticIndexQueue(image); 177 bit=0; 178 byte=0; 179 for (x=0; x < (long) image->columns; x++) 180 { 181 if (bit == 0) 182 { 183 byte=ReadBlobByte(image); 184 if (byte == EOF) 185 ThrowReaderException(CorruptImageError,"CorruptImage"); 186 } 187 indexes[x]=(IndexPacket) ((byte & (0x01 << (7-bit))) ? 0x00 : 0x01); 188 bit++; 189 if (bit == 8) 190 bit=0; 191 } 192 if (SyncAuthenticPixels(image,exception) == MagickFalse) 193 break; 194 if (image->previous == (Image *) NULL) 195 { 196 status=SetImageProgress(image,LoadImageTag,y,image->rows); 197 if (status == MagickFalse) 198 break; 199 } 200 } 201 (void) SyncImage(image); 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% unsigned long RegisterOTBImage(void) 230% 231*/ 232ModuleExport unsigned long 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,Image *image) 288% 289% A description of each parameter follows. 290% 291% o image_info: the image info. 292% 293% o image: The image. 294% 295% 296*/ 297static MagickBooleanType WriteOTBImage(const ImageInfo *image_info,Image *image) 298{ 299#define SetBit(a,i,set) \ 300 a=(unsigned char) ((set) ? (a) | (1L << (i)) : (a) & ~(1L << (i))) 301 302 long 303 y; 304 305 MagickBooleanType 306 status; 307 308 register const PixelPacket 309 *p; 310 311 register long 312 x; 313 314 unsigned char 315 bit, 316 byte, 317 info; 318 319 /* 320 Open output image file. 321 */ 322 assert(image_info != (const ImageInfo *) NULL); 323 assert(image_info->signature == MagickSignature); 324 assert(image != (Image *) NULL); 325 assert(image->signature == MagickSignature); 326 if (image->debug != MagickFalse) 327 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 328 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception); 329 if (status == MagickFalse) 330 return(status); 331 if (image->colorspace != RGBColorspace) 332 (void) TransformImageColorspace(image,RGBColorspace); 333 /* 334 Convert image to a bi-level image. 335 */ 336 (void) SetImageType(image,BilevelType); 337 info=0; 338 if ((image->columns >= 256) || (image->rows >= 256)) 339 SetBit(info,4,1); 340 (void) WriteBlobByte(image,info); 341 if ((image->columns >= 256) || (image->rows >= 256)) 342 { 343 (void) WriteBlobMSBShort(image,(unsigned short) image->columns); 344 (void) WriteBlobMSBShort(image,(unsigned short) image->rows); 345 } 346 else 347 { 348 (void) WriteBlobByte(image,(unsigned char) image->columns); 349 (void) WriteBlobByte(image,(unsigned char) image->rows); 350 } 351 (void) WriteBlobByte(image,1); /* depth */ 352 for (y=0; y < (long) image->rows; y++) 353 { 354 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception); 355 if (p == (const PixelPacket *) NULL) 356 break; 357 bit=0; 358 byte=0; 359 for (x=0; x < (long) image->columns; x++) 360 { 361 if (PixelIntensity(p) < ((Quantum) QuantumRange/2.0)) 362 byte|=0x1 << (7-bit); 363 bit++; 364 if (bit == 8) 365 { 366 (void) WriteBlobByte(image,byte); 367 bit=0; 368 byte=0; 369 } 370 p++; 371 } 372 if (bit != 0) 373 (void) WriteBlobByte(image,byte); 374 if (image->previous == (Image *) NULL) 375 { 376 status=SetImageProgress(image,SaveImageTag,y,image->rows); 377 if (status == MagickFalse) 378 break; 379 } 380 } 381 (void) CloseBlob(image); 382 return(MagickTrue); 383} 384