blob: 4f489e0c52f0a759761f9f76141197cc79a31e7f [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% M M PPPP EEEEE GGGG %
7% MM MM P P E G %
8% M M M PPPP EEE G GG %
9% M M P E G G %
10% M M P EEEEE GGGG %
11% %
12% %
13% Read/Write MPEG Image Format %
14% %
15% Software Design %
16% John Cristy %
17% July 1999 %
18% %
19% %
cristy16af1cb2009-12-11 21:38:29 +000020% Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000021% 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/constitute.h"
45#include "magick/delegate.h"
46#include "magick/exception.h"
47#include "magick/exception-private.h"
48#include "magick/geometry.h"
49#include "magick/image.h"
50#include "magick/image-private.h"
51#include "magick/layer.h"
52#include "magick/list.h"
53#include "magick/log.h"
54#include "magick/magick.h"
55#include "magick/memory_.h"
56#include "magick/resource_.h"
57#include "magick/quantum-private.h"
58#include "magick/static.h"
59#include "magick/string_.h"
60#include "magick/module.h"
61#include "magick/transform.h"
62#include "magick/utility.h"
63
64/*
65 Forward declarations.
66*/
67static MagickBooleanType
68 WriteMPEGImage(const ImageInfo *image_info,Image *image);
69
70/*
71%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
72% %
73% %
74% %
cristyaded3262009-10-24 22:47:02 +000075% I s A V I %
76% %
77% %
78% %
79%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
80%
81% IsAVI() returns MagickTrue if the image format type, identified by the
82% magick string, is Audio/Video Interleaved file format.
83%
84% The format of the IsAVI method is:
85%
cristybb503372010-05-27 20:51:26 +000086% size_t IsAVI(const unsigned char *magick,const size_t length)
cristyaded3262009-10-24 22:47:02 +000087%
88% A description of each parameter follows:
89%
90% o magick: compare image format pattern against these bytes.
91%
92% o length: Specifies the length of the magick string.
93%
94*/
95static MagickBooleanType IsAVI(const unsigned char *magick,const size_t length)
96{
97 if (length < 4)
98 return(MagickFalse);
99 if (memcmp(magick,"RIFF",4) == 0)
100 return(MagickTrue);
101 return(MagickFalse);
102}
103
104/*
105%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
106% %
107% %
108% %
cristy3ed852e2009-09-05 21:47:34 +0000109% I s M P E G %
110% %
111% %
112% %
113%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
114%
115% IsMPEG() returns MagickTrue if the image format type, identified by the
116% magick string, is MPEG.
117%
118% The format of the IsMPEG method is:
119%
120% MagickBooleanType IsMPEG(const unsigned char *magick,const size_t length)
121%
122% A description of each parameter follows:
123%
124% o magick: compare image format pattern against these bytes.
125%
126% o length: Specifies the length of the magick string.
127%
128*/
129static MagickBooleanType IsMPEG(const unsigned char *magick,const size_t length)
130{
131 if (length < 4)
132 return(MagickFalse);
133 if (memcmp(magick,"\000\000\001\263",4) == 0)
134 return(MagickTrue);
135 return(MagickFalse);
136}
137
138/*
139%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
140% %
141% %
142% %
143% R e a d M P E G I m a g e %
144% %
145% %
146% %
147%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
148%
149% ReadMPEGImage() reads an binary file in the MPEG video stream format
150% and returns it. It allocates the memory necessary for the new Image
151% structure and returns a pointer to the new image.
152%
153% The format of the ReadMPEGImage method is:
154%
155% Image *ReadMPEGImage(const ImageInfo *image_info,
156% ExceptionInfo *exception)
157%
158% A description of each parameter follows:
159%
160% o image_info: the image info.
161%
162% o exception: return any errors or warnings in this structure.
163%
164*/
165static Image *ReadMPEGImage(const ImageInfo *image_info,
166 ExceptionInfo *exception)
167{
168#define ReadMPEGIntermediateFormat "pam"
169
170 Image
171 *image,
172 *images;
173
174 ImageInfo
175 *read_info;
176
177 MagickBooleanType
178 status;
179
180 /*
181 Open image file.
182 */
183 assert(image_info != (const ImageInfo *) NULL);
184 assert(image_info->signature == MagickSignature);
185 if (image_info->debug != MagickFalse)
186 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
187 image_info->filename);
188 assert(exception != (ExceptionInfo *) NULL);
189 assert(exception->signature == MagickSignature);
190 image=AcquireImage(image_info);
191 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
192 if (status == MagickFalse)
193 {
194 image=DestroyImageList(image);
195 return((Image *) NULL);
196 }
197 (void) CloseBlob(image);
198 (void) DestroyImageList(image);
199 /*
200 Convert MPEG to PAM with delegate.
201 */
202 read_info=CloneImageInfo(image_info);
203 image=AcquireImage(image_info);
204 (void) InvokeDelegate(read_info,image,"mpeg:decode",(char *) NULL,exception);
205 image=DestroyImage(image);
206 (void) FormatMagickString(read_info->filename,MaxTextExtent,"%s.%s",
207 read_info->unique,ReadMPEGIntermediateFormat);
208 images=ReadImage(read_info,exception);
209 (void) RelinquishUniqueFileResource(read_info->filename);
210 read_info=DestroyImageInfo(read_info);
211 return(images);
212}
213
214/*
215%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
216% %
217% %
218% %
219% R e g i s t e r M P E G I m a g e %
220% %
221% %
222% %
223%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
224%
225% RegisterMPEGImage() adds attributes for the MPEG image format to
226% the list of supported formats. The attributes include the image format
227% tag, a method to read and/or write the format, whether the format
228% supports the saving of more than one frame to the same file or blob,
229% whether the format supports native in-memory I/O, and a brief
230% description of the format.
231%
232% The format of the RegisterMPEGImage method is:
233%
cristybb503372010-05-27 20:51:26 +0000234% size_t RegisterMPEGImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000235%
236*/
cristybb503372010-05-27 20:51:26 +0000237ModuleExport size_t RegisterMPEGImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000238{
239 MagickInfo
240 *entry;
241
cristyf34a1452009-10-24 22:29:27 +0000242 entry=SetMagickInfo("AVI");
cristyaded3262009-10-24 22:47:02 +0000243 entry->decoder=(DecodeImageHandler *) ReadMPEGImage;
cristyf34a1452009-10-24 22:29:27 +0000244 entry->magick=(IsImageFormatHandler *) IsAVI;
cristy0fc02592010-05-24 14:12:38 +0000245 entry->blob_support=MagickFalse;
cristyf34a1452009-10-24 22:29:27 +0000246 entry->description=ConstantString("Microsoft Audio/Visual Interleaved");
cristy0fc02592010-05-24 14:12:38 +0000247 entry->module=ConstantString("MPEG");
cristyf34a1452009-10-24 22:29:27 +0000248 (void) RegisterMagickInfo(entry);
cristy3ed852e2009-09-05 21:47:34 +0000249 entry=SetMagickInfo("MOV");
250 entry->decoder=(DecodeImageHandler *) ReadMPEGImage;
251 entry->encoder=(EncodeImageHandler *) WriteMPEGImage;
252 entry->magick=(IsImageFormatHandler *) IsMPEG;
253 entry->blob_support=MagickFalse;
254 entry->description=ConstantString("MPEG Video Stream");
255 entry->module=ConstantString("MPEG");
256 (void) RegisterMagickInfo(entry);
257 entry=SetMagickInfo("MPEG");
258 entry->decoder=(DecodeImageHandler *) ReadMPEGImage;
259 entry->encoder=(EncodeImageHandler *) WriteMPEGImage;
260 entry->magick=(IsImageFormatHandler *) IsMPEG;
261 entry->blob_support=MagickFalse;
262 entry->description=ConstantString("MPEG Video Stream");
263 entry->module=ConstantString("MPEG");
264 (void) RegisterMagickInfo(entry);
265 entry=SetMagickInfo("MPG");
266 entry->decoder=(DecodeImageHandler *) ReadMPEGImage;
267 entry->encoder=(EncodeImageHandler *) WriteMPEGImage;
268 entry->magick=(IsImageFormatHandler *) IsMPEG;
269 entry->blob_support=MagickFalse;
270 entry->description=ConstantString("MPEG Video Stream");
271 entry->module=ConstantString("MPEG");
272 (void) RegisterMagickInfo(entry);
273 entry=SetMagickInfo("MP4");
274 entry->decoder=(DecodeImageHandler *) ReadMPEGImage;
275 entry->encoder=(EncodeImageHandler *) WriteMPEGImage;
276 entry->magick=(IsImageFormatHandler *) IsMPEG;
277 entry->blob_support=MagickFalse;
278 entry->description=ConstantString("MPEG-4 Video Stream");
279 entry->module=ConstantString("MPEG");
280 (void) RegisterMagickInfo(entry);
281 entry=SetMagickInfo("M2V");
282 entry->decoder=(DecodeImageHandler *) ReadMPEGImage;
283 entry->encoder=(EncodeImageHandler *) WriteMPEGImage;
284 entry->magick=(IsImageFormatHandler *) IsMPEG;
285 entry->blob_support=MagickFalse;
286 entry->description=ConstantString("MPEG Video Stream");
287 entry->module=ConstantString("MPEG");
288 (void) RegisterMagickInfo(entry);
289 entry=SetMagickInfo("M4V");
290 entry->decoder=(DecodeImageHandler *) ReadMPEGImage;
291 entry->encoder=(EncodeImageHandler *) WriteMPEGImage;
292 entry->magick=(IsImageFormatHandler *) IsMPEG;
293 entry->blob_support=MagickFalse;
294 entry->description=ConstantString("Raw MPEG-4 Video");
295 entry->module=ConstantString("MPEG");
296 (void) RegisterMagickInfo(entry);
297 entry=SetMagickInfo("WMV");
298 entry->decoder=(DecodeImageHandler *) ReadMPEGImage;
299 entry->encoder=(EncodeImageHandler *) WriteMPEGImage;
300 entry->magick=(IsImageFormatHandler *) IsMPEG;
301 entry->blob_support=MagickFalse;
302 entry->description=ConstantString("Windows Media Video");
303 entry->module=ConstantString("MPEG");
304 (void) RegisterMagickInfo(entry);
305 return(MagickImageCoderSignature);
306}
307
308/*
309%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
310% %
311% %
312% %
313% U n r e g i s t e r M P E G I m a g e %
314% %
315% %
316% %
317%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
318%
319% UnregisterMPEGImage() removes format registrations made by the
320% BIM module from the list of supported formats.
321%
322% The format of the UnregisterBIMImage method is:
323%
324% UnregisterMPEGImage(void)
325%
326*/
327ModuleExport void UnregisterMPEGImage(void)
328{
329 (void) UnregisterMagickInfo("WMV");
330 (void) UnregisterMagickInfo("M4V");
331 (void) UnregisterMagickInfo("M2V");
332 (void) UnregisterMagickInfo("MP4");
333 (void) UnregisterMagickInfo("MPG");
334 (void) UnregisterMagickInfo("MPEG");
335 (void) UnregisterMagickInfo("MOV");
cristyf34a1452009-10-24 22:29:27 +0000336 (void) UnregisterMagickInfo("AVI");
cristy3ed852e2009-09-05 21:47:34 +0000337}
338
339/*
340%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
341% %
342% %
343% %
344% W r i t e M P E G I m a g e %
345% %
346% %
347% %
348%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
349%
350% WriteMPEGImage() writes an image to a file in MPEG video stream format.
351% Lawrence Livermore National Laboratory (LLNL) contributed code to adjust
352% the MPEG parameters to correspond to the compression quality setting.
353%
354% The format of the WriteMPEGImage method is:
355%
356% MagickBooleanType WriteMPEGImage(const ImageInfo *image_info,
357% Image *image)
358%
359% A description of each parameter follows.
360%
361% o image_info: the image info.
362%
363% o image: The image.
364%
365*/
366
367static inline double MagickMax(const double x,const double y)
368{
369 if (x > y)
370 return(x);
371 return(y);
372}
373
374static inline double MagickMin(const double x,const double y)
375{
376 if (x < y)
377 return(x);
378 return(y);
379}
380
381static MagickBooleanType CopyDelegateFile(const char *source,
382 const char *destination)
383{
384 int
385 destination_file,
386 source_file;
387
388 MagickBooleanType
389 status;
390
391 register size_t
392 i;
393
394 size_t
395 length,
396 quantum;
397
398 ssize_t
399 count;
400
401 struct stat
402 attributes;
403
404 unsigned char
405 *buffer;
406
407 /*
408 Return if destination file already exists and is not empty.
409 */
410 assert(source != (const char *) NULL);
411 assert(destination != (char *) NULL);
412 status=GetPathAttributes(destination,&attributes);
413 if ((status != MagickFalse) && (attributes.st_size != 0))
414 return(MagickTrue);
415 /*
416 Copy source file to destination.
417 */
418 destination_file=open(destination,O_WRONLY | O_BINARY | O_CREAT,S_MODE);
419 if (destination_file == -1)
420 return(MagickFalse);
421 source_file=open(source,O_RDONLY | O_BINARY);
422 if (source_file == -1)
423 {
424 (void) close(destination_file);
425 return(MagickFalse);
426 }
427 quantum=(size_t) MagickMaxBufferExtent;
428 if ((fstat(source_file,&attributes) == 0) && (attributes.st_size != 0))
429 quantum=(size_t) MagickMin((double) attributes.st_size,
430 MagickMaxBufferExtent);
431 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
432 if (buffer == (unsigned char *) NULL)
433 {
434 (void) close(source_file);
435 (void) close(destination_file);
436 return(MagickFalse);
437 }
438 length=0;
439 for (i=0; ; i+=count)
440 {
441 count=(ssize_t) read(source_file,buffer,quantum);
442 if (count <= 0)
443 break;
444 length=(size_t) count;
445 count=(ssize_t) write(destination_file,buffer,length);
446 if ((size_t) count != length)
447 break;
448 }
449 (void) close(destination_file);
450 (void) close(source_file);
451 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
452 return(i != 0 ? MagickTrue : MagickFalse);
453}
454
455static MagickBooleanType WriteMPEGImage(const ImageInfo *image_info,
456 Image *image)
457{
458#define WriteMPEGIntermediateFormat "jpg"
459
460 char
461 basename[MaxTextExtent],
462 filename[MaxTextExtent];
463
464 double
465 delay;
466
467 Image
468 *coalesce_image;
469
470 ImageInfo
471 *write_info;
472
473 int
474 file;
475
476 MagickBooleanType
477 status;
478
479 register Image
480 *p;
481
cristybb503372010-05-27 20:51:26 +0000482 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000483 i;
484
485 size_t
486 length;
487
488 unsigned char
489 *blob;
490
cristybb503372010-05-27 20:51:26 +0000491 size_t
cristy3ed852e2009-09-05 21:47:34 +0000492 count,
493 scene;
494
495 /*
496 Open output image file.
497 */
498 assert(image_info != (const ImageInfo *) NULL);
499 assert(image_info->signature == MagickSignature);
500 assert(image != (Image *) NULL);
501 assert(image->signature == MagickSignature);
502 if (image->debug != MagickFalse)
503 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
504 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
505 if (status == MagickFalse)
506 return(status);
507 (void) CloseBlob(image);
508 /*
cristye9ae8112009-09-21 16:17:49 +0000509 Write intermediate files.
cristy3ed852e2009-09-05 21:47:34 +0000510 */
511 coalesce_image=CoalesceImages(image,&image->exception);
512 if (coalesce_image == (Image *) NULL)
513 return(MagickFalse);
514 file=AcquireUniqueFileResource(basename);
515 if (file != -1)
516 file=close(file)-1;
517 (void) FormatMagickString(coalesce_image->filename,MaxTextExtent,"%s",
518 basename);
519 count=0;
520 write_info=CloneImageInfo(image_info);
521 for (p=coalesce_image; p != (Image *) NULL; p=GetNextImageInList(p))
522 {
523 char
524 previous_image[MaxTextExtent];
525
526 blob=(unsigned char *) NULL;
527 length=0;
528 scene=p->scene;
529 delay=100.0*p->delay/MagickMax(1.0*p->ticks_per_second,1.0);
cristybb503372010-05-27 20:51:26 +0000530 for (i=0; i < (ssize_t) MagickMax((1.0*delay+1.0)/3.0,1.0); i++)
cristy3ed852e2009-09-05 21:47:34 +0000531 {
532 p->scene=count;
533 count++;
534 status=MagickFalse;
535 switch (i)
536 {
537 case 0:
538 {
539 Image
540 *frame;
541
cristye8c25f92010-06-03 00:53:06 +0000542 (void) FormatMagickString(p->filename,MaxTextExtent,"%s%.20g.%s",
543 basename,(double) p->scene,WriteMPEGIntermediateFormat);
544 (void) FormatMagickString(filename,MaxTextExtent,"%s%.20g.%s",
545 basename,(double) p->scene,WriteMPEGIntermediateFormat);
cristy3ed852e2009-09-05 21:47:34 +0000546 (void) FormatMagickString(previous_image,MaxTextExtent,
cristye8c25f92010-06-03 00:53:06 +0000547 "%s%.20g.%s",basename,(double) p->scene,
cristyf2faecf2010-05-28 19:19:36 +0000548 WriteMPEGIntermediateFormat);
cristy3ed852e2009-09-05 21:47:34 +0000549 frame=CloneImage(p,0,0,MagickTrue,&p->exception);
550 if (frame == (Image *) NULL)
551 break;
552 status=WriteImage(write_info,frame);
553 frame=DestroyImage(frame);
554 break;
555 }
556 case 1:
557 {
558 blob=(unsigned char *) FileToBlob(previous_image,~0UL,&length,
559 &image->exception);
560 }
561 default:
562 {
cristye8c25f92010-06-03 00:53:06 +0000563 (void) FormatMagickString(filename,MaxTextExtent,"%s%.20g.%s",
564 basename,(double) p->scene,WriteMPEGIntermediateFormat);
cristy3ed852e2009-09-05 21:47:34 +0000565 if (length > 0)
566 status=BlobToFile(filename,blob,length,&image->exception);
567 break;
568 }
569 }
570 if (image->debug != MagickFalse)
571 {
572 if (status != MagickFalse)
573 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
cristye8c25f92010-06-03 00:53:06 +0000574 "%.20g. Wrote %s file for scene %.20g:",(double) i,
575 WriteMPEGIntermediateFormat,(double) p->scene);
cristy3ed852e2009-09-05 21:47:34 +0000576 else
577 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
cristye8c25f92010-06-03 00:53:06 +0000578 "%.20g. Failed to write %s file for scene %.20g:",(double) i,
579 WriteMPEGIntermediateFormat,(double) p->scene);
580 (void) LogMagickEvent(CoderEvent,GetMagickModule(),"%s",filename);
cristy3ed852e2009-09-05 21:47:34 +0000581 }
582 }
583 p->scene=scene;
584 if (blob != (unsigned char *) NULL)
585 blob=(unsigned char *) RelinquishMagickMemory(blob);
586 if (status == MagickFalse)
587 break;
588 }
589 /*
590 Convert JPEG to MPEG.
591 */
592 (void) CopyMagickString(coalesce_image->magick_filename,basename,
593 MaxTextExtent);
594 (void) CopyMagickString(coalesce_image->filename,basename,MaxTextExtent);
595 GetPathComponent(image_info->filename,ExtensionPath,coalesce_image->magick);
596 if (*coalesce_image->magick == '\0')
597 (void) CopyMagickString(coalesce_image->magick,image->magick,MaxTextExtent);
598 status=InvokeDelegate(write_info,coalesce_image,(char *) NULL,"mpeg:encode",
599 &image->exception);
600 (void) FormatMagickString(write_info->filename,MaxTextExtent,"%s.%s",
601 write_info->unique,coalesce_image->magick);
602 status=CopyDelegateFile(write_info->filename,image->filename);
603 (void) RelinquishUniqueFileResource(write_info->filename);
604 write_info=DestroyImageInfo(write_info);
605 /*
606 Relinquish resources.
607 */
608 count=0;
609 for (p=coalesce_image; p != (Image *) NULL; p=GetNextImageInList(p))
610 {
611 delay=100.0*p->delay/MagickMax(1.0*p->ticks_per_second,1.0);
cristybb503372010-05-27 20:51:26 +0000612 for (i=0; i < (ssize_t) MagickMax((1.0*delay+1.0)/3.0,1.0); i++)
cristy3ed852e2009-09-05 21:47:34 +0000613 {
cristye8c25f92010-06-03 00:53:06 +0000614 (void) FormatMagickString(p->filename,MaxTextExtent,"%s%.20g.%s",
615 basename,(double) count++,WriteMPEGIntermediateFormat);
cristy3ed852e2009-09-05 21:47:34 +0000616 (void) RelinquishUniqueFileResource(p->filename);
617 }
618 (void) CopyMagickString(p->filename,image_info->filename,MaxTextExtent);
619 }
620 (void) RelinquishUniqueFileResource(basename);
621 coalesce_image=DestroyImageList(coalesce_image);
622 if (image->debug != MagickFalse)
623 (void) LogMagickEvent(CoderEvent,GetMagickModule(),"exit");
624 return(status);
625}