├── LICENSE ├── README.md └── extract.py /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CSPExtract 2 | Extract png images from Csp brushes 3 | 4 | You can find free brushes at https://www.forgotten-adventures.net/product/other/clip-studio-paint-brush-bundle/ 5 | 6 | To use it, you have to : 7 | - install Python 3.7+ (see install python for your os) 8 | - create a directory where you copy the script 9 | - create a directory where you copy your CSP brushes 10 | - in a console, type "python3 path_to_the_script/extract.py path_to_the_brushes" 11 | 12 | -------------------------------------------------------------------------------- /extract.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import sqlite3 3 | import os 4 | from os.path import isfile, join 5 | 6 | def control_args(): 7 | if (len(sys.argv) < 2): 8 | print("Error : need arguments") 9 | if (len(sys.argv) > 2): 10 | print("Error : too much arguments") 11 | if (len(sys.argv) < 2 or len(sys.argv) > 2): 12 | print("extract.py Directory_name") 13 | 14 | def get_last_pos(str, source): 15 | str_find = bytearray(str,'ascii') 16 | last_pos = 0 17 | pos = 0 18 | while True: 19 | pos = source.find(str_find, last_pos) 20 | if pos == -1: 21 | break 22 | last_pos = pos + 1 23 | return (last_pos -1) 24 | 25 | def extract_png_from_layer(working_file): 26 | try: 27 | with open(working_file, "rb") as inputFile: 28 | content = inputFile.read() 29 | if content != "": 30 | s = 'PNG' 31 | begin_pos = get_last_pos(s, content) 32 | begin_pos -= 1 33 | 34 | s = 'IEND' 35 | end_pos = get_last_pos(s, content) 36 | end_pos += 4 37 | 38 | with open(working_file+".png", 'wb') as outputFile: 39 | outputFile.write(content[begin_pos:end_pos]) 40 | except FileNotFoundError: 41 | print("File not found") 42 | 43 | def extract_sqlite_layers(working_file): 44 | con = sqlite3.connect(working_file) 45 | cur = con.cursor() 46 | cur.execute("select _PW_ID, FileData from MaterialFile") 47 | row = cur.fetchone() 48 | while row != None: 49 | #extract images 50 | file_name = working_file+"."+str(row[0])+".layer" 51 | with open(file_name, 'wb') as outputFile: 52 | outputFile.write(row[1]) 53 | extract_png_from_layer(file_name) 54 | os.remove(file_name) 55 | row = cur.fetchone() 56 | cur.close() 57 | 58 | def main(): 59 | # Control args 60 | control_args() 61 | 62 | if isfile(sys.argv[1]): 63 | print("A file provided as an argument, extracting textures from the file...") 64 | filedir='' 65 | files = [sys.argv[1]] 66 | else: 67 | filedir = sys.argv[1] 68 | files = [join(filedir,x) for x in os.listdir(filedir)] 69 | files = [x for x in files if isfile(x)] 70 | 71 | for m_file in files: 72 | print(m_file) 73 | extract_sqlite_layers(m_file) 74 | 75 | if __name__ == "__main__": 76 | main() 77 | --------------------------------------------------------------------------------