├── 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 | ![example of invalid directory](./readme_images/invalid_ex.png) 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 | ![example of valid directory](./readme_images/valid_ex.png) 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 | drawing  122 | 123 | drawing  124 | 125 | drawing  126 | 127 | ### Trained on Building Icons 🏢: 128 | 129 | drawing  130 | 131 | drawing  132 | 133 | drawing  134 | 135 | ### Trained on Flower Icons 🌺: 136 | 137 | drawing  138 | 139 | drawing  140 | 141 | drawing  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() --------------------------------------------------------------------------------