00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
#include "magick/studio.h"
00042
#include "magick/blob.h"
00043
#include "magick/blob_private.h"
00044
#include "magick/constitute.h"
00045
#include "magick/delegate.h"
00046
#include "magick/error.h"
00047
#include "magick/error_private.h"
00048
#include "magick/geometry.h"
00049
#include "magick/image.h"
00050
#include "magick/image_private.h"
00051
#include "magick/list.h"
00052
#include "magick/log.h"
00053
#include "magick/magick.h"
00054
#include "magick/memory_.h"
00055
#include "magick/resource_.h"
00056
#include "magick/static.h"
00057
#include "magick/string_.h"
00058
#include "magick/transform.h"
00059
#include "magick/utility.h"
00060
00061
00062
00063
00064
static MagickBooleanType
00065
WriteMPEGImage(
const ImageInfo *image_info,
Image *image);
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094 static MagickBooleanType IsMPEG(
const unsigned char *magick,
const size_t length)
00095 {
00096
if (length < 4)
00097
return(
MagickFalse);
00098
if (memcmp(magick,
"\000\000\001\263",4) == 0)
00099
return(
MagickTrue);
00100
return(
MagickFalse);
00101 }
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133 static Image *
ReadMPEGImage(
const ImageInfo *image_info,
00134
ExceptionInfo *
exception)
00135 {
00136
Image
00137 *image,
00138 *images;
00139
00140
ImageInfo
00141 *read_info;
00142
00143
MagickBooleanType
00144 status;
00145
00146
register long
00147 i;
00148
00149
00150
00151
00152
assert(image_info != (
const ImageInfo *) NULL);
00153
assert(image_info->
signature ==
MagickSignature);
00154
if (image_info->
debug !=
MagickFalse)
00155 (
void)
LogMagickEvent(
TraceEvent,
GetMagickModule(),image_info->
filename);
00156
assert(exception != (
ExceptionInfo *) NULL);
00157
assert(exception->
signature ==
MagickSignature);
00158 image=
AllocateImage(image_info);
00159 status=
OpenBlob(image_info,image,
ReadBinaryBlobMode,exception);
00160
if (status ==
MagickFalse)
00161 {
00162
DestroyImageList(image);
00163
return((
Image *) NULL);
00164 }
00165
CloseBlob(image);
00166
00167
00168
00169 image=
AllocateImage(image_info);
00170 read_info=
CloneImageInfo(image_info);
00171 (
void)
InvokeDelegate(read_info,image,
"mpeg-decode",(
char *) NULL,exception);
00172 image=
DestroyImage(image);
00173
00174
00175
00176 images=
NewImageList();
00177
for (i=(
long) read_info->
scene; ; i++)
00178 {
00179 (
void)
FormatMagickString(read_info->
filename,
MaxTextExtent,
00180
"%s%ld.ppm",read_info->
unique,i);
00181
if (
IsAccessible(read_info->
filename) ==
MagickFalse)
00182
break;
00183 image=
ReadImage(read_info,exception);
00184
if (image == (
Image *) NULL)
00185
break;
00186 (
void) strcpy(image->
magick,image_info->
magick);
00187 image->
scene=(
unsigned long) i;
00188
AppendImageToList(&images,image);
00189
if (read_info->
number_scenes != 0)
00190
if (i >= (
long) (read_info->
scene+read_info->
number_scenes-1))
00191
break;
00192 }
00193
00194
00195
00196
for (i=0; ; i++)
00197 {
00198 (
void)
FormatMagickString(read_info->
filename,
MaxTextExtent,
00199
"%s%ld.ppm",read_info->
unique,i);
00200
if (
IsAccessible(read_info->
filename) ==
MagickFalse)
00201
break;
00202 (
void) remove(read_info->
filename);
00203 }
00204 read_info=
DestroyImageInfo(read_info);
00205
return(images);
00206 }
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231 ModuleExport void RegisterMPEGImage(
void)
00232 {
00233
MagickInfo
00234 *entry;
00235
00236 entry=
SetMagickInfo(
"MPEG");
00237 entry->
decoder=(
DecoderHandler *)
ReadMPEGImage;
00238 entry->
encoder=(
EncoderHandler *)
WriteMPEGImage;
00239 entry->
magick=(
MagickHandler *)
IsMPEG;
00240 entry->
blob_support=
MagickFalse;
00241 entry->
description=
AcquireString(
"MPEG Video Stream");
00242 entry->
module=
AcquireString(
"MPEG");
00243 (
void)
RegisterMagickInfo(entry);
00244 entry=
SetMagickInfo(
"MPG");
00245 entry->
decoder=(
DecoderHandler *)
ReadMPEGImage;
00246 entry->
encoder=(
EncoderHandler *)
WriteMPEGImage;
00247 entry->
magick=(
MagickHandler *)
IsMPEG;
00248 entry->
blob_support=
MagickFalse;
00249 entry->
description=
AcquireString(
"MPEG Video Stream");
00250 entry->
module=
AcquireString(
"MPEG");
00251 (
void)
RegisterMagickInfo(entry);
00252 entry=
SetMagickInfo(
"M2V");
00253 entry->
decoder=(
DecoderHandler *)
ReadMPEGImage;
00254 entry->
encoder=(
EncoderHandler *)
WriteMPEGImage;
00255 entry->
magick=(
MagickHandler *)
IsMPEG;
00256 entry->
blob_support=
MagickFalse;
00257 entry->
description=
AcquireString(
"MPEG Video Stream");
00258 entry->
module=
AcquireString(
"MPEG");
00259 (
void)
RegisterMagickInfo(entry);
00260 }
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281 ModuleExport void UnregisterMPEGImage(
void)
00282 {
00283 (
void)
UnregisterMagickInfo(
"M2V");
00284 (
void)
UnregisterMagickInfo(
"MPEG");
00285 (
void)
UnregisterMagickInfo(
"MPG");
00286 }
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316 static MagickBooleanType WriteMPEGParameterFiles(
const ImageInfo *image_info,
00317
Image *image,
const char *basename)
00318 {
00319
char
00320 filename[
MaxTextExtent];
00321
00322
double
00323 q;
00324
00325 FILE
00326 *file,
00327 *parameter_file;
00328
00329
long
00330 quant,
00331 vertical_factor;
00332
00333
MagickBooleanType
00334 mpeg;
00335
00336
register Image
00337 *p;
00338
00339
register long
00340 i;
00341
00342
ssize_t
00343 count;
00344
00345
static int
00346 q_matrix[]=
00347 {
00348 8, 16, 19, 22, 26, 27, 29, 34,
00349 16, 16, 22, 24, 27, 29, 34, 37,
00350 19, 22, 26, 27, 29, 34, 34, 38,
00351 22, 22, 26, 27, 29, 34, 37, 40,
00352 22, 26, 27, 29, 32, 35, 40, 48,
00353 26, 27, 29, 32, 35, 40, 48, 58,
00354 26, 27, 29, 34, 38, 46, 56, 69,
00355 27, 29, 35, 38, 46, 56, 69, 83
00356 };
00357
00358
00359
00360
00361 file=fopen(basename,
"w");
00362
if (file == (FILE *) NULL)
00363
return(
MagickFalse);
00364 (
void) fprintf(file,
"MPEG\n");
00365 (
void) fprintf(file,
"%s.%%d\n",image->
filename);
00366 (
void) fprintf(file,
"-\n");
00367
if (image->
quality ==
UndefinedCompressionQuality)
00368 (
void) fprintf(file,
"-\n");
00369
else
00370 {
00371
00372
00373
00374 (
void)
FormatMagickString(filename,
MaxTextExtent,
"%s.iqm",basename);
00375 (
void) fprintf(file,
"%s\n",filename);
00376 parameter_file=fopen(filename,
"w");
00377
if (parameter_file == (FILE *) NULL)
00378
return(
MagickFalse);
00379
if (image->
quality >= 75)
00380 {
00381 q=(
double)
Max((image->
quality-75)*2,1);
00382
for (i=0; i < 64; i++)
00383 {
00384 quant=(
long)
Min(
Max(q_matrix[i]/q,1.0),255.0);
00385 (
void) fprintf(parameter_file,
" %ld",quant);
00386
if ((i % 8) == 7)
00387 (
void) fprintf(parameter_file,
"\n");
00388 }
00389 }
00390
else
00391 {
00392 q=(
double)
Max((75-image->
quality)/8,1);
00393
for (i=0; i < 64; i++)
00394 {
00395 quant=(
long)
Min(
Max(q*q_matrix[i]+0.5,1.0),255.0);
00396 (
void) fprintf(parameter_file,
" %ld",quant);
00397
if ((i % 8) == 7)
00398 (
void) fprintf(parameter_file,
"\n");
00399 }
00400 }
00401 (
void) fclose(parameter_file);
00402 }
00403
if (image->
quality ==
UndefinedCompressionQuality)
00404 (
void) fprintf(file,
"-\n");
00405
else
00406 {
00407
00408
00409
00410 (
void)
FormatMagickString(filename,
MaxTextExtent,
"%s.niq",basename);
00411 (
void) fprintf(file,
"%s\n",filename);
00412 parameter_file=fopen(filename,
"w");
00413
if (parameter_file == (FILE *) NULL)
00414
return(
MagickFalse);
00415 q=
Min(
Max(66.0-(2*image->
quality)/3.0,1.0),255);
00416 for (i=0; i < 64; i++)
00417 {
00418 (
void) fprintf(parameter_file,
" %d",(
int) q);
00419
if ((i % 8) == 7)
00420 (
void) fprintf(parameter_file,
"\n");
00421 }
00422 (
void) fclose(parameter_file);
00423 }
00424 (
void) fprintf(file,
"%s.log\n",basename);
00425 (
void) fprintf(file,
"1\n");
00426 count=0;
00427
for (p=image; p != (
Image *) NULL; p=p->
next)
00428 count+=
Max((p->delay+1)/3,1);
00429 (
void) fprintf(file,
"%lu\n",(
unsigned long) count);
00430 (
void) fprintf(file,
"0\n");
00431 (
void) fprintf(file,
"00:00:00:00\n");
00432 mpeg=(
MagickBooleanType) (
LocaleCompare(image_info->
magick,
"M2V") != 0);
00433 if (image->
quality > 98)
00434 (
void) fprintf(file,
"1\n");
00435
else
00436 (
void) fprintf(file,
"%d\n",mpeg !=
MagickFalse ? 12 : 15);
00437
if (image->
quality > 98)
00438 (
void) fprintf(file,
"1\n");
00439
else
00440 (
void) fprintf(file,
"3\n");
00441 (
void) fprintf(file,
"%d\n",mpeg !=
MagickFalse ? 1 : 0);
00442 (
void) fprintf(file,
"0\n");
00443 (
void) fprintf(file,
"%lu\n",image->
columns+
00444 ((image->
columns & 0x01) != 0 ? 1 : 0));
00445 (
void) fprintf(file,
"%lu\n",image->
rows+((image->
rows & 0x01) != 0 ? 1 : 0));
00446 (
void) fprintf(file,
"%d\n",mpeg !=
MagickFalse ? 8 : 2);
00447 (
void) fprintf(file,
"%d\n",mpeg !=
MagickFalse ? 3 : 5);
00448 (
void) fprintf(file,
"%g\n",mpeg !=
MagickFalse ? 1152000.0 : 5000000.0);
00449 (
void) fprintf(file,
"%d\n",mpeg !=
MagickFalse ? 20 : 112);
00450 (
void) fprintf(file,
"0\n");
00451 (
void) fprintf(file,
"%d\n",mpeg !=
MagickFalse ? 1 : 0);
00452 (
void) fprintf(file,
"%d\n",mpeg !=
MagickFalse ? 4 : 1);
00453 (
void) fprintf(file,
"%d\n",mpeg !=
MagickFalse ? 8 : 4);
00454 (
void) fprintf(file,
"%d\n",mpeg !=
MagickFalse ? 1 : 0);
00455 vertical_factor=2;
00456
if (image_info->
sampling_factor != (
char *) NULL)
00457 {
00458
GeometryInfo
00459 geometry_info;
00460
00461
long
00462 horizontal_factor;
00463
00464
MagickStatusType
00465 flags;
00466
00467 flags=
ParseGeometry(image_info->
sampling_factor,&geometry_info);
00468 horizontal_factor=(
long) geometry_info.rho;
00469 vertical_factor=(
long) geometry_info.sigma;
00470 if ((flags &
SigmaValue) == 0)
00471 vertical_factor=horizontal_factor;
00472
if (mpeg !=
MagickFalse)
00473 {
00474
if ((horizontal_factor != 2) || (vertical_factor != 2))
00475 {
00476 (
void) fclose(file);
00477
return(
MagickFalse);
00478 }
00479 }
00480
else
00481
if ((horizontal_factor != 2) ||
00482 ((vertical_factor != 1) && (vertical_factor != 2)))
00483 {
00484 (
void) fclose(file);
00485
return(
MagickFalse);
00486 }
00487 }
00488 (
void) fprintf(file,
"%d\n",vertical_factor == 2 ? 1 : 2);
00489 (
void) fprintf(file,
"%d\n",mpeg !=
MagickFalse ? 1 : 2);
00490 (
void) fprintf(file,
"5\n");
00491 (
void) fprintf(file,
"5\n");
00492 (
void) fprintf(file,
"%d\n",mpeg !=
MagickFalse ? 5 : 4);
00493 (
void) fprintf(file,
"%lu\n",image->
columns+
00494 ((image->
columns & 0x01) != 0 ? 1 : 0));
00495 (
void) fprintf(file,
"%lu\n",image->
rows+((image->
rows & 0x01) != 0 ? 1 : 0));
00496 (
void) fprintf(file,
"0\n");
00497 (
void) fprintf(file,
"%d\n",mpeg !=
MagickFalse ? 0 : 1);
00498 (
void) fprintf(file,
"%d %d %d\n",mpeg !=
MagickFalse ? 1 : 0,
00499 mpeg !=
MagickFalse ? 1 : 0, mpeg !=
MagickFalse ? 1 : 0);
00500 (
void) fprintf(file,
"0 0 0\n");
00501 (
void) fprintf(file,
"%d %d %d\n",mpeg !=
MagickFalse ? 0 : 1,
00502 mpeg !=
MagickFalse ? 0 : 1,mpeg !=
MagickFalse ? 0 : 1);
00503 (
void) fprintf(file,
"%d 0 0\n",mpeg !=
MagickFalse ? 0 : 1);
00504 (
void) fprintf(file,
"0 0 0\n");
00505 (
void) fprintf(file,
"0\n");
00506 (
void) fprintf(file,
"%d\n",mpeg !=
MagickFalse ? 1 : 0);
00507 (
void) fprintf(file,
"0\n");
00508 (
void) fprintf(file,
"0\n");
00509 (
void) fprintf(file,
"0\n");
00510 (
void) fprintf(file,
"0\n");
00511 (
void) fprintf(file,
"0\n");
00512 (
void) fprintf(file,
"0\n");
00513 (
void) fprintf(file,
"0\n");
00514 (
void) fprintf(file,
"0\n");
00515 (
void) fprintf(file,
"0\n");
00516 (
void) fprintf(file,
"2 2 11 11\n");
00517 (
void) fprintf(file,
"1 1 3 3\n");
00518 (
void) fprintf(file,
"1 1 7 7\n");
00519 (
void) fprintf(file,
"1 1 7 7\n");
00520 (
void) fprintf(file,
"1 1 3 3\n");
00521 (
void) fclose(file);
00522
return(
MagickTrue);
00523 }
00524
00525 static MagickBooleanType
WriteMPEGImage(
const ImageInfo *image_info,Image *image)
00526 {
00527
char
00528 basename[MaxTextExtent],
00529 filename[MaxTextExtent];
00530
00531 Image
00532 *coalesce_image,
00533 *next_image;
00534
00535
ImageInfo
00536 *write_info;
00537
00538
int
00539 file;
00540
00541 MagickBooleanType
00542 status;
00543
00544
register Image
00545 *p;
00546
00547
register long
00548 i;
00549
00550 size_t
00551 length;
00552
00553
unsigned char
00554 *blob;
00555
00556
unsigned long
00557 count,
00558 scene;
00559
00560
00561
00562
00563
assert(image_info != (
const ImageInfo *) NULL);
00564
assert(image_info->signature == MagickSignature);
00565
assert(image != (Image *) NULL);
00566
assert(image->
signature == MagickSignature);
00567 if (image->
debug != MagickFalse)
00568 (
void)
LogMagickEvent(TraceEvent,
GetMagickModule(),image->
filename);
00569 status=
OpenBlob(image_info,image,WriteBinaryBlobMode,&image->
exception);
00570 if (status == MagickFalse)
00571
return(status);
00572
CloseBlob(image);
00573
00574
00575
00576 coalesce_image=image;
00577
for (next_image=image; next_image != (Image *) NULL; )
00578 {
00579
if ((image->columns != next_image->columns) ||
00580 (image->rows != next_image->rows))
00581
break;
00582 if ((image->page.x != next_image->page.x) ||
00583 (image->page.y != next_image->page.y))
00584
break;
00585 next_image=next_image->next;
00586 }
00587
if (next_image != (
Image *) NULL)
00588 {
00589 coalesce_image=
CoalesceImages(image,&image->exception);
00590
if (coalesce_image == (
Image *) NULL)
00591
return(
MagickFalse);
00592 }
00593
00594
00595
00596 file=
AcquireUniqueFileResource(basename);
00597
if (file != -1)
00598 (
void) close(file);
00599 (
void)
FormatMagickString(coalesce_image->filename,MaxTextExtent,
"%s",
00600 basename);
00601 write_info=
CloneImageInfo(image_info);
00602 status=
WriteMPEGParameterFiles(write_info,coalesce_image,basename);
00603
if (status ==
MagickFalse)
00604 {
00605
if (coalesce_image != image)
00606 coalesce_image=
DestroyImage(coalesce_image);
00607 (
void) remove(basename);
00608
if (image->quality !=
UndefinedCompressionQuality)
00609 {
00610 (
void)
FormatMagickString(filename,MaxTextExtent,
"%s.iqm",
00611 basename);
00612 (
void) remove(filename);
00613 (
void)
FormatMagickString(filename,MaxTextExtent,
"%s.niq",
00614 basename);
00615 (
void) remove(filename);
00616 }
00617
ThrowWriterException(CoderError,
"UnableToWriteMPEGParameters");
00618 }
00619 count=0;
00620 write_info->interlace=
PlaneInterlace;
00621
for (p=coalesce_image; p != (
Image *) NULL; p=p->next)
00622 {
00623
char
00624 previous_image[
MaxTextExtent];
00625
00626 blob=(
unsigned char *) NULL;
00627 length=0;
00628 scene=p->scene;
00629
for (i=0; i < (
long)
Max((p->delay+1)/3,1); i++)
00630 {
00631 p->scene=count;
00632 count++;
00633 status=
MagickFalse;
00634
switch (i)
00635 {
00636
case 0:
00637 {
00638
Image
00639 *frame;
00640
00641 (
void)
FormatMagickString(p->filename,MaxTextExtent,
"%s.%lu.yuv",
00642 basename,p->scene);
00643 (
void)
FormatMagickString(filename,MaxTextExtent,
"%s.%lu.yuv",
00644 basename,p->scene);
00645 (
void)
FormatMagickString(previous_image,MaxTextExtent,
00646
"%s.%lu.yuv",basename,p->scene);
00647 frame=
CloneImage(p,0,0,MagickTrue,&p->exception);
00648
if (frame == (
Image *) NULL)
00649
break;
00650 status=
WriteImage(write_info,frame);
00651 frame=
DestroyImage(frame);
00652
break;
00653 }
00654
case 1:
00655 {
00656 blob=(
unsigned char *)
00657
FileToBlob(previous_image,&length,&image->exception);
00658 }
00659
default:
00660 {
00661 (
void)
FormatMagickString(filename,MaxTextExtent,
"%s.%lu.yuv",
00662 basename,p->scene);
00663
if (length > 0)
00664 status=
BlobToFile(filename,blob,length,&image->exception);
00665
break;
00666 }
00667 }
00668
if (image->debug !=
MagickFalse)
00669 {
00670
if (status !=
MagickFalse)
00671 (
void)
LogMagickEvent(CoderEvent,
GetMagickModule(),
00672
"%lu. Wrote YUV file for scene %lu:",i,p->scene);
00673
else
00674 (
void)
LogMagickEvent(CoderEvent,
GetMagickModule(),
00675
"%lu. Failed to write YUV file for scene %lu:",i,p->scene);
00676 (
void)
LogMagickEvent(CoderEvent,
GetMagickModule(),
"%s",
00677 filename);
00678 }
00679 }
00680 p->scene=scene;
00681
if (blob != (
unsigned char *) NULL)
00682 blob=(
unsigned char *)
RelinquishMagickMemory(blob);
00683
if (status ==
MagickFalse)
00684
break;
00685 }
00686
00687
00688
00689 (
void)
CopyMagickString(coalesce_image->filename,basename,MaxTextExtent);
00690 status=
InvokeDelegate(write_info,coalesce_image,(
char *) NULL,
"mpeg-encode",
00691 &image->exception);
00692 write_info=
DestroyImageInfo(write_info);
00693
00694
00695
00696 count=0;
00697
for (p=coalesce_image; p != (
Image *) NULL; p=p->next)
00698 {
00699
for (i=0; i < (
long)
Max((p->delay+1)/3,1); i++)
00700 {
00701 (
void)
FormatMagickString(p->filename,MaxTextExtent,
"%s.%lu.yuv",
00702 basename,count++);
00703 (
void) remove(p->filename);
00704 }
00705 (
void)
CopyMagickString(p->filename,image_info->filename,MaxTextExtent);
00706 }
00707 (
void)
RelinquishUniqueFileResource(basename);
00708 (
void)
FormatMagickString(filename,MaxTextExtent,
"%s.iqm",basename);
00709 (
void) remove(filename);
00710 (
void)
FormatMagickString(filename,MaxTextExtent,
"%s.niq",basename);
00711 (
void) remove(filename);
00712 (
void)
FormatMagickString(filename,MaxTextExtent,
"%s.log",basename);
00713 (
void) remove(filename);
00714
if (coalesce_image != image)
00715 coalesce_image=
DestroyImage(coalesce_image);
00716
if (image->debug !=
MagickFalse)
00717 (
void)
LogMagickEvent(CoderEvent,
GetMagickModule(),
"exit");
00718
return(status);
00719 }