viff.c revision 8a46d827a124555f0c48fb2368ec1bba8e079ab6
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->alpha_trait=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=(double) QuantumRange/min_value; 578 min_value=0; 579 } 580 else 581 scale_factor=(double) 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) < ((double) 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) < ((double) 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->alpha_trait == BlendPixelTrait ? 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 (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse) 978 (void) TransformImageColorspace(image,sRGBColorspace,exception); 979 viff_info.identifier=(char) 0xab; 980 viff_info.file_type=1; 981 viff_info.release=1; 982 viff_info.version=3; 983 viff_info.machine_dependency=VFF_DEP_IEEEORDER; /* IEEE byte ordering */ 984 *viff_info.comment='\0'; 985 value=GetImageProperty(image,"comment",exception); 986 if (value != (const char *) NULL) 987 (void) CopyMagickString(viff_info.comment,value,MagickMin(strlen(value), 988 511)+1); 989 viff_info.rows=image->columns; 990 viff_info.columns=image->rows; 991 viff_info.subrows=0; 992 viff_info.x_offset=(~0); 993 viff_info.y_offset=(~0); 994 viff_info.x_bits_per_pixel=0; 995 viff_info.y_bits_per_pixel=0; 996 viff_info.location_type=VFF_LOC_IMPLICIT; 997 viff_info.location_dimension=0; 998 viff_info.number_of_images=1; 999 viff_info.data_encode_scheme=VFF_DES_RAW; 1000 viff_info.map_scheme=VFF_MS_NONE; 1001 viff_info.map_storage_type=VFF_MAPTYP_NONE; 1002 viff_info.map_rows=0; 1003 viff_info.map_columns=0; 1004 viff_info.map_subrows=0; 1005 viff_info.map_enable=1; /* no colormap */ 1006 viff_info.maps_per_cycle=0; 1007 number_pixels=(MagickSizeType) image->columns*image->rows; 1008 if (image->storage_class == DirectClass) 1009 { 1010 /* 1011 Full color VIFF raster. 1012 */ 1013 viff_info.number_data_bands=image->alpha_trait ? 4UL : 3UL; 1014 viff_info.color_space_model=VFF_CM_genericRGB; 1015 viff_info.data_storage_type=VFF_TYP_1_BYTE; 1016 packets=viff_info.number_data_bands*number_pixels; 1017 } 1018 else 1019 { 1020 viff_info.number_data_bands=1; 1021 viff_info.color_space_model=VFF_CM_NONE; 1022 viff_info.data_storage_type=VFF_TYP_1_BYTE; 1023 packets=number_pixels; 1024 if (IsImageGray(image,exception) == MagickFalse) 1025 { 1026 /* 1027 Colormapped VIFF raster. 1028 */ 1029 viff_info.map_scheme=VFF_MS_ONEPERBAND; 1030 viff_info.map_storage_type=VFF_MAPTYP_1_BYTE; 1031 viff_info.map_rows=3; 1032 viff_info.map_columns=(unsigned int) image->colors; 1033 } 1034 else 1035 if (image->colors <= 2) 1036 { 1037 /* 1038 Monochrome VIFF raster. 1039 */ 1040 viff_info.data_storage_type=VFF_TYP_BIT; 1041 packets=((image->columns+7) >> 3)*image->rows; 1042 } 1043 } 1044 /* 1045 Write VIFF image header (pad to 1024 bytes). 1046 */ 1047 buffer[0]=(unsigned char) viff_info.identifier; 1048 buffer[1]=(unsigned char) viff_info.file_type; 1049 buffer[2]=(unsigned char) viff_info.release; 1050 buffer[3]=(unsigned char) viff_info.version; 1051 buffer[4]=(unsigned char) viff_info.machine_dependency; 1052 buffer[5]=(unsigned char) viff_info.reserve[0]; 1053 buffer[6]=(unsigned char) viff_info.reserve[1]; 1054 buffer[7]=(unsigned char) viff_info.reserve[2]; 1055 (void) WriteBlob(image,8,buffer); 1056 (void) WriteBlob(image,512,(unsigned char *) viff_info.comment); 1057 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.rows); 1058 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.columns); 1059 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.subrows); 1060 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.x_offset); 1061 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.y_offset); 1062 viff_info.x_bits_per_pixel=1U*(63 << 24) | (128 << 16); 1063 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.x_bits_per_pixel); 1064 viff_info.y_bits_per_pixel=1U*(63 << 24) | (128 << 16); 1065 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.y_bits_per_pixel); 1066 (void) WriteBlobMSBLong(image,viff_info.location_type); 1067 (void) WriteBlobMSBLong(image,viff_info.location_dimension); 1068 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.number_of_images); 1069 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.number_data_bands); 1070 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.data_storage_type); 1071 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.data_encode_scheme); 1072 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.map_scheme); 1073 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.map_storage_type); 1074 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.map_rows); 1075 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.map_columns); 1076 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.map_subrows); 1077 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.map_enable); 1078 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.maps_per_cycle); 1079 (void) WriteBlobMSBLong(image,(unsigned int) viff_info.color_space_model); 1080 for (i=0; i < 420; i++) 1081 (void) WriteBlobByte(image,'\0'); 1082 /* 1083 Convert MIFF to VIFF raster pixels. 1084 */ 1085 viff_pixels=(unsigned char *) AcquireQuantumMemory((size_t) packets, 1086 sizeof(*viff_pixels)); 1087 if (viff_pixels == (unsigned char *) NULL) 1088 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); 1089 q=viff_pixels; 1090 if (image->storage_class == DirectClass) 1091 { 1092 /* 1093 Convert DirectClass packet to VIFF RGB pixel. 1094 */ 1095 number_pixels=(MagickSizeType) image->columns*image->rows; 1096 for (y=0; y < (ssize_t) image->rows; y++) 1097 { 1098 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 1099 if (p == (const Quantum *) NULL) 1100 break; 1101 for (x=0; x < (ssize_t) image->columns; x++) 1102 { 1103 *q=ScaleQuantumToChar(GetPixelRed(image,p)); 1104 *(q+number_pixels)=ScaleQuantumToChar(GetPixelGreen(image,p)); 1105 *(q+number_pixels*2)=ScaleQuantumToChar(GetPixelBlue(image,p)); 1106 if (image->alpha_trait == BlendPixelTrait) 1107 *(q+number_pixels*3)=ScaleQuantumToChar((Quantum) 1108 (GetPixelAlpha(image,p))); 1109 p+=GetPixelChannels(image); 1110 q++; 1111 } 1112 if (image->previous == (Image *) NULL) 1113 { 1114 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, 1115 image->rows); 1116 if (status == MagickFalse) 1117 break; 1118 } 1119 } 1120 } 1121 else 1122 if (IsImageGray(image,exception) == MagickFalse) 1123 { 1124 unsigned char 1125 *viff_colormap; 1126 1127 /* 1128 Dump colormap to file. 1129 */ 1130 viff_colormap=(unsigned char *) AcquireQuantumMemory(image->colors, 1131 3*sizeof(*viff_colormap)); 1132 if (viff_colormap == (unsigned char *) NULL) 1133 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); 1134 q=viff_colormap; 1135 for (i=0; i < (ssize_t) image->colors; i++) 1136 *q++=ScaleQuantumToChar(image->colormap[i].red); 1137 for (i=0; i < (ssize_t) image->colors; i++) 1138 *q++=ScaleQuantumToChar(image->colormap[i].green); 1139 for (i=0; i < (ssize_t) image->colors; i++) 1140 *q++=ScaleQuantumToChar(image->colormap[i].blue); 1141 (void) WriteBlob(image,3*image->colors,viff_colormap); 1142 viff_colormap=(unsigned char *) RelinquishMagickMemory(viff_colormap); 1143 /* 1144 Convert PseudoClass packet to VIFF colormapped pixels. 1145 */ 1146 q=viff_pixels; 1147 for (y=0; y < (ssize_t) image->rows; y++) 1148 { 1149 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 1150 if (p == (const Quantum *) NULL) 1151 break; 1152 for (x=0; x < (ssize_t) image->columns; x++) 1153 { 1154 *q++=(unsigned char) GetPixelIndex(image,p); 1155 p+=GetPixelChannels(image); 1156 } 1157 if (image->previous == (Image *) NULL) 1158 { 1159 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, 1160 image->rows); 1161 if (status == MagickFalse) 1162 break; 1163 } 1164 } 1165 } 1166 else 1167 if (image->colors <= 2) 1168 { 1169 ssize_t 1170 x, 1171 y; 1172 1173 register unsigned char 1174 bit, 1175 byte; 1176 1177 /* 1178 Convert PseudoClass image to a VIFF monochrome image. 1179 */ 1180 (void) SetImageType(image,BilevelType,exception); 1181 for (y=0; y < (ssize_t) image->rows; y++) 1182 { 1183 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 1184 if (p == (const Quantum *) NULL) 1185 break; 1186 bit=0; 1187 byte=0; 1188 for (x=0; x < (ssize_t) image->columns; x++) 1189 { 1190 byte>>=1; 1191 if (GetPixelIntensity(image,p) < ((double) QuantumRange/2.0)) 1192 byte|=0x80; 1193 bit++; 1194 if (bit == 8) 1195 { 1196 *q++=byte; 1197 bit=0; 1198 byte=0; 1199 } 1200 p+=GetPixelChannels(image); 1201 } 1202 if (bit != 0) 1203 *q++=byte >> (8-bit); 1204 if (image->previous == (Image *) NULL) 1205 { 1206 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) 1207 y,image->rows); 1208 if (status == MagickFalse) 1209 break; 1210 } 1211 } 1212 } 1213 else 1214 { 1215 /* 1216 Convert PseudoClass packet to VIFF grayscale pixel. 1217 */ 1218 for (y=0; y < (ssize_t) image->rows; y++) 1219 { 1220 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 1221 if (p == (const Quantum *) NULL) 1222 break; 1223 for (x=0; x < (ssize_t) image->columns; x++) 1224 { 1225 *q++=(unsigned char) GetPixelIntensity(image,p); 1226 p+=GetPixelChannels(image); 1227 } 1228 if (image->previous == (Image *) NULL) 1229 { 1230 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) 1231 y,image->rows); 1232 if (status == MagickFalse) 1233 break; 1234 } 1235 } 1236 } 1237 (void) WriteBlob(image,(size_t) packets,viff_pixels); 1238 viff_pixels=(unsigned char *) RelinquishMagickMemory(viff_pixels); 1239 if (GetNextImageInList(image) == (Image *) NULL) 1240 break; 1241 image=SyncNextImageInList(image); 1242 status=SetImageProgress(image,SaveImagesTag,scene++, 1243 GetImageListLength(image)); 1244 if (status == MagickFalse) 1245 break; 1246 } while (image_info->adjoin != MagickFalse); 1247 (void) CloseBlob(image); 1248 return(MagickTrue); 1249} 1250