37
60
#include <sys/types.h>
40
/* transcode defines these as well as ImageMagick. */
42
#undef PACKAGE_TARNAME
43
#undef PACKAGE_VERSION
46
#include <magick/api.h>
62
/* ------------------------------------------------------------
64
static char *head = NULL, *tail = NULL;
65
static int first_frame = 0, current_frame = 0, pad = 0;
66
static int width = 0, height = 0;
67
static MagickWand *wand = NULL;
69
static int TCHandleMagickError(MagickWand *wand)
71
ExceptionType severity;
72
const char *description = MagickGetException(wand, &severity);
74
fprintf(stderr, "[%s] %s\n", MOD_NAME, description);
76
MagickRelinquishMemory((void*)description);
77
return TC_IMPORT_ERROR;
81
/* ------------------------------------------------------------
66
85
* ------------------------------------------------------------*/
88
/* I suspect we have a lot of potential memleaks in here -- FRomani */
91
if(param->flag == TC_AUDIO) {
95
if(param->flag == TC_VIDEO) {
99
// get the frame name and range
100
regex = "\\(.\\+[-._]\\)\\?\\([0-9]\\+\\)\\([-._].\\+\\)\\?";
101
result = regcomp(&preg, regex, 0);
103
perror("ERROR: Regex compile failed.\n");
104
return(TC_IMPORT_ERROR);
107
result = regexec(&preg, vob->video_in_file, 4, pmatch, 0);
109
fprintf(stderr, "Regex match failed: no image sequence\n");
110
string_length = strlen(vob->video_in_file) + 1;
111
if ((head = malloc(string_length)) == NULL) {
112
perror("filename head");
113
return(TC_IMPORT_ERROR);
115
strlcpy(head, vob->video_in_file, string_length);
119
last_frame = 0x7fffffff;
122
// split the name into head, frame number, and tail
123
string_length = pmatch[1].rm_eo - pmatch[1].rm_so + 1;
124
if ((head = malloc(string_length)) == NULL) {
125
perror("filename head");
126
return(TC_IMPORT_ERROR);
128
strlcpy(head, vob->video_in_file, string_length);
130
string_length = pmatch[2].rm_eo - pmatch[2].rm_so + 1;
131
if ((frame = malloc(string_length)) == NULL) {
132
perror("filename frame");
133
return(TC_IMPORT_ERROR);
135
strlcpy(frame, vob->video_in_file + pmatch[2].rm_so, string_length);
137
// If the frame number is padded with zeros, record how many digits
138
// are actually being used.
139
if (frame[0] == '0') {
140
pad = pmatch[2].rm_eo - pmatch[2].rm_so;
142
first_frame = atoi(frame);
144
string_length = pmatch[3].rm_eo - pmatch[3].rm_so + 1;
145
if ((tail = malloc(string_length)) == NULL) {
146
perror("filename tail");
147
return(TC_IMPORT_ERROR);
149
strlcpy(tail, vob->video_in_file + pmatch[3].rm_so, string_length);
151
// find the last frame by trying to open files
152
last_frame = first_frame;
153
filename = malloc(strlen(head) + pad + strlen(tail) + 1);
154
/* why remalloc frame? */
155
/* frame = malloc(pad + 1); */
158
snprintf(printfspec, sizeof(printfspec), "%%s%%0%dd%%s", pad);
159
string_length = strlen(head) + pad + strlen(tail) + 1;
160
sret = snprintf(filename, string_length, printfspec, head,
162
if (tc_test_string(__FILE__, __LINE__, string_length, sret, errno))
163
return(TC_IMPORT_ERROR);
164
} while (close(open(filename, O_RDONLY)) != -1);
170
current_frame = first_frame;
172
// initialize ImageMagick
173
InitializeMagick("");
175
return(TC_IMPORT_OK);
178
return(TC_IMPORT_ERROR);
92
char *regex = NULL, *frame = NULL;
96
if (param->flag == TC_AUDIO) {
100
if (param->flag == TC_VIDEO) {
103
// get the frame name and range
104
regex = "\\([^0-9]\\+[-._]\\?\\)\\?\\([0-9]\\+\\)\\([-._].\\+\\)\\?";
105
result = regcomp(&preg, regex, 0);
107
perror("regex compile");
108
return TC_IMPORT_ERROR;
111
result = regexec(&preg, vob->video_in_file, 4, pmatch, 0);
113
fprintf(stderr, "[%s] regex match failed: no image sequence\n", MOD_NAME);
114
slen = strlen(vob->video_in_file) + 1;
117
perror("filename head");
118
return TC_IMPORT_ERROR;
120
strlcpy(head, vob->video_in_file, slen);
121
tail = malloc(1); /* URGH -- FRomani */
125
// split the name into head, frame number, and tail
126
slen = pmatch[1].rm_eo - pmatch[1].rm_so + 1;
129
perror("filename head");
130
return TC_IMPORT_ERROR;
132
strlcpy(head, vob->video_in_file, slen);
134
slen = pmatch[2].rm_eo - pmatch[2].rm_so + 1;
135
frame = malloc(slen);
137
perror("filename frame");
138
return TC_IMPORT_ERROR;
140
strlcpy(frame, vob->video_in_file + pmatch[2].rm_so, slen);
142
// If the frame number is padded with zeros, record how many digits
143
// are actually being used.
144
if (frame[0] == '0') {
145
pad = pmatch[2].rm_eo - pmatch[2].rm_so;
147
first_frame = atoi(frame);
149
slen = pmatch[3].rm_eo - pmatch[3].rm_so + 1;
152
perror("filename tail");
153
return TC_IMPORT_ERROR;
155
strlcpy(tail, vob->video_in_file + pmatch[3].rm_so, slen);
160
current_frame = first_frame;
162
width = vob->im_v_width;
163
height = vob->im_v_height;
166
wand = NewMagickWand();
169
fprintf(stderr, "[%s] cannot create magick wand\n", MOD_NAME);
170
return TC_IMPORT_ERROR;
176
return TC_IMPORT_ERROR;
182
/* ------------------------------------------------------------
180
/* ------------------------------------------------------------
186
184
* ------------------------------------------------------------*/
213
if (current_frame > last_frame)
214
return(TC_IMPORT_ERROR);
216
// build the filename for the current frame
217
string_length = strlen(head) + pad + strlen(tail) + 1;
218
filename = malloc(string_length);
220
frame = malloc(pad+1);
221
framespec = malloc(10);
222
snprintf(framespec, 10, "%%0%dd", pad);
223
snprintf(frame, pad+1, framespec, current_frame);
227
else if (first_frame >= 0) {
229
snprintf(frame, 10, "%d", current_frame);
231
strlcpy(filename, head, string_length);
233
strlcat(filename, frame, string_length);
237
strlcat(filename, tail, string_length);
239
// Have ImageMagick open the file and read in the image data.
240
GetExceptionInfo(&exception_info);
241
image_info=CloneImageInfo((ImageInfo *) NULL);
242
(void) strlcpy(image_info->filename, filename, MaxTextExtent);
243
image=ReadImage(image_info,&exception_info);
244
if (image == (Image *) NULL) {
245
MagickError(exception_info.severity,
246
exception_info.reason,
247
exception_info.description);
249
return (TC_IMPORT_ERROR);
253
* Copy the pixels into a buffer in RGB order
255
pixel_packet = GetImagePixels(image, 0, 0, image->columns, image->rows);
256
for (row = 0; row < image->rows; row++) {
257
for (column = 0; column < image->columns; column++) {
259
* The bit-shift 8 in the following lines is to convert
260
* 16-bit-per-channel images that may be read by ImageMagick
261
* into the 8-bit-per-channel images that transcode uses.
262
* The bit-shift is still valid for 8-bit-per-channel images
263
* because when ImageMagick handles 8-bit images it still uses
264
* unsigned shorts, but stores the same 8-bit value in both
265
* the low and high byte.
267
param->buffer[(row * image->columns + column) * 3 + 0] =
268
(char) (pixel_packet[(image->rows - row - 1) * image->columns +
270
param->buffer[(row * image->columns + column) * 3 + 1] =
271
(char) (pixel_packet[(image->rows - row - 1) * image->columns +
273
param->buffer[(row * image->columns + column) * 3 + 2] =
274
(char) (pixel_packet[(image->rows - row - 1) * image->columns +
279
if (current_frame == first_frame)
188
char *filename = NULL, *frame = NULL;
190
MagickBooleanType status;
192
if (param->flag == TC_AUDIO) {
196
if (param->flag == TC_VIDEO) {
197
// build the filename for the current frame
198
slen = strlen(head) + pad + strlen(tail) + 1;
199
filename = malloc(slen);
202
frame = malloc(pad+1);
203
snprintf(framespec, 10, "%%0%dd", pad);
204
snprintf(frame, pad+1, framespec, current_frame);
206
} else if (first_frame >= 0) {
208
snprintf(frame, 10, "%d", current_frame);
210
strlcpy(filename, head, slen);
212
strlcat(filename, frame, slen);
216
strlcat(filename, tail, slen);
218
ClearMagickWand(wand);
220
* This avoids IM to buffer all read images.
221
* I'm quite sure that this can be done in a smarter way,
222
* but I haven't yet figured out how. -- FRomani
225
status = MagickReadImage(wand, filename);
226
if (status == MagickFalse) {
227
/* let's assume that image sequence ends here */
228
return TC_IMPORT_ERROR;
231
MagickSetLastIterator(wand);
233
status = MagickGetImagePixels(wand,
237
/* param->size already set correctly by caller */
238
if (status == MagickFalse) {
239
return TCHandleMagickError(wand);
280
242
param->attributes |= TC_FRAME_IS_KEYFRAME;
284
// How do we do this? The next line is not right (segfaults)
285
// I can't find a DestroyPixelPacket() method.
286
//free(pixel_packet);
288
DestroyImageInfo(image_info);
289
DestroyExceptionInfo(&exception_info);
292
return(TC_IMPORT_OK);
250
return TC_IMPORT_ERROR;
295
/* ------------------------------------------------------------
253
/* ------------------------------------------------------------
299
257
* ------------------------------------------------------------*/
303
if (param->fd != NULL) pclose(param->fd);
304
if (head != NULL) free(head);
305
if (tail != NULL) free(tail);
309
return(TC_IMPORT_OK);
261
if (param->flag == TC_AUDIO) {
265
if (param->flag == TC_VIDEO) {
266
if (param->fd != NULL)
274
DestroyMagickWand(wand);
275
MagickWandTerminus();
280
return TC_IMPORT_ERROR;
283
/*************************************************************************/
287
* c-file-style: "stroustrup"
288
* c-file-offsets: ((case-label . *) (statement-case-intro . *))
289
* indent-tabs-mode: nil
292
* vim: expandtab shiftwidth=4: