Browse Source

Initial commit. Version 1.0

Carlos Mogas da Silva 7 years ago
commit
4055c49a5a
1 changed files with 286 additions and 0 deletions
  1. 286
    0
      srt2ass3D.c

+ 286
- 0
srt2ass3D.c View File

@@ -0,0 +1,286 @@
1
+#include <stdio.h>
2
+#include <getopt.h>
3
+#include <string.h>
4
+#include <stdlib.h>
5
+#include <errno.h>
6
+#include <ctype.h>
7
+
8
+#define SBS_MIDDLE_LEFT_1920 480
9
+#define SBS_MIDDLE_LEFT_3840 SBS_MIDDLE_LEFT_1920 * 2
10
+#define SBS_MIDDLE_RIGHT_1920 1440
11
+#define SBS_MIDDLE_RIGHT_3840 SBS_MIDDLE_RIGHT_1920 * 2
12
+#define TB_MIDDLE_1920 960
13
+#define TB_MIDDLE_3840 TB_MIDDLE_1920 * 2
14
+
15
+static int fullres = 0;
16
+
17
+static struct option long_options[] = {
18
+	{ "input",	    required_argument,  0, 'i' },
19
+	{ "output",	    required_argument,  0, 'o' },
20
+	{ "3dmode",	    required_argument,  0, '3' },
21
+	{ "3ddepth",	required_argument,  0, 'd' },
22
+	{ "help",	    no_argument,        0, 'h' },
23
+	{ "fullres",    no_argument,        &fullres, 1 },
24
+	{ 0, 0, 0, 0 }
25
+};
26
+
27
+void show_help() {
28
+	printf("srt2ass3D converts a SRT subtitle file to a ASS subtitle file for 3d viewing. Options are:\n");
29
+	printf("\t--input,-i\t(required) Input file name\n");
30
+	printf("\t--output,-o\t(required) Output file name\n");
31
+	printf("\t--3dmode,-3\t(required) 3D Mode (SBS, TB)\n");
32
+	printf("\t--3ddepth,-d\t(required) 3D Depth for the subtitles [-3, 3]\n");
33
+	printf("\t--fullres\tSpecifies that the movie is a full resolution 3D movie (3840x1080 or 1920x2160)\n");
34
+	printf("\t--help,-h\tThis help screen\n\n");
35
+}
36
+
37
+char* strreplace(const char *string, const char *substr, const char *replacement){
38
+    char *tok = NULL;
39
+    char *newstr = NULL;
40
+    char *oldstr = NULL;
41
+    char *head = NULL;
42
+
43
+    /* if either substr or replacement is NULL, duplicate string a let caller handle it */
44
+    if (substr == NULL || replacement == NULL)
45
+        return strdup (string);
46
+
47
+    newstr = strdup(string);
48
+    head = newstr;
49
+    while ((tok = strstr(head, substr))) {
50
+        oldstr = newstr;
51
+        newstr = malloc(strlen(oldstr) - strlen(substr) + strlen(replacement) + 1 );
52
+        /*failed to alloc mem, free old string and return NULL */
53
+        if (newstr == NULL) {
54
+            free (oldstr);
55
+            return NULL;
56
+        }
57
+        memcpy(newstr, oldstr, tok - oldstr);
58
+        memcpy(newstr + (tok - oldstr), replacement, strlen(replacement));
59
+        memcpy(newstr + (tok - oldstr) + strlen(replacement), tok + strlen(substr), strlen(oldstr) - strlen(substr) - (tok - oldstr));
60
+        memset(newstr + strlen(oldstr) - strlen(substr) + strlen(replacement), 0, 1 );
61
+
62
+        /* move back head right after the last replacement */
63
+        head = newstr + (tok - oldstr) + strlen(replacement);
64
+        free (oldstr);
65
+    }
66
+    return newstr;
67
+}
68
+
69
+char* replace_tags(char *text) {
70
+	char *tmp1, *tmp2;
71
+
72
+	tmp1 = strreplace(strreplace(text, "<i>", "{\\i1}"), "</i>", "{\\i0}");
73
+	tmp2 = strreplace(strreplace(tmp1, "<b>", "{\\b1}"), "</b>", "{\\b0}");
74
+	free(tmp1);
75
+	return tmp2;
76
+}
77
+
78
+int main(int argc, char** argv) {
79
+	int option_index;
80
+	unsigned int c;
81
+	char *input_name = NULL;
82
+	char *output_name = NULL;
83
+	int tb;
84
+	short depth = 0;
85
+	short valid_args = 0;
86
+
87
+	while ((c = getopt_long(argc, argv, "i:o:3:d:h", long_options, &option_index)) != -1) {
88
+		switch (c) {
89
+            case 0: {
90
+                if (long_options[option_index].flag != 0)
91
+                    break;
92
+            }
93
+			case 'i': {
94
+				input_name = malloc(sizeof(char) * strlen(optarg) + 1);
95
+				strcpy(input_name, optarg);
96
+				valid_args++;
97
+				break;
98
+			}
99
+			case 'o': {
100
+				output_name = malloc(sizeof(unsigned char) * strlen(optarg) + 1);
101
+				strcpy(output_name, optarg);
102
+				valid_args++;
103
+				break;
104
+			}
105
+			case '3': {
106
+				// If the argument is SBS then the result will be 0, and 0 == false, so TB = false.
107
+				tb = strcasecmp("SBS", optarg);
108
+				valid_args++;
109
+				break;
110
+			}
111
+			case 'd': {
112
+				depth = atoi(optarg);
113
+				valid_args++;
114
+				break;
115
+			}
116
+			case 'h': {
117
+				show_help();
118
+				return 0;
119
+				break;
120
+			}
121
+		}
122
+	}
123
+
124
+	if (valid_args != 4) {
125
+		if (input_name != NULL)
126
+			free(input_name);
127
+		if (output_name != NULL)
128
+			free(output_name);
129
+		show_help();
130
+		return -1;
131
+	}
132
+
133
+    if (depth < -3 || depth > 3) {
134
+        printf("Values of depth should be between -3 and 3\n");
135
+        return -1;
136
+	}
137
+
138
+	FILE *inputf;
139
+	FILE *outputf;
140
+	inputf = fopen(input_name, "r");
141
+	if (inputf == NULL) {
142
+		printf("Error opening %s for reading: %s\n", input_name, strerror(errno));
143
+		return -1;
144
+	}
145
+	outputf = fopen(output_name, "w");
146
+	if (outputf == NULL) {
147
+		printf("Error opening %s for writing: %s\n", output_name, strerror(errno));
148
+		return -1;
149
+	}
150
+
151
+	printf("Input file: %s\nOutput file: %s\n3D type: %s\nDepth: %i\n\n",
152
+		input_name, output_name, (tb ? "TB" : "SBS"), depth);
153
+
154
+	// ASS headers
155
+	fprintf(outputf, "[Script Info]\n");
156
+	fprintf(outputf, "; Script generated by srt2ass3D 1.0\n");
157
+	fprintf(outputf, "Title: %s\n", output_name);
158
+	fprintf(outputf, "ScriptType: v4.00+\n");
159
+	fprintf(outputf, "WrapStyle: 0\n");
160
+	if (!fullres) {
161
+        fprintf(outputf, "PlayResX: 1920\n");
162
+        fprintf(outputf, "PlayResY: 1080\n");
163
+	} else {
164
+	    if (!tb) {
165
+            fprintf(outputf, "PlayResX: 3840\n");
166
+            fprintf(outputf, "PlayResY: 1080\n");
167
+	    } else {
168
+            fprintf(outputf, "PlayResX: 1920\n");
169
+            fprintf(outputf, "PlayResY: 2160\n");
170
+	    }
171
+	}
172
+	fprintf(outputf, "ScaledBorderAndShadow: yes\n\n");
173
+	fprintf(outputf, "[V4+ Styles]\n");
174
+	fprintf(outputf, "Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\n");
175
+	if (!tb)
176
+        fprintf(outputf, "Style: 3D,Cube Modern Rounded Thin,60,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,0,0,0,0,100,100,0,0,1,6,0,2,0,0,0,1\n\n");
177
+    else
178
+        fprintf(outputf, "Style: 3D,Cube Modern Rounded Short,60,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,0,0,0,0,100,100,0,0,1,6,0,2,0,0,0,1\n\n");
179
+	fprintf(outputf, "[Events]\n");
180
+	fprintf(outputf, "Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\n\n");
181
+
182
+	short state = 0;
183
+	char *line = malloc(sizeof(unsigned char) * 50);
184
+	char *subtitle1 = malloc(sizeof(unsigned char) * 256);
185
+	char *subtitle2 = malloc(sizeof(unsigned char) * 256);
186
+	// read the input file and convert it
187
+	while (fgets(line, 50, inputf) != NULL) {
188
+		switch (state) {
189
+			case 0: {
190
+				// subtitle index expected
191
+				strtol(line, (char **) NULL, 10);
192
+				if (errno == EINVAL) {
193
+					// Maybe the input format is wrong
194
+					printf("Input file format is wrong\n");
195
+					fclose(inputf);
196
+					fclose(outputf);
197
+					free(input_name);
198
+					free(output_name);
199
+					return -1;
200
+				}
201
+				state = 1;
202
+				break;
203
+			}
204
+			case 1: {
205
+				// start/end time expected
206
+				unsigned short sh, sm, ss, sms;
207
+				unsigned short eh, em, es, ems;
208
+				int r = sscanf(line, "%hd:%hd:%hd,%hd --> %hd:%hd:%hd,%hd", &sh, &sm, &ss, &sms, &eh, &em, &es, &ems);
209
+				if (r == 0) {
210
+					// Maybe the input format is wrong
211
+					printf("Input file format is wrong\n");
212
+					fclose(inputf);
213
+					fclose(outputf);
214
+					free(input_name);
215
+					free(output_name);
216
+					return -1;
217
+				}
218
+
219
+				sprintf(subtitle1, "Dialogue: 0,%hd:%02hd:%02hd.%03hd,%hd:%02hd:%02hd.%03hd,3D,,0000,0000,0000,,",
220
+					sh, sm, ss, sms, eh, em, es, ems);
221
+				sprintf(subtitle2, "Dialogue: 0,%hd:%02hd:%02hd.%03hd,%hd:%02hd:%02hd.%03hd,3D,,0000,0000,0000,,",
222
+					sh, sm, ss, sms, eh, em, es, ems);
223
+
224
+				state = 2;
225
+				break;
226
+			}
227
+			case 2: {
228
+				// 1st line of the subtitle expected
229
+				if (strlen(line) == 0) {
230
+					// Maybe the input format is wrong
231
+					printf("Input file format is wrong\n");
232
+					fclose(inputf);
233
+					fclose(outputf);
234
+					free(input_name);
235
+					free(output_name);
236
+					return -1;
237
+				}
238
+
239
+                if (!tb) {
240
+                    sprintf(subtitle1 + strlen(subtitle1), "{\\pos(%d,1060)}%s", (fullres == 0 ? SBS_MIDDLE_LEFT_1920 : SBS_MIDDLE_LEFT_3840) - depth, line);
241
+                    sprintf(subtitle2 + strlen(subtitle2), "{\\pos(%d,1060)}%s", (fullres == 0 ? SBS_MIDDLE_RIGHT_1920 : SBS_MIDDLE_RIGHT_3840) + depth, line);
242
+                } else {
243
+                    sprintf(subtitle1 + strlen(subtitle1), "{\\pos(%d,1070)}%s", (fullres == 0 ? TB_MIDDLE_1920 : TB_MIDDLE_3840) - depth, line);
244
+                    sprintf(subtitle2 + strlen(subtitle2), "{\\pos(%d,530)}%s", (fullres == 0 ? TB_MIDDLE_1920 : TB_MIDDLE_3840) + depth, line);
245
+                }
246
+
247
+				state = 3;
248
+				break;
249
+			}
250
+			case 3: {
251
+				// In this case, we can have a 2nd subtitle, or an empty line
252
+				if (!isspace(*line)) {
253
+					sprintf(subtitle1 + strlen(subtitle1) - 2, "\\N%s", line);
254
+					sprintf(subtitle2 + strlen(subtitle2) - 2, "\\N%s", line);
255
+				}
256
+
257
+				fprintf(outputf, "%s", replace_tags(subtitle1));
258
+				fprintf(outputf, "%s", replace_tags(subtitle2));
259
+
260
+				state = (!isspace(*line) ? 4 : 0);
261
+				break;
262
+			}
263
+			case 4: {
264
+				// empty line expected
265
+				if (!isspace(*line)) {
266
+					// Maybe the input format is wrong
267
+					printf("Input file format is wrong\n");
268
+					fclose(inputf);
269
+					fclose(outputf);
270
+					free(input_name);
271
+					free(output_name);
272
+					return -1;
273
+				}
274
+				state = 0;
275
+			}
276
+		}
277
+	}
278
+
279
+	printf("Done\n");
280
+
281
+	fclose(inputf);
282
+	fclose(outputf);
283
+	free(input_name);
284
+	free(output_name);
285
+	return 0;
286
+}

Loading…
Cancel
Save