viff.c revision 501c5597e8d10b6102a4566f2740f4166bdd545f
1/* 2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3% % 4% % 5% % 6% V V IIIII FFFFF FFFFF % 7% V V I F F % 8% V V I FFF FFF % 9% V V I F F % 10% V IIIII F F % 11% % 12% % 13% Read/Write Khoros Visualization Image Format % 14% % 15% Software Design % 16% John Cristy % 17% July 1992 % 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/* 40 Include declarations. 41*/ 42#include "MagickCore/studio.h" 43#include "MagickCore/attribute.h" 44#include "MagickCore/blob.h" 45#include "MagickCore/blob-private.h" 46#include "MagickCore/cache.h" 47#include "MagickCore/color.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/property.h" 63#include "MagickCore/quantum-private.h" 64#include "MagickCore/static.h" 65#include "MagickCore/string_.h" 66#include "MagickCore/module.h" 67 68/* 69 Forward declarations. 70*/ 71static MagickBooleanType 72 WriteVIFFImage(const ImageInfo *,Image *,ExceptionInfo *); 73 74/* 75%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 76% % 77% % 78% % 79% I s V I F F % 80% % 81% % 82% % 83%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 84% 85% IsVIFF() returns MagickTrue if the image format type, identified by the 86% magick string, is VIFF. 87% 88% The format of the IsVIFF method is: 89% 90% MagickBooleanType IsVIFF(const unsigned char *magick,const size_t length) 91% 92% A description of each parameter follows: 93% 94% o magick: compare image format pattern against these bytes. 95% 96% o length: Specifies the length of the magick string. 97% 98*/ 99static MagickBooleanType IsVIFF(const unsigned char *magick,const size_t length) 100{ 101 if (length < 2) 102 return(MagickFalse); 103 if (memcmp(magick,"\253\001",2) == 0) 104 return(MagickTrue); 105 return(MagickFalse); 106} 107 108/* 109%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 110% % 111% % 112% % 113% R e a d V I F F I m a g e % 114% % 115% % 116% % 117%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 118% 119% ReadVIFFImage() reads a Khoros Visualization image file and returns 120% it. It allocates the memory necessary for the new Image structure and 121% returns a pointer to the new image. 122% 123% The format of the ReadVIFFImage method is: 124% 125% Image *ReadVIFFImage(const ImageInfo *image_info, 126% ExceptionInfo *exception) 127% 128% A description of each parameter follows: 129% 130% o image: Method ReadVIFFImage returns a pointer to the image after 131% reading. A null image is returned if there is a memory shortage or if 132% the image cannot be read. 133% 134% o image_info: the image info. 135% 136% o exception: return any errors or warnings in this structure. 137% 138*/ 139static Image *ReadVIFFImage(const ImageInfo *image_info, 140 ExceptionInfo *exception) 141{ 142#define VFF_CM_genericRGB 15 143#define VFF_CM_ntscRGB 1 144#define VFF_CM_NONE 0 145#define VFF_DEP_DECORDER 0x4 146#define VFF_DEP_NSORDER 0x8 147#define VFF_DES_RAW 0 148#define VFF_LOC_IMPLICIT 1 149#define VFF_MAPTYP_NONE 0 150#define VFF_MAPTYP_1_BYTE 1 151#define VFF_MAPTYP_2_BYTE 2 152#define VFF_MAPTYP_4_BYTE 4 153#define VFF_MAPTYP_FLOAT 5 154#define VFF_MAPTYP_DOUBLE 7 155#define VFF_MS_NONE 0 156#define VFF_MS_ONEPERBAND 1 157#define VFF_MS_SHARED 3 158#define VFF_TYP_BIT 0 159#define VFF_TYP_1_BYTE 1 160#define VFF_TYP_2_BYTE 2 161#define VFF_TYP_4_BYTE 4 162#define VFF_TYP_FLOAT 5 163#define VFF_TYP_DOUBLE 9 164 165 typedef struct _ViffInfo 166 { 167 unsigned char 168 identifier, 169 file_type, 170 release, 171 version, 172 machine_dependency, 173 reserve[3]; 174 175 char 176 comment[512]; 177 178 unsigned int 179 rows, 180 columns, 181 subrows; 182 183 int 184 x_offset, 185 y_offset; 186 187 float 188 x_bits_per_pixel, 189 y_bits_per_pixel; 190 191 unsigned int 192 location_type, 193 location_dimension, 194 number_of_images, 195 number_data_bands, 196 data_storage_type, 197 data_encode_scheme, 198 map_scheme, 199 map_storage_type, 200 map_rows, 201 map_columns, 202 map_subrows, 203 map_enable, 204 maps_per_cycle, 205 color_space_model; 206 } ViffInfo; 207 208 double 209 min_value, 210 scale_factor, 211 value; 212 213 Image 214 *image; 215 216 int 217 bit; 218 219 MagickBooleanType 220 status; 221 222 MagickSizeType 223 number_pixels; 224 225 register ssize_t 226 x; 227 228 register Quantum 229 *q; 230 231 register ssize_t 232 i; 233 234 register unsigned char 235 *p; 236 237 size_t 238 bytes_per_pixel, 239 lsb_first, 240 max_packets, 241 quantum; 242 243 ssize_t 244 count, 245 y; 246 247 unsigned char 248 buffer[7], 249 *viff_pixels; 250 251 ViffInfo 252 viff_info; 253 254 /* 255 Open image file. 256 */ 257 assert(image_info != (const ImageInfo *) NULL); 258 assert(image_info->signature == MagickSignature); 259 if (image_info->debug != MagickFalse) 260 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 261 image_info->filename); 262 assert(exception != (ExceptionInfo *) NULL); 263 assert(exception->signature == MagickSignature); 264 image=AcquireImage(image_info,exception); 265 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); 266 if (status == MagickFalse) 267 { 268 image=DestroyImageList(image); 269 return((Image *) NULL); 270 } 271 /* 272 Read VIFF header (1024 bytes). 273 */ 274 count=ReadBlob(image,1,&viff_info.identifier); 275 do 276 { 277 /* 278 Verify VIFF identifier. 279 */ 280 if ((count == 0) || ((unsigned char) viff_info.identifier != 0xab)) 281 ThrowReaderException(CorruptImageError,"NotAVIFFImage"); 282 /* 283 Initialize VIFF image. 284 */ 285 count=ReadBlob(image,7,buffer); 286 viff_info.file_type=buffer[0]; 287 viff_info.release=buffer[1]; 288 viff_info.version=buffer[2]; 289 viff_info.machine_dependency=buffer[3]; 290 count=ReadBlob(image,512,(unsigned char *) viff_info.comment); 291 viff_info.comment[511]='\0'; 292 if (strlen(viff_info.comment) > 4) 293 (void) SetImageProperty(image,"comment",viff_info.comment,exception); 294 if ((viff_info.machine_dependency == VFF_DEP_DECORDER) || 295 (viff_info.machine_dependency == VFF_DEP_NSORDER)) 296 { 297 viff_info.rows=ReadBlobLSBLong(image); 298 viff_info.columns=ReadBlobLSBLong(image); 299 viff_info.subrows=ReadBlobLSBLong(image); 300 viff_info.x_offset=(int) ReadBlobLSBLong(image); 301 viff_info.y_offset=(int) ReadBlobLSBLong(image); 302 viff_info.x_bits_per_pixel=(float) ReadBlobLSBLong(image); 303 viff_info.y_bits_per_pixel=(float) ReadBlobLSBLong(image); 304 viff_info.location_type=ReadBlobLSBLong(image); 305 viff_info.location_dimension=ReadBlobLSBLong(image); 306 viff_info.number_of_images=ReadBlobLSBLong(image); 307 viff_info.number_data_bands=ReadBlobLSBLong(image); 308 viff_info.data_storage_type=ReadBlobLSBLong(image); 309 viff_info.data_encode_scheme=ReadBlobLSBLong(image); 310 viff_info.map_scheme=ReadBlobLSBLong(image); 311 viff_info.map_storage_type=ReadBlobLSBLong(image); 312 viff_info.map_rows=ReadBlobLSBLong(image); 313 viff_info.map_columns=ReadBlobLSBLong(image); 314 viff_info.map_subrows=ReadBlobLSBLong(image); 315 viff_info.map_enable=ReadBlobLSBLong(image); 316 viff_info.maps_per_cycle=ReadBlobLSBLong(image); 317 viff_info.color_space_model=ReadBlobLSBLong(image); 318 } 319 else 320 { 321 viff_info.rows=ReadBlobMSBLong(image); 322 viff_info.columns=ReadBlobMSBLong(image); 323 viff_info.subrows=ReadBlobMSBLong(image); 324 viff_info.x_offset=(int) ReadBlobMSBLong(image); 325 viff_info.y_offset=(int) ReadBlobMSBLong(image); 326 viff_info.x_bits_per_pixel=(float) ReadBlobMSBLong(image); 327 viff_info.y_bits_per_pixel=(float) ReadBlobMSBLong(image); 328 viff_info.location_type=ReadBlobMSBLong(image); 329 viff_info.location_dimension=ReadBlobMSBLong(image); 330 viff_info.number_of_images=ReadBlobMSBLong(image); 331 viff_info.number_data_bands=ReadBlobMSBLong(image); 332 viff_info.data_storage_type=ReadBlobMSBLong(image); 333 viff_info.data_encode_scheme=ReadBlobMSBLong(image); 334 viff_info.map_scheme=ReadBlobMSBLong(image); 335 viff_info.map_storage_type=ReadBlobMSBLong(image); 336 viff_info.map_rows=ReadBlobMSBLong(image); 337 viff_info.map_columns=ReadBlobMSBLong(image); 338 viff_info.map_subrows=ReadBlobMSBLong(image); 339 viff_info.map_enable=ReadBlobMSBLong(image); 340 viff_info.maps_per_cycle=ReadBlobMSBLong(image); 341 viff_info.color_space_model=ReadBlobMSBLong(image); 342 } 343 for (i=0; i < 420; i++) 344 (void) ReadBlobByte(image); 345 image->columns=viff_info.rows; 346 image->rows=viff_info.columns; 347 image->depth=viff_info.x_bits_per_pixel <= 8 ? 8UL : 348 MAGICKCORE_QUANTUM_DEPTH; 349 /* 350 Verify that we can read this VIFF image. 351 */ 352 number_pixels=(MagickSizeType) viff_info.columns*viff_info.rows; 353 if (number_pixels != (size_t) number_pixels) 354 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 355 if (number_pixels == 0) 356 ThrowReaderException(CoderError,"ImageColumnOrRowSizeIsNotSupported"); 357 if ((viff_info.number_data_bands < 1) || (viff_info.number_data_bands > 4)) 358 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 359 if ((viff_info.data_storage_type != VFF_TYP_BIT) && 360 (viff_info.data_storage_type != VFF_TYP_1_BYTE) && 361 (viff_info.data_storage_type != VFF_TYP_2_BYTE) && 362 (viff_info.data_storage_type != VFF_TYP_4_BYTE) && 363 (viff_info.data_storage_type != VFF_TYP_FLOAT) && 364 (viff_info.data_storage_type != VFF_TYP_DOUBLE)) 365 ThrowReaderException(CoderError,"DataStorageTypeIsNotSupported"); 366 if (viff_info.data_encode_scheme != VFF_DES_RAW) 367 ThrowReaderException(CoderError,"DataEncodingSchemeIsNotSupported"); 368 if ((viff_info.map_storage_type != VFF_MAPTYP_NONE) && 369 (viff_info.map_storage_type != VFF_MAPTYP_1_BYTE) && 370 (viff_info.map_storage_type != VFF_MAPTYP_2_BYTE) && 371 (viff_info.map_storage_type != VFF_MAPTYP_4_BYTE) && 372 (viff_info.map_storage_type != VFF_MAPTYP_FLOAT) && 373 (viff_info.map_storage_type != VFF_MAPTYP_DOUBLE)) 374 ThrowReaderException(CoderError,"MapStorageTypeIsNotSupported"); 375 if ((viff_info.color_space_model != VFF_CM_NONE) && 376 (viff_info.color_space_model != VFF_CM_ntscRGB) && 377 (viff_info.color_space_model != VFF_CM_genericRGB)) 378 ThrowReaderException(CoderError,"ColorspaceModelIsNotSupported"); 379 if (viff_info.location_type != VFF_LOC_IMPLICIT) 380 ThrowReaderException(CoderError,"LocationTypeIsNotSupported"); 381 if (viff_info.number_of_images != 1) 382 ThrowReaderException(CoderError,"NumberOfImagesIsNotSupported"); 383 if (viff_info.map_rows == 0) 384 viff_info.map_scheme=VFF_MS_NONE; 385 switch ((int) viff_info.map_scheme) 386 { 387 case VFF_MS_NONE: 388 { 389 if (viff_info.number_data_bands < 3) 390 { 391 /* 392 Create linear color ramp. 393 */ 394 image->colors=image->depth <= 8 ? 256UL : 65536UL; 395 if (viff_info.data_storage_type == VFF_TYP_BIT) 396 image->colors=2; 397 if (AcquireImageColormap(image,image->colors,exception) == MagickFalse) 398 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 399 } 400 break; 401 } 402 case VFF_MS_ONEPERBAND: 403 case VFF_MS_SHARED: 404 { 405 unsigned char 406 *viff_colormap; 407 408 /* 409 Allocate VIFF colormap. 410 */ 411 switch ((int) viff_info.map_storage_type) 412 { 413 case VFF_MAPTYP_1_BYTE: bytes_per_pixel=1; break; 414 case VFF_MAPTYP_2_BYTE: bytes_per_pixel=2; break; 415 case VFF_MAPTYP_4_BYTE: bytes_per_pixel=4; break; 416 case VFF_MAPTYP_FLOAT: bytes_per_pixel=4; break; 417 case VFF_MAPTYP_DOUBLE: bytes_per_pixel=8; break; 418 default: bytes_per_pixel=1; break; 419 } 420 image->colors=viff_info.map_columns; 421 if (AcquireImageColormap(image,image->colors,exception) == MagickFalse) 422 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 423 viff_colormap=(unsigned char *) AcquireQuantumMemory(image->colors, 424 viff_info.map_rows*bytes_per_pixel*sizeof(*viff_colormap)); 425 if (viff_colormap == (unsigned char *) NULL) 426 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 427 /* 428 Read VIFF raster colormap. 429 */ 430 count=ReadBlob(image,bytes_per_pixel*image->colors*viff_info.map_rows, 431 viff_colormap); 432 lsb_first=1; 433 if (*(char *) &lsb_first && 434 ((viff_info.machine_dependency != VFF_DEP_DECORDER) && 435 (viff_info.machine_dependency != VFF_DEP_NSORDER))) 436 switch ((int) viff_info.map_storage_type) 437 { 438 case VFF_MAPTYP_2_BYTE: 439 { 440 MSBOrderShort(viff_colormap,(bytes_per_pixel*image->colors* 441 viff_info.map_rows)); 442 break; 443 } 444 case VFF_MAPTYP_4_BYTE: 445 case VFF_MAPTYP_FLOAT: 446 { 447 MSBOrderLong(viff_colormap,(bytes_per_pixel*image->colors* 448 viff_info.map_rows)); 449 break; 450 } 451 default: break; 452 } 453 for (i=0; i < (ssize_t) (viff_info.map_rows*image->colors); i++) 454 { 455 switch ((int) viff_info.map_storage_type) 456 { 457 case VFF_MAPTYP_2_BYTE: value=1.0*((short *) viff_colormap)[i]; break; 458 case VFF_MAPTYP_4_BYTE: value=1.0*((int *) viff_colormap)[i]; break; 459 case VFF_MAPTYP_FLOAT: value=((float *) viff_colormap)[i]; break; 460 case VFF_MAPTYP_DOUBLE: value=((double *) viff_colormap)[i]; break; 461 default: value=1.0*viff_colormap[i]; break; 462 } 463 if (i < (ssize_t) image->colors) 464 { 465 image->colormap[i].red=ScaleCharToQuantum((unsigned char) value); 466 image->colormap[i].green= 467 ScaleCharToQuantum((unsigned char) value); 468 image->colormap[i].blue=ScaleCharToQuantum((unsigned char) value); 469 } 470 else 471 if (i < (ssize_t) (2*image->colors)) 472 image->colormap[i % image->colors].green= 473 ScaleCharToQuantum((unsigned char) value); 474 else 475 if (i < (ssize_t) (3*image->colors)) 476 image->colormap[i % image->colors].blue= 477 ScaleCharToQuantum((unsigned char) value); 478 } 479 viff_colormap=(unsigned char *) RelinquishMagickMemory(viff_colormap); 480 break; 481 } 482 default: 483 ThrowReaderException(CoderError,"ColormapTypeNotSupported"); 484 } 485 /* 486 Initialize image structure. 487 */ 488 image->matte=viff_info.number_data_bands == 4 ? MagickTrue : MagickFalse; 489 image->storage_class= 490 (viff_info.number_data_bands < 3 ? PseudoClass : DirectClass); 491 image->columns=viff_info.rows; 492 image->rows=viff_info.columns; 493 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0)) 494 if (image->scene >= (image_info->scene+image_info->number_scenes-1)) 495 break; 496 /* 497 Allocate VIFF pixels. 498 */ 499 switch ((int) viff_info.data_storage_type) 500 { 501 case VFF_TYP_2_BYTE: bytes_per_pixel=2; break; 502 case VFF_TYP_4_BYTE: bytes_per_pixel=4; break; 503 case VFF_TYP_FLOAT: bytes_per_pixel=4; break; 504 case VFF_TYP_DOUBLE: bytes_per_pixel=8; break; 505 default: bytes_per_pixel=1; break; 506 } 507 if (viff_info.data_storage_type == VFF_TYP_BIT) 508 max_packets=((image->columns+7UL) >> 3UL)*image->rows; 509 else 510 max_packets=(size_t) (number_pixels*viff_info.number_data_bands); 511 viff_pixels=(unsigned char *) AcquireQuantumMemory(max_packets, 512 bytes_per_pixel*sizeof(*viff_pixels)); 513 if (viff_pixels == (unsigned char *) NULL) 514 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 515 count=ReadBlob(image,bytes_per_pixel*max_packets,viff_pixels); 516 lsb_first=1; 517 if (*(char *) &lsb_first && 518 ((viff_info.machine_dependency != VFF_DEP_DECORDER) && 519 (viff_info.machine_dependency != VFF_DEP_NSORDER))) 520 switch ((int) viff_info.data_storage_type) 521 { 522 case VFF_TYP_2_BYTE: 523 { 524 MSBOrderShort(viff_pixels,bytes_per_pixel*max_packets); 525 break; 526 } 527 case VFF_TYP_4_BYTE: 528 case VFF_TYP_FLOAT: 529 { 530 MSBOrderLong(viff_pixels,bytes_per_pixel*max_packets); 531 break; 532 } 533 default: break; 534 } 535 min_value=0.0; 536 scale_factor=1.0; 537 if ((viff_info.data_storage_type != VFF_TYP_1_BYTE) && 538 (viff_info.map_scheme == VFF_MS_NONE)) 539 { 540 double 541 max_value; 542 543 /* 544 Determine scale factor. 545 */ 546 switch ((int) viff_info.data_storage_type) 547 { 548 case VFF_TYP_2_BYTE: value=1.0*((short *) viff_pixels)[0]; break; 549 case VFF_TYP_4_BYTE: value=1.0*((int *) viff_pixels)[0]; break; 550 case VFF_TYP_FLOAT: value=((float *) viff_pixels)[0]; break; 551 case VFF_TYP_DOUBLE: value=((double *) viff_pixels)[0]; break; 552 default: value=1.0*viff_pixels[0]; break; 553 } 554 max_value=value; 555 min_value=value; 556 for (i=0; i < (ssize_t) max_packets; i++) 557 { 558 switch ((int) viff_info.data_storage_type) 559 { 560 case VFF_TYP_2_BYTE: value=1.0*((short *) viff_pixels)[i]; break; 561 case VFF_TYP_4_BYTE: value=1.0*((int *) viff_pixels)[i]; break; 562 case VFF_TYP_FLOAT: value=((float *) viff_pixels)[i]; break; 563 case VFF_TYP_DOUBLE: value=((double *) viff_pixels)[i]; break; 564 default: value=1.0*viff_pixels[i]; break; 565 } 566 if (value > max_value) 567 max_value=value; 568 else 569 if (value < min_value) 570 min_value=value; 571 } 572 if ((min_value == 0) && (max_value == 0)) 573 scale_factor=0; 574 else 575 if (min_value == max_value) 576 { 577 scale_factor=(MagickRealType) QuantumRange/min_value; 578 min_value=0; 579 } 580 else 581 scale_factor=(MagickRealType) QuantumRange/(max_value-min_value); 582 } 583 /* 584 Convert pixels to Quantum size. 585 */ 586 p=(unsigned char *) viff_pixels; 587 for (i=0; i < (ssize_t) max_packets; i++) 588 { 589 switch ((int) viff_info.data_storage_type) 590 { 591 case VFF_TYP_2_BYTE: value=1.0*((short *) viff_pixels)[i]; break; 592 case VFF_TYP_4_BYTE: value=1.0*((int *) viff_pixels)[i]; break; 593 case VFF_TYP_FLOAT: value=((float *) viff_pixels)[i]; break; 594 case VFF_TYP_DOUBLE: value=((double *) viff_pixels)[i]; break; 595 default: value=1.0*viff_pixels[i]; break; 596 } 597 if (viff_info.map_scheme == VFF_MS_NONE) 598 { 599 value=(value-min_value)*scale_factor; 600 if (value > QuantumRange) 601 value=QuantumRange; 602 else 603 if (value < 0) 604 value=0; 605 } 606 *p=(unsigned char) value; 607 p++; 608 } 609 /* 610 Convert VIFF raster image to pixel packets. 611 */ 612 p=(unsigned char *) viff_pixels; 613 if (viff_info.data_storage_type == VFF_TYP_BIT) 614 { 615 /* 616 Convert bitmap scanline. 617 */ 618 (void) SetImageType(image,BilevelType,exception); 619 (void) SetImageType(image,PaletteType,exception); 620 for (y=0; y < (ssize_t) image->rows; y++) 621 { 622 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); 623 if (q == (Quantum *) NULL) 624 break; 625 for (x=0; x < (ssize_t) (image->columns-7); x+=8) 626 { 627 for (bit=0; bit < 8; bit++) 628 { 629 if (GetPixelIntensity(image,q) < ((MagickRealType) QuantumRange/2.0)) 630 { 631 quantum=(size_t) GetPixelIndex(image,q); 632 quantum|=0x01; 633 SetPixelIndex(image,quantum,q); 634 } 635 q+=GetPixelChannels(image); 636 } 637 p++; 638 } 639 if ((image->columns % 8) != 0) 640 { 641 for (bit=0; bit < (ssize_t) (image->columns % 8); bit++) 642 if (GetPixelIntensity(image,q) < ((MagickRealType) QuantumRange/2.0)) 643 { 644 quantum=(size_t) GetPixelIndex(image,q); 645 quantum|=0x01; 646 SetPixelIndex(image,quantum,q); 647 q+=GetPixelChannels(image); 648 } 649 p++; 650 } 651 if (SyncAuthenticPixels(image,exception) == MagickFalse) 652 break; 653 if (image->previous == (Image *) NULL) 654 { 655 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y, 656 image->rows); 657 if (status == MagickFalse) 658 break; 659 } 660 } 661 } 662 else 663 if (image->storage_class == PseudoClass) 664 for (y=0; y < (ssize_t) image->rows; y++) 665 { 666 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); 667 if (q == (Quantum *) NULL) 668 break; 669 for (x=0; x < (ssize_t) image->columns; x++) 670 { 671 SetPixelIndex(image,*p++,q); 672 q+=GetPixelChannels(image); 673 } 674 if (SyncAuthenticPixels(image,exception) == MagickFalse) 675 break; 676 if (image->previous == (Image *) NULL) 677 { 678 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y, 679 image->rows); 680 if (status == MagickFalse) 681 break; 682 } 683 } 684 else 685 { 686 /* 687 Convert DirectColor scanline. 688 */ 689 number_pixels=(MagickSizeType) image->columns*image->rows; 690 for (y=0; y < (ssize_t) image->rows; y++) 691 { 692 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); 693 if (q == (Quantum *) NULL) 694 break; 695 for (x=0; x < (ssize_t) image->columns; x++) 696 { 697 SetPixelRed(image,ScaleCharToQuantum(*p),q); 698 SetPixelGreen(image,ScaleCharToQuantum(*(p+number_pixels)),q); 699 SetPixelBlue(image,ScaleCharToQuantum(*(p+2*number_pixels)),q); 700 if (image->colors != 0) 701 { 702 SetPixelRed(image,image->colormap[(ssize_t) 703 GetPixelRed(image,q)].red,q); 704 SetPixelGreen(image,image->colormap[(ssize_t) 705 GetPixelGreen(image,q)].green,q); 706 SetPixelBlue(image,image->colormap[(ssize_t) 707 GetPixelBlue(image,q)].blue,q); 708 } 709 SetPixelAlpha(image,image->matte != MagickFalse ? 710 ScaleCharToQuantum(*(p+number_pixels*3)) : OpaqueAlpha,q); 711 p++; 712 q+=GetPixelChannels(image); 713 } 714 if (SyncAuthenticPixels(image,exception) == MagickFalse) 715 break; 716 if (image->previous == (Image *) NULL) 717 { 718 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y, 719 image->rows); 720 if (status == MagickFalse) 721 break; 722 } 723 } 724 } 725 viff_pixels=(unsigned char *) RelinquishMagickMemory(viff_pixels); 726 if (image->storage_class == PseudoClass) 727 (void) SyncImage(image,exception); 728 if (EOFBlob(image) != MagickFalse) 729 { 730 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", 731 image->filename); 732 break; 733 } 734 /* 735 Proceed to next image. 736 */ 737 if (image_info->number_scenes != 0) 738 if (image->scene >= (image_info->scene+image_info->number_scenes-1)) 739 break; 740 count=ReadBlob(image,1,&viff_info.identifier); 741 if ((count != 0) && (viff_info.identifier == 0xab)) 742 { 743 /* 744 Allocate next image structure. 745 */ 746 AcquireNextImage(image_info,image,exception); 747 if (GetNextImageInList(image) == (Image *) NULL) 748 { 749 image=DestroyImageList(image); 750 return((Image *) NULL); 751 } 752 image=SyncNextImageInList(image); 753 status=SetImageProgress(image,LoadImagesTag,TellBlob(image), 754 GetBlobSize(image)); 755 if (status == MagickFalse) 756 break; 757 } 758 } while ((count != 0) && (viff_info.identifier == 0xab)); 759 (void) CloseBlob(image); 760 return(GetFirstImageInList(image)); 761} 762 763/* 764%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 765% % 766% % 767% % 768% R e g i s t e r V I F F I m a g e % 769% % 770% % 771% % 772%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 773% 774% RegisterVIFFImage() adds properties for the VIFF image format to 775% the list of supported formats. The properties include the image format 776% tag, a method to read and/or write the format, whether the format 777% supports the saving of more than one frame to the same file or blob, 778% whether the format supports native in-memory I/O, and a brief 779% description of the format. 780% 781% The format of the RegisterVIFFImage method is: 782% 783% size_t RegisterVIFFImage(void) 784% 785*/ 786ModuleExport size_t RegisterVIFFImage(void) 787{ 788 MagickInfo 789 *entry; 790 791 entry=SetMagickInfo("VIFF"); 792 entry->decoder=(DecodeImageHandler *) ReadVIFFImage; 793 entry->encoder=(EncodeImageHandler *) WriteVIFFImage; 794 entry->magick=(IsImageFormatHandler *) IsVIFF; 795 entry->description=ConstantString("Khoros Visualization image"); 796 entry->module=ConstantString("VIFF"); 797 (void) RegisterMagickInfo(entry); 798 entry=SetMagickInfo("XV"); 799 entry->decoder=(DecodeImageHandler *) ReadVIFFImage; 800 entry->encoder=(EncodeImageHandler *) WriteVIFFImage; 801 entry->description=ConstantString("Khoros Visualization image"); 802 entry->module=ConstantString("VIFF"); 803 (void) RegisterMagickInfo(entry); 804 return(MagickImageCoderSignature); 805} 806 807/* 808%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 809% % 810% % 811% % 812% U n r e g i s t e r V I F F I m a g e % 813% % 814% % 815% % 816%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 817% 818% UnregisterVIFFImage() removes format registrations made by the 819% VIFF module from the list of supported formats. 820% 821% The format of the UnregisterVIFFImage method is: 822% 823% UnregisterVIFFImage(void) 824% 825*/ 826ModuleExport void UnregisterVIFFImage(void) 827{ 828 (void) UnregisterMagickInfo("VIFF"); 829 (void) UnregisterMagickInfo("XV"); 830} 831 832/* 833%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 834% % 835% % 836% % 837% W r i t e V I F F I m a g e % 838% % 839% % 840% % 841%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 842% 843% WriteVIFFImage() writes an image to a file in the VIFF image format. 844% 845% The format of the WriteVIFFImage method is: 846% 847% MagickBooleanType WriteVIFFImage(const ImageInfo *image_info, 848% Image *image,ExceptionInfo *exception) 849% 850% A description of each parameter follows. 851% 852% o image_info: the image info. 853% 854% o image: The image. 855% 856% o exception: return any errors or warnings in this structure. 857% 858*/ 859 860static inline size_t MagickMin(const size_t x,const size_t y) 861{ 862 if (x < y) 863 return(x); 864 return(y); 865} 866 867static MagickBooleanType WriteVIFFImage(const ImageInfo *image_info, 868 Image *image,ExceptionInfo *exception) 869{ 870#define VFF_CM_genericRGB 15 871#define VFF_CM_NONE 0 872#define VFF_DEP_IEEEORDER 0x2 873#define VFF_DES_RAW 0 874#define VFF_LOC_IMPLICIT 1 875#define VFF_MAPTYP_NONE 0 876#define VFF_MAPTYP_1_BYTE 1 877#define VFF_MS_NONE 0 878#define VFF_MS_ONEPERBAND 1 879#define VFF_TYP_BIT 0 880#define VFF_TYP_1_BYTE 1 881 882 typedef struct _ViffInfo 883 { 884 char 885 identifier, 886 file_type, 887 release, 888 version, 889 machine_dependency, 890 reserve[3], 891 comment[512]; 892 893 size_t 894 rows, 895 columns, 896 subrows; 897 898 int 899 x_offset, 900 y_offset; 901 902 unsigned int 903 x_bits_per_pixel, 904 y_bits_per_pixel, 905 location_type, 906 location_dimension, 907 number_of_images, 908 number_data_bands, 909 data_storage_type, 910 data_encode_scheme, 911 map_scheme, 912 map_storage_type, 913 map_rows, 914 map_columns, 915 map_subrows, 916 map_enable, 917 maps_per_cycle, 918 color_space_model; 919 } ViffInfo; 920 921 const char 922 *value; 923 924 MagickBooleanType 925 status; 926 927 MagickOffsetType 928 scene; 929 930 MagickSizeType 931 number_pixels, 932 packets; 933 934 register const Quantum 935 *p; 936 937 register ssize_t 938 x; 939 940 register ssize_t 941 i; 942 943 register unsigned char 944 *q; 945 946 ssize_t 947 y; 948 949 unsigned char 950 buffer[8], 951 *viff_pixels; 952 953 ViffInfo 954 viff_info; 955 956 /* 957 Open output image file. 958 */ 959 assert(image_info != (const ImageInfo *) NULL); 960 assert(image_info->signature == MagickSignature); 961 assert(image != (Image *) NULL); 962 assert(image->signature == MagickSignature); 963 if (image->debug != MagickFalse) 964 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 965 assert(exception != (ExceptionInfo *) NULL); 966 assert(exception->signature == MagickSignature); 967 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception); 968 if (status == MagickFalse) 969 return(status); 970 (void) ResetMagickMemory(&viff_info,0,sizeof(ViffInfo)); 971 scene=0; 972 do 973 { 974 /* 975 Initialize VIFF image structure. 976 */ 977 if (IssRGBColorspace(image->colorspace) == MagickFalse) 978 (void) TransformImageColorspace(image,sRGBColorspace,exception); 979 if (IsImageGray(image,exception) != MagickFalse) 980 (void) SetImageStorageClass(image,DirectClass,exception); 981 viff_info.identifier=(char) 0xab; 982 viff_info.file_type=1; 983 viff_info.release=1; 984 viff_info.version=3; 985 viff_info.machine_dependency=VFF_DEP_IEEEORDER; /* IEEE byte ordering */ 986 *viff_info.comment='\0'; 987 value=GetImageProperty(image,"comment",exception); 988 if (value != (const char *) NULL) 989 (void) CopyMagickString(viff_info.comment,value,MagickMin(strlen(value), 990 511)+1); 991 viff_info.rows=image->columns; 992 viff_info.columns=image->rows; 993 viff_info.subrows=0; 994 viff_info.x_offset=(~0); 995 viff_info.y_offset=(~0); 996 viff_info.x_bits_per_pixel=0; 997 viff_info.y_bits_per_pixel=0; 998 viff_info.location_type=VFF_LOC_IMPLICIT; 999 viff_info.location_dimension=0; 1000 viff_info.number_of_images=1; 1001 viff_info.data_encode_scheme=VFF_DES_RAW; 1002 viff_info.map_scheme=VFF_MS_NONE; 1003 viff_info.map_storage_type=VFF_MAPTYP_NONE; 1004 viff_info.map_rows=0; 1005 viff_info.map_columns=0; 1006 viff_info.map_subrows=0; 1007 viff_info.map_enable=1; /* no colormap */ 1008 viff_info.maps_per_cycle=0; 1009 number_pixels=(MagickSizeType) image->columns*image->rows; 1010 if (image->storage_class == DirectClass) 1011 { 1012 /* 1013 Full color VIFF raster. 1014 */ 1015 viff_info.number_data_bands=image->matte ? 4UL : 3UL; 1016 viff_info.color_space_model=VFF_CM_genericRGB; 1017 viff_info.data_storage_type=VFF_TYP_1_BYTE; 1018 packets=viff_info.number_data_bands*number_pixels; 1019 } 1020 else 1021 { 1022 viff_info.number_data_bands=1; 1023 viff_info.color_space_model=VFF_CM_NONE; 1024 viff_info.data_storage_type=VFF_TYP_1_BYTE; 1025 packets=number_pixels; 1026 if (IsImageGray(image,exception) == MagickFalse) 1027 { 1028 /* 1029 Colormapped VIFF raster. 1030 */ 1031 viff_info.map_scheme=VFF_MS_ONEPERBAND; 1032 viff_info.map_storage_type=VFF_MAPTYP_1_BYTE; 1033 viff_info.map_rows=3; 1034 viff_info.map_columns=(unsigned int) image->colors; 1035 } 1036 else 1037 if (image->colors <= 2) 1038 { 1039 /* 1040 Monochrome VIFF raster. 1041 */ 1042 viff_info.data_storage_type=VFF_TYP_BIT; 1043 packets=((image->columns+7) >> 3)*image->rows; 1044 } 1045 } 1046 /* 1047 Write VIFF image header (pad to 1024 bytes). 1048 */ 1049 buffer[0]=(unsigned char) viff_info.identifier; 1050 buffer[1]=(unsigned char) viff_info.file_type; 1051 buffer[2]=(unsigned char) viff_info.release; 1052 buffer[3]=(unsigned char) viff_info.version; 1053 buffer[4]=(unsigned char) viff_info.machine_dependency; 1054 buffer[5]=(unsigned char) viff_info.reserve[0]; 1055 buffer[6]=(unsigned char) viff_info.reserve[1]; 1056 buffer[7]=(unsigned char) viff_info.reserve[2]; 1057 (void) WriteBlob(image,8,buffer); 1058 (void) WriteBlob(image,512,(unsigned char *) viff_info.comment); 1059 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.rows); 1060 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.columns); 1061 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.subrows); 1062 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.x_offset); 1063 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.y_offset); 1064 viff_info.x_bits_per_pixel=1U*(63 << 24) | (128 << 16); 1065 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.x_bits_per_pixel); 1066 viff_info.y_bits_per_pixel=1U*(63 << 24) | (128 << 16); 1067 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.y_bits_per_pixel); 1068 (void) WriteBlobMSBLong(image,viff_info.location_type); 1069 (void) WriteBlobMSBLong(image,viff_info.location_dimension); 1070 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.number_of_images); 1071 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.number_data_bands); 1072 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.data_storage_type); 1073 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.data_encode_scheme); 1074 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.map_scheme); 1075 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.map_storage_type); 1076 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.map_rows); 1077 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.map_columns); 1078 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.map_subrows); 1079 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.map_enable); 1080 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.maps_per_cycle); 1081 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.color_space_model); 1082 for (i=0; i < 420; i++) 1083 (void) WriteBlobByte(image,'\0'); 1084 /* 1085 Convert MIFF to VIFF raster pixels. 1086 */ 1087 viff_pixels=(unsigned char *) AcquireQuantumMemory((size_t) packets, 1088 sizeof(*viff_pixels)); 1089 if (viff_pixels == (unsigned char *) NULL) 1090 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); 1091 q=viff_pixels; 1092 if (image->storage_class == DirectClass) 1093 { 1094 /* 1095 Convert DirectClass packet to VIFF RGB pixel. 1096 */ 1097 number_pixels=(MagickSizeType) image->columns*image->rows; 1098 for (y=0; y < (ssize_t) image->rows; y++) 1099 { 1100 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 1101 if (p == (const Quantum *) NULL) 1102 break; 1103 for (x=0; x < (ssize_t) image->columns; x++) 1104 { 1105 *q=ScaleQuantumToChar(GetPixelRed(image,p)); 1106 *(q+number_pixels)=ScaleQuantumToChar(GetPixelGreen(image,p)); 1107 *(q+number_pixels*2)=ScaleQuantumToChar(GetPixelBlue(image,p)); 1108 if (image->matte != MagickFalse) 1109 *(q+number_pixels*3)=ScaleQuantumToChar((Quantum) 1110 (GetPixelAlpha(image,p))); 1111 p+=GetPixelChannels(image); 1112 q++; 1113 } 1114 if (image->previous == (Image *) NULL) 1115 { 1116 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, 1117 image->rows); 1118 if (status == MagickFalse) 1119 break; 1120 } 1121 } 1122 } 1123 else 1124 if (IsImageGray(image,exception) == MagickFalse) 1125 { 1126 unsigned char 1127 *viff_colormap; 1128 1129 /* 1130 Dump colormap to file. 1131 */ 1132 viff_colormap=(unsigned char *) AcquireQuantumMemory(image->colors, 1133 3*sizeof(*viff_colormap)); 1134 if (viff_colormap == (unsigned char *) NULL) 1135 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); 1136 q=viff_colormap; 1137 for (i=0; i < (ssize_t) image->colors; i++) 1138 *q++=ScaleQuantumToChar(image->colormap[i].red); 1139 for (i=0; i < (ssize_t) image->colors; i++) 1140 *q++=ScaleQuantumToChar(image->colormap[i].green); 1141 for (i=0; i < (ssize_t) image->colors; i++) 1142 *q++=ScaleQuantumToChar(image->colormap[i].blue); 1143 (void) WriteBlob(image,3*image->colors,viff_colormap); 1144 viff_colormap=(unsigned char *) RelinquishMagickMemory(viff_colormap); 1145 /* 1146 Convert PseudoClass packet to VIFF colormapped pixels. 1147 */ 1148 q=viff_pixels; 1149 for (y=0; y < (ssize_t) image->rows; y++) 1150 { 1151 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 1152 if (p == (const Quantum *) NULL) 1153 break; 1154 for (x=0; x < (ssize_t) image->columns; x++) 1155 { 1156 *q++=(unsigned char) GetPixelIndex(image,p); 1157 p+=GetPixelChannels(image); 1158 } 1159 if (image->previous == (Image *) NULL) 1160 { 1161 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, 1162 image->rows); 1163 if (status == MagickFalse) 1164 break; 1165 } 1166 } 1167 } 1168 else 1169 if (image->colors <= 2) 1170 { 1171 ssize_t 1172 x, 1173 y; 1174 1175 register unsigned char 1176 bit, 1177 byte; 1178 1179 /* 1180 Convert PseudoClass image to a VIFF monochrome image. 1181 */ 1182 (void) SetImageType(image,BilevelType,exception); 1183 for (y=0; y < (ssize_t) image->rows; y++) 1184 { 1185 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 1186 if (p == (const Quantum *) NULL) 1187 break; 1188 bit=0; 1189 byte=0; 1190 for (x=0; x < (ssize_t) image->columns; x++) 1191 { 1192 byte>>=1; 1193 if (GetPixelIntensity(image,p) < ((MagickRealType) QuantumRange/2.0)) 1194 byte|=0x80; 1195 bit++; 1196 if (bit == 8) 1197 { 1198 *q++=byte; 1199 bit=0; 1200 byte=0; 1201 } 1202 p+=GetPixelChannels(image); 1203 } 1204 if (bit != 0) 1205 *q++=byte >> (8-bit); 1206 if (image->previous == (Image *) NULL) 1207 { 1208 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) 1209 y,image->rows); 1210 if (status == MagickFalse) 1211 break; 1212 } 1213 } 1214 } 1215 else 1216 { 1217 /* 1218 Convert PseudoClass packet to VIFF grayscale pixel. 1219 */ 1220 for (y=0; y < (ssize_t) image->rows; y++) 1221 { 1222 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 1223 if (p == (const Quantum *) NULL) 1224 break; 1225 for (x=0; x < (ssize_t) image->columns; x++) 1226 { 1227 *q++=(unsigned char) GetPixelIntensity(image,p); 1228 p+=GetPixelChannels(image); 1229 } 1230 if (image->previous == (Image *) NULL) 1231 { 1232 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) 1233 y,image->rows); 1234 if (status == MagickFalse) 1235 break; 1236 } 1237 } 1238 } 1239 (void) WriteBlob(image,(size_t) packets,viff_pixels); 1240 viff_pixels=(unsigned char *) RelinquishMagickMemory(viff_pixels); 1241 if (GetNextImageInList(image) == (Image *) NULL) 1242 break; 1243 image=SyncNextImageInList(image); 1244 status=SetImageProgress(image,SaveImagesTag,scene++, 1245 GetImageListLength(image)); 1246 if (status == MagickFalse) 1247 break; 1248 } while (image_info->adjoin != MagickFalse); 1249 (void) CloseBlob(image); 1250 return(MagickTrue); 1251} 1252