├── LICENSE
├── README.md
├── readme_images
├── 1.png
├── 17.png
├── 1x_corrected_11.png
├── 1x_corrected_12.png
├── 1x_corrected_14.png
├── 1x_corrected_16.png
├── 1x_corrected_7.png
├── 4.png
├── 8.png
├── empty
├── invalid_ex.png
└── valid_ex.png
├── svg-schema.xsd
├── tool.py
└── vcc.py
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Alexander Reben
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ✅ GAN XML Fixer 🎨
2 | ### coded by: Allan Gelman
3 | ### concept by: Alexander Reben
4 | ### supported by [Stochastic Labs](http://stochasticlabs.org/)
5 |
6 | This tool converts a txt file containing [text generated by a neural network](https://www.tensorflow.org/tutorials/sequences/text_generation) trained on Scalable Vector Graphics (svg files) into two directories, one containing the valid svg files produced, and one containing the invalid svg files produced. This tool's key feature is that it attempts to correct every invalid file, thereby producing more than 150% of the original number of valid files (specifics in the Testing section)!
7 |
8 | ## Prerequisites
9 | This tool uses [xmlschema](https://github.com/brunato/xmlschema). To import xmlschema into a Python 2.7 or 3.4+ environment, run this command:
10 |
11 | pip install xmlschema
12 |
13 | ## How To Use
14 | In the command line, cd into the root of this repository and run this command (replacing "my_txt_file.txt" with the name/path of your txt file). This will create two directories in the root of this repo named 'invalid_svg' and 'valid_svg', by default:
15 |
16 | ./vcc.py -txt my_txt_file.txt
17 |
18 | If you want to customize the path or name of the directories created, run this command:
19 |
20 | ./vcc.py -txt my_txt_file.txt -idir invalid_custom_name -vdir valid_custom_name
21 |
22 | If you want to see a help menu for this tool in the command line, run this command:
23 |
24 | ./vcc.py -h
25 |
26 | ## Naming System
27 |
28 | By default, the two directories created are called 'invalid_svg' and 'valid_svg'.
29 |
30 | Files produced are named simply by the order that they were produced in (0.svg, 1.svg, 2.svg, etc.). Some files will have certain prefixes before the number to indicate if it has been altered or not (illustrated in the example below).
31 |
32 | Here are examples of what the contents of each directory could look like, and what the names of the files inside indicate:
33 |
34 | * invalid_svg:
35 | * #.svg => an invalid file that was unable to be corrected
36 | * orig_#.svg => the original invalid version of a now corrected file in the 'valid_svg' directory
37 |
38 | 
39 |
40 | * valid_svg:
41 | * #.svg => a valid file without any correction
42 | * x_corrected_#.svg => a valid file that has had some number of attempts of correction applied
43 | * 1x => first attempt; all the 'g' tags were removed
44 | * 2x => second attempt; any extra quotation marks were removed, and any necessary quotation marks were added
45 | * 3x => third attempt; any redefinitions of the 'viewBox' or 'd' attributes were removed
46 | * 4x => fourth attempt; any missing 'path' end tags were added
47 |
48 | 
49 |
50 | ## How it Works
51 |
52 | ### 1) File Division
53 | First, the inputted txt file is divided into individual svg files by splitting on the 'svg' end tag. All the files are initially placed in the 'invalid_svg' directory.
54 |
55 | ### 2) Validation and Classification
56 | Next, the tool iterates over all the files, and validates them. The valid svg files are moved from the 'invalid_svg' directory to the 'valid_svg' directory.
57 |
58 | Validation is done using [xmlschema](https://github.com/brunato/xmlschema), which validates files written in XML (like svg files!) against a schema. A [schema](https://www.w3schools.com/xml/schema_intro.asp) is an xsd file that lists rules indicating which elements, attributes, nesting structures, and references are valid in a type of file written in XML. This tool uses a custom-made schema, with added flexibility to account for the unpredictable results of the neural network, to validate specifically svg files.
59 |
60 | For example, below is a segment from the schema which describes the attributes allowed for the 'rect' element (a rectangle element). Things to note about the added flexibility are:
61 |
62 | * the use of every attribute is `use = "optional"`
63 | * most of the attributes' types are `string`, as oppose to more restricting types, like `float` or `byte`
64 | * many of the attributes are actually not meant for a `rect` element, like `rx`, which is meant for an `ellipse` element
65 |
66 | ```xsd
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 | ```
97 |
98 | ### 3) Correction Attempts
99 | Lastly, the tool iterates over all the remaining files in the 'invalid_svg' directory, and attempts to correct them. This correction occurs recursively, attempting in order (1 - 4) to apply the next level of correction until the file is finally valid. Once the file is corrected, the corrected version is moved to the 'valid_svg' directory, with the naming specified above. If after the fourth attempt, the file is still invalid, it remains in the 'invalid_svg' directory.
100 |
101 | ## Testing
102 | From my tests, I produced 534 svg files.
103 |
104 | Without the corrections of my tool, 225 files were valid.
105 | With the correction of my tool, 352 files were valid.
106 |
107 | ### Number/Percent Valid of Total 534
108 | | w/o Corrections | w/ Corrections|
109 | | :--------------:|:-------------:|
110 | | 225 | 352 |
111 | | 42.1% | 65.9% |
112 |
113 | ### **352 is 156% of the original number of valid files!**
114 |
115 | ## Examples!
116 |
117 | I have been using the free online databases of icons, [Flaticon](https://www.flaticon.com/) and [The Noun Project](https://thenounproject.com), to create my training sets! Here are some of the coolest/weirdest/wackiest results I got!
118 |
119 | ### Trained on Shoe Icons 👟:
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 | ### Trained on Building Icons 🏢:
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 | ### Trained on Flower Icons 🌺:
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 | ## Tips for Optimizing Results
145 |
146 | * Don't get discouraged! If you don't get a cool output at first, try again! Just keep training, just keep training!
147 | * The more files you use in your training data set, the better! Training sets with 500+ files have resulted in interesting outputs for me.
148 | * Try to include repetitive or similar files in your training data set! I noticed that the more similar the files are, the better the neural network learns!
149 | * To create a repetitive data set, you can have duplicates of the same file. Having about 20 duplicates for every file in the dataset resulted in interesting outputs for me! (ex: duplicate 25 unique svg files 20 times each to create a data set of 500 files)
150 | * You can open svg files in many ways. I noticed that opening them in a browser (like chrome or safari) results in a more interesting output that opening them in Adobe Illustrator.
151 |
--------------------------------------------------------------------------------
/readme_images/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/artBoffin/GAN-XML-Fixer/7de3fbf10b1675f47ab51b7ea4f57bb66b644372/readme_images/1.png
--------------------------------------------------------------------------------
/readme_images/17.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/artBoffin/GAN-XML-Fixer/7de3fbf10b1675f47ab51b7ea4f57bb66b644372/readme_images/17.png
--------------------------------------------------------------------------------
/readme_images/1x_corrected_11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/artBoffin/GAN-XML-Fixer/7de3fbf10b1675f47ab51b7ea4f57bb66b644372/readme_images/1x_corrected_11.png
--------------------------------------------------------------------------------
/readme_images/1x_corrected_12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/artBoffin/GAN-XML-Fixer/7de3fbf10b1675f47ab51b7ea4f57bb66b644372/readme_images/1x_corrected_12.png
--------------------------------------------------------------------------------
/readme_images/1x_corrected_14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/artBoffin/GAN-XML-Fixer/7de3fbf10b1675f47ab51b7ea4f57bb66b644372/readme_images/1x_corrected_14.png
--------------------------------------------------------------------------------
/readme_images/1x_corrected_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/artBoffin/GAN-XML-Fixer/7de3fbf10b1675f47ab51b7ea4f57bb66b644372/readme_images/1x_corrected_16.png
--------------------------------------------------------------------------------
/readme_images/1x_corrected_7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/artBoffin/GAN-XML-Fixer/7de3fbf10b1675f47ab51b7ea4f57bb66b644372/readme_images/1x_corrected_7.png
--------------------------------------------------------------------------------
/readme_images/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/artBoffin/GAN-XML-Fixer/7de3fbf10b1675f47ab51b7ea4f57bb66b644372/readme_images/4.png
--------------------------------------------------------------------------------
/readme_images/8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/artBoffin/GAN-XML-Fixer/7de3fbf10b1675f47ab51b7ea4f57bb66b644372/readme_images/8.png
--------------------------------------------------------------------------------
/readme_images/empty:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/readme_images/invalid_ex.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/artBoffin/GAN-XML-Fixer/7de3fbf10b1675f47ab51b7ea4f57bb66b644372/readme_images/invalid_ex.png
--------------------------------------------------------------------------------
/readme_images/valid_ex.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/artBoffin/GAN-XML-Fixer/7de3fbf10b1675f47ab51b7ea4f57bb66b644372/readme_images/valid_ex.png
--------------------------------------------------------------------------------
/svg-schema.xsd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
493 |
494 |
495 |
496 |
497 |
498 |
499 |
500 |
501 |
502 |
503 |
504 |
505 |
506 |
507 |
508 |
509 |
510 |
511 |
512 |
513 |
514 |
515 |
516 |
517 |
518 |
519 |
520 |
521 |
522 |
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 |
531 | Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)
532 |
533 |
534 |
535 |
536 |
537 |
538 |
539 |
540 |
541 |
542 |
543 |
544 |
545 |
546 |
547 |
548 |
549 |
550 |
551 |
552 |
553 |
554 |
555 |
556 |
557 |
558 |
559 |
560 |
561 |
562 |
563 |
564 |
565 |
566 |
567 |
568 |
569 |
570 |
571 |
572 |
573 |
--------------------------------------------------------------------------------
/tool.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | """
4 | Coded by: Allan Gelman
5 | Concept by: Alexander Reben
6 | Supported by: Stochastic Labs
7 | """
8 |
9 | import xmlschema
10 | import os
11 |
12 | def txt_to_invalid_svg_dir(generated_txt, invalid_svg_dir):
13 |
14 | """
15 | Converts the generated_txt to a directory individual svg files
16 |
17 | generated_txt: name of text file of a collection of generated svg files
18 | invalid_svg_dir: path or name of desired directory to hold svg files
19 | """
20 |
21 | generated_txt = open(generated_txt, 'r')
22 | line = generated_txt.readline()
23 |
24 | #creating invalid_svg_dir if doesn't exist already
25 | if not os.path.exists(invalid_svg_dir):
26 | os.mkdir(invalid_svg_dir)
27 | print("Directory " , invalid_svg_dir , " Created ")
28 | else:
29 | print("Directory " , invalid_svg_dir , " already exists")
30 |
31 | file_content = ""
32 | carry_over = ""
33 | num_files = 0
34 |
35 | while line:
36 | svg_end_tag_found = False
37 | last_line_content = ""
38 | index_end_of_last_line = 0
39 |
40 | #svg files don't need \n to be read properly
41 | if line != "\n":
42 | char_index = 0
43 |
44 | while char_index < len(line):
45 | if line[char_index: char_index+6] == "":
46 | svg_end_tag_found = True
47 | index_end_of_last_line = char_index+6
48 |
49 | #the last line of a svg file ends with the end tag
50 | last_line_content = line[:index_end_of_last_line]
51 | carry_over = line[index_end_of_last_line:]
52 |
53 | #carryover that contains end tags is handled by helper function
54 | #returns the left over carry_over to be added to the next file and the updated num_files
55 | if "" in carry_over:
56 | carry_over, num_files = carry_over_to_files(carry_over, invalid_svg_dir, num_files)
57 | break
58 |
59 | char_index = char_index + 1
60 |
61 | #building up files contained in generated_txt
62 | #the end of svg files is marked by the end tag
63 | if not svg_end_tag_found:
64 | file_content = file_content + line
65 | else:
66 | file_content = file_content + last_line_content
67 | f = open(str(num_files)+".svg","w+")
68 | f.write(file_content)
69 | f.close()
70 | #moving all the files into the invalid_svg_dir since none of them have been validated yet
71 | os.rename(str(num_files) + ".svg", invalid_svg_dir + "/" + str(num_files)+".svg")
72 | file_content = ""
73 |
74 | for char in carry_over:
75 | if char != "\n":
76 | file_content = file_content + char
77 |
78 | num_files = num_files + 1
79 |
80 | line = generated_txt.readline()
81 |
82 | generated_txt.close()
83 |
84 | return None
85 |
86 | def carry_over_to_files(carry_over, invalid_svg_dir, num_files):
87 |
88 | """
89 | Converts the carry_over to individual svg files place in the invalid_svg_dir
90 |
91 | carry_over: string of the carry_over text
92 | invalid_svg_dir: path or name of desired directory to hold svg files
93 | num_files: number to keep track of how many files created
94 | """
95 |
96 | char_index = 0
97 | while carry_over[char_index: char_index+6] != "":
98 | char_index = char_index + 1
99 |
100 | index_end_of_file = char_index+6
101 | #the entire file is the carryover until the end tag
102 | file_content = carry_over[:index_end_of_file]
103 | carry_over = carry_over[index_end_of_file:]
104 |
105 | f = open(str(num_files) + ".svg","w+")
106 | f.write(file_content)
107 | f.close()
108 |
109 | #moving all the files into the invalid_svg_dir since none of them have been validated yet
110 | os.rename(str(num_files) + ".svg", invalid_svg_dir + "/" + str(num_files) + ".svg")
111 |
112 | #recursivley converts the carry_over to files until there is just carry_over without any end tags
113 | if "" in carry_over:
114 | return carry_over_to_files(carry_over, invalid_svg_dir, num_files+1)
115 | else:
116 | return (carry_over, num_files+1)
117 |
118 | def invalid_svg_dir_to_valid_svg_dir(invalid_svg_dir, valid_svg_dir):
119 |
120 | """
121 | Classifies the svg files into invalid and valid, and attempts to correct invalid files.
122 |
123 | invalid_svg_dir: directory of invalid svg files
124 | valid_svg_dir: directory of valid svg files
125 | """
126 |
127 | #creating valid_svg_dir if doesn't exist already
128 | if not os.path.exists(valid_svg_dir):
129 | os.mkdir(valid_svg_dir)
130 | print("Directory " , valid_svg_dir , " Created ")
131 | else:
132 | print("Directory " , valid_svg_dir , " already exists")
133 |
134 | #iterating through the files in invalid_svg_dir
135 | for filename in os.listdir(invalid_svg_dir):
136 | schema = xmlschema.XMLSchema('./svg-schema.xsd')
137 | try:
138 | valid = schema.is_valid(invalid_svg_dir + "/" + filename)
139 | except:
140 | valid = False
141 | #moving the validated files into valid_svg_dir
142 | if valid:
143 | os.rename(invalid_svg_dir + "/" + filename, valid_svg_dir + "/" + filename)
144 | else:
145 | correction_attempt(filename, 1, invalid_svg_dir + "/" + filename, invalid_svg_dir, valid_svg_dir)
146 |
147 | return None
148 |
149 | def correction_attempt(filename, num_attempts, path, invalid_svg_dir, valid_svg_dir):
150 |
151 | """
152 | Recursivley attemps to correct the svg file.
153 |
154 | filename: file attempting to be correct
155 | num_attempts: the amount of times the files has been corrected
156 | path: path of file
157 | invalid_svg_dir: directory of invalid svg files
158 | valid_svg_dir: directory of valid svg files
159 | """
160 |
161 | schema = xmlschema.XMLSchema('./svg-schema.xsd')
162 | f = open(str(num_attempts) + "x_corrected_" + filename,"w+")
163 | if num_attempts == 1:
164 | file_content = remove_g_tags(path)
165 | elif num_attempts == 2:
166 | file_content = fix_quote(path)
167 | elif num_attempts == 3:
168 | file_content = remove_redefined_attributes(path)
169 | elif num_attempts == 4:
170 | file_content = add_missing_path_end_tag(path)
171 | f.write(file_content)
172 | f.close()
173 | try:
174 | valid = schema.is_valid("./" + str(num_attempts) + "x_corrected_" + filename)
175 | except:
176 | valid = False
177 | #moving the validated files to valid_svg_dir
178 | #marking the corrected files with "num_attemptsx_corrected_" to indicate they have been modified num_attempts times
179 | #marking the original files with "orig_" to imply that their is a modified version in the valid_svg_dir
180 | if valid:
181 | os.rename(invalid_svg_dir + "/" + filename, invalid_svg_dir + "/" + "orig_" + filename)
182 | os.rename(str(num_attempts) + "x_corrected_" + filename, valid_svg_dir + "/" + str(num_attempts) + "x_corrected_" + filename)
183 | return None
184 | #deleting the files that failed to be validated after correction
185 | #recursivley attempting to correct file
186 | else:
187 | if num_attempts < 4:
188 | correction_attempt(filename, num_attempts+1, str(num_attempts) + "x_corrected_" + filename, invalid_svg_dir, valid_svg_dir)
189 | os.remove(str(num_attempts) + "x_corrected_" + filename)
190 | else:
191 | os.remove(str(num_attempts) + "x_corrected_" + filename)
192 | return None
193 |
194 | def remove_g_tags(path):
195 |
196 | """
197 | Removing all g-tags from the file.
198 |
199 | path: path of file being corrected
200 | """
201 |
202 | file_content = ""
203 | file = open(path, 'r')
204 | line = file.readline()
205 |
206 | while line:
207 | char_index = 0
208 | #passing through all the file except for the g-tags
209 | line_content = ""
210 | while char_index < len(line):
211 | if line[char_index: char_index + 3] == "":
212 | char_index=char_index + 3
213 | if line[char_index: char_index + 4] == "":
214 | char_index=char_index + 4
215 |
216 | line_content = line_content + line[char_index]
217 | char_index = char_index + 1
218 |
219 | file_content = file_content + line_content
220 | line = file.readline()
221 |
222 | return file_content
223 |
224 | def fix_quote(path):
225 |
226 | """
227 | Removing any extra quotation marks and adds any missing quotation marks
228 |
229 | path: path of file being corrected
230 | """
231 |
232 | chars_after_quote = ["/"," ", ">", "\n", "?"]
233 | start_quote_found = False
234 | file_content = ""
235 | file = open(path, 'r')
236 |
237 | for line in file:
238 | #passing through all the file except for the extra quotes
239 | i = 0
240 | line_content = ""
241 | while i < len(line):
242 | #skipping over quote that comes after '=' that isn't a start quote
243 | if line[i] == '"' and line[i-1] != '=' and start_quote_found and line[i+1] in chars_after_quote:
244 | start_quote_found = False
245 | elif line[i] == '"' and line[i-1] == '=' and not start_quote_found:
246 | start_quote_found = True
247 | elif line[i] == '"' and line[i-1] == '=' and start_quote_found:
248 | i = i + 1
249 |
250 | #skipping over any other quote that isn't a start or end quote
251 | if line[i] == '"' and line[i-1] != '=' and line[i+1] not in chars_after_quote:
252 | i = i + 1
253 | else:
254 | line_content = line_content + line[i]
255 |
256 | #adding a quote for the last attribute if it doesn't have a closing quote
257 | if line[i+1:i+2] == '>' and line[i] != '"' and start_quote_found:
258 | line_content = line_content + '"'
259 | start_quote_found = False
260 |
261 | i = i + 1
262 |
263 | #building up file_content
264 | file_content = file_content + line_content
265 | return file_content
266 |
267 | def remove_redefined_attributes(path):
268 |
269 | """
270 | Removing any redefined 'viewBox' or 'd' attributes
271 |
272 | path: path of file being corrected
273 | """
274 |
275 | file_content = ""
276 | file = open(path, 'r')
277 | file = file.read()
278 | d_attribute_found = False
279 | view_box_attribute_found = False
280 | end_tag_found = False
281 | i = 0
282 |
283 | while i < len(file):
284 | #keeping track of end tags, beacuse redefinitions occur within elements
285 | if file[i] == ">":
286 | end_tag_found = True
287 | d_attribute_found = False
288 | view_box_attribute_found = False
289 | if file[i] == "<":
290 | end_tag_found = False
291 |
292 | #skipping over d attribute
293 | if file[i:i+3] == 'd="' and not d_attribute_found:
294 | d_attribute_found = True
295 | file_content = file_content + file[i]
296 | i = i + 1
297 | elif file[i:i+3] == 'd="' and d_attribute_found and not end_tag_found:
298 | i = i + 3
299 | while file[i] != '"':
300 | i = i + 1
301 | i = i + 1
302 | else:
303 | #skipping over viewBox attribute
304 | if file[i:i+9] == 'viewBox="' and not view_box_attribute_found:
305 | view_box_attribute_found = True
306 | file_content = file_content + file[i]
307 | i = i + 1
308 | elif file[i:i+9] == 'viewBox="' and view_box_attribute_found and not end_tag_found:
309 | i = i + 9
310 | while file[i] != '"':
311 | i = i + 1
312 | i = i + 1
313 | else:
314 | file_content = file_content + file[i]
315 | i = i + 1
316 |
317 | return file_content
318 |
319 | def add_missing_path_end_tag(path):
320 |
321 | """
322 | Adding any missing path end tags
323 |
324 | path: path of file being corrected
325 | """
326 |
327 | file_content = ""
328 | file = open(path, 'r')
329 | path_start_tag_found = False
330 |
331 | for line in file:
332 | i = 0
333 | line_content = ""
334 | while i < len(line):
335 | if line[i:i+5] == "" and path_start_tag_found and line [i+1: i+8] == "":
338 | path_start_tag_found = False
339 | #adding path end tag
340 | elif line[i] == ">" and path_start_tag_found and line [i+1: i+8] != "":
341 | path_start_tag_found = False
342 | line_content = line_content + line[i]
343 | line_content = line_content + ""
344 | i = i + 1
345 | continue
346 |
347 | line_content = line_content + line[i]
348 | i = i + 1
349 |
350 | file_content = file_content + line_content
351 |
352 | return file_content
353 |
354 | def txt_to_valid_svg_dir(generated_txt, invalid_svg_dir, valid_svg_dir):
355 |
356 | """
357 | Contains all the actions of this tool. Converting the text file to classified folders of svg files.
358 |
359 | generated_txt: name of text file of a collection of generated svg files
360 | invalid_svg_dir: directory of invalid svg files
361 | valid_svg_dir: directory of valid svg files
362 | """
363 |
364 | txt_to_invalid_svg_dir(generated_txt, invalid_svg_dir)
365 | invalid_svg_dir_to_valid_svg_dir(invalid_svg_dir, valid_svg_dir)
366 |
367 | if __name__ == '__main__':
368 | pass
369 |
--------------------------------------------------------------------------------
/vcc.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | """
4 | Coded by: Allan Gelman
5 | Concept by: Alexander Reben
6 | Supported by: Stochastic Labs
7 | """
8 |
9 | #! /usr/bin/env python
10 | import argparse
11 | import tool
12 |
13 | def run(args):
14 | generated_txt = args.txt_input
15 | invalid_svg_dir = args.idir_output
16 | valid_svg_dir = args.vdir_output
17 | tool.txt_to_valid_svg_dir(generated_txt, invalid_svg_dir, valid_svg_dir)
18 |
19 | def main():
20 | parser=argparse.ArgumentParser(description="Validate, Correct, and Classify generated SVG files")
21 | parser.add_argument("-txt",help="Path of generated text file trained on Scalable Vector Graphics (.svg files)" ,dest="txt_input", type=str, required=True)
22 | parser.add_argument("-idir",help="Path of the output invalid SVG directory. Default = invalid_svg" ,dest="idir_output", type=str, default="invalid_svg")
23 | parser.add_argument("-vdir",help="Path of the output valid SVG directory. Default = valid_svg" ,dest="vdir_output", type=str, default="valid_svg")
24 | parser.set_defaults(func=run)
25 | args=parser.parse_args()
26 | args.func(args)
27 |
28 | if __name__=="__main__":
29 | main()
--------------------------------------------------------------------------------