├── README.md ├── __pycache__ ├── draw.cpython-38.pyc ├── drawbot.cpython-38.pyc └── utils.cpython-38.pyc ├── app.py ├── app.spec ├── app.ui ├── colorPalettes ├── garticColors.txt ├── garticCoordinates.txt ├── paintColors.txt ├── paintCoordinates.txt ├── skribblColors.txt └── skribblCoordinates.txt ├── drawbot.ico ├── drawbot.py └── utils.py /README.md: -------------------------------------------------------------------------------- 1 | # DrawBot 2 | 3 | You don't speak french? No worries, [english translation is over here.](#Drawbot-in-english) 4 | Не беспокойтесь, [о Русских позаботились.](#Drawbot-in-russian) 5 | [中国人在这里](#Drawbot-in-chinese) 6 | ## C'est quoi ? 7 | 8 | DrawBot est un logiciel codé par [V2F](https://youtube.com/user/IV2FI) qui va prendre possession de ta souris pour dessiner à ta place sur des sites comme Gartic Phone ou Skribbl.io. Il est doté d'une UI avec pas mal d'options pour rendre le tout simple d'utilisation. 9 | Voici un petit gif de ce que tu peux faire avec : 10 | 11 | ![Gif qui montre à quoi ça ressemble](https://user-images.githubusercontent.com/63878365/107878420-d7f0c480-6ed2-11eb-83de-f5bf8a276b50.gif) 12 | 13 | ## Ca se télécharge où ? 14 | 15 | Ici, le .zip : https://github.com/IV2FI/DrawBot/releases 16 | 17 | **Mais regarde d'abord la vidéo ci-dessous pour comprendre comment set up tout ça et comment bien utiliser DrawBot !** 18 | 19 | ## Installation et utilisation 20 | 21 | "Une image vaut mille mots", il paraît, alors voici une vidéo ou je t'explique tout ! Il y a une étape à faire pour configurer le bot **sans quoi il ne marchera probablement pas ! (ça prend 5 min max)** Donc regarde la vidéo ! 22 | 23 | **/!\ J'AI OUBLIE DE LE PRECISER DANS LA VIDEO. UNE FOIS LE SET UP FINI, REDEMARRE LE LOGICIEL ! Aussi, Paint n'a pas l'air de très bien marcher.** 24 | 25 | https://youtu.be/vMTNtDWsS4k 26 | 27 | # Drawbot (in english) 28 | 29 | DrawBot is a software made by [V2F](https://youtube.com/user/IV2FI), which will take control of your mouse to draw images on websites like Gartic Phone or Skribbl.io. It has a UI with quite a lot of options to make things really easy for you. 30 | 31 | ![Gif qui montre à quoi ça ressemble](https://user-images.githubusercontent.com/63878365/107878420-d7f0c480-6ed2-11eb-83de-f5bf8a276b50.gif) 32 | 33 | ## Where can I download it? 34 | 35 | Over here, the .zip file: https://github.com/IV2FI/DrawBot/releases 36 | 37 | **Before downloading, please watch the video below to understand how set up everything! Thanks** 38 | 39 | ## How to install and use the bot? 40 | 41 | Watch that video and the bot will have no secrets for you: 42 | 43 | **/!\ I FORGOT TO MENTION IT IN THE VIDEO, ONCE DONE WITH THE SET UP PART, RESTART THE SOFTWARE! Also, it does not seem to work very well with Paint.** 44 | 45 | https://youtu.be/bdCBftJV25s 46 | # Drawbot (in russian) 47 | 48 | DrawBot это программа сделанная [V2F](https://youtube.com/user/IV2FI), которая будет рисовать за вас в Gartic.io, Paint, Skribbl.io. 49 | 50 | ![Гифка работы](https://user-images.githubusercontent.com/63878365/107878420-d7f0c480-6ed2-11eb-83de-f5bf8a276b50.gif) 51 | 52 | ## Где скачать? 53 | 54 | .zip архив: https://github.com/IV2FI/DrawBot/releases 55 | 56 | **До скачивания посмотрите видео чтобы понимать как устроена данная программа** 57 | ## Как установить бота? 58 | Посмотрите видео !не забудьте включить Яндекс Переводчик :)!: 59 | https://youtu.be/vMTNtDWsS4k 60 | 61 | # Drawbot (in chinese) 62 | DrawBot 是一个由 V2F 制作的程序,可以在 Gartic.io、Paint、Skribbl.io 中为您绘图。 63 | 64 | ![Гифка работы](https://user-images.githubusercontent.com/63878365/107878420-d7f0c480-6ed2-11eb-83de-f5bf8a276b50.gif) 65 | ## 哪里可以下载? 66 | 67 | .zip 存档:https://github.com/IV2FI/DrawBot/releases 68 | 69 | **下载之前,请观看视频以了解该程序的工作原理。** 70 | ## 如何安装机器人? 71 | 72 | 观看视频!别忘了打开 Yandex 翻译器:)!:https://youtu.be/vMTNtDWsS4k 73 | -------------------------------------------------------------------------------- /__pycache__/draw.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IV2FI/DrawBot/62994ea5e7da2b255d418d4f759f121ac5269000/__pycache__/draw.cpython-38.pyc -------------------------------------------------------------------------------- /__pycache__/drawbot.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IV2FI/DrawBot/62994ea5e7da2b255d418d4f759f121ac5269000/__pycache__/drawbot.cpython-38.pyc -------------------------------------------------------------------------------- /__pycache__/utils.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IV2FI/DrawBot/62994ea5e7da2b255d418d4f759f121ac5269000/__pycache__/utils.cpython-38.pyc -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Form implementation generated from reading ui file 'app.ui' 4 | # 5 | # Created by: PyQt5 UI code generator 5.15.2 6 | # 7 | # WARNING: Any manual changes made to this file will be lost when pyuic5 is 8 | # run again. Do not edit this file unless you know what you are doing. 9 | 10 | 11 | from PyQt5 import QtCore, QtGui, QtWidgets 12 | from pynput.keyboard import Key, Listener 13 | import utils 14 | import drawbot 15 | import threading 16 | 17 | try: 18 | # Include in try/except block if you're also targeting Mac/Linux 19 | from PyQt5.QtWinExtras import QtWin 20 | myappid = 'v2f.drawbot.1' 21 | QtWin.setCurrentProcessExplicitAppUserModelID(myappid) 22 | except ImportError: 23 | pass 24 | 25 | class Ui_MainWindow(object): 26 | 27 | def setupUi(self, MainWindow): 28 | MainWindow.setObjectName("MainWindow") 29 | MainWindow.resize(299, 613) 30 | self.centralwidget = QtWidgets.QWidget(MainWindow) 31 | self.centralwidget.setObjectName("centralwidget") 32 | self.verticalLayoutWidget = QtWidgets.QWidget(self.centralwidget) 33 | self.verticalLayoutWidget.setGeometry(QtCore.QRect(0, 0, 300, 581)) 34 | self.verticalLayoutWidget.setObjectName("verticalLayoutWidget") 35 | self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget) 36 | self.verticalLayout.setContentsMargins(20, 20, 20, 20) 37 | self.verticalLayout.setObjectName("verticalLayout") 38 | self.title = QtWidgets.QLabel(self.verticalLayoutWidget) 39 | self.title.setStyleSheet("font-weight:bold;") 40 | self.title.setObjectName("title") 41 | self.verticalLayout.addWidget(self.title, 0, QtCore.Qt.AlignHCenter|QtCore.Qt.AlignVCenter) 42 | spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) 43 | self.verticalLayout.addItem(spacerItem) 44 | self.urlTextBox = QtWidgets.QLineEdit(self.verticalLayoutWidget) 45 | self.urlTextBox.setText("") 46 | self.urlTextBox.setObjectName("urlTextBox") 47 | self.verticalLayout.addWidget(self.urlTextBox) 48 | spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) 49 | self.verticalLayout.addItem(spacerItem1) 50 | self.appLabel = QtWidgets.QLabel(self.verticalLayoutWidget) 51 | self.appLabel.setStyleSheet("") 52 | self.appLabel.setObjectName("appLabel") 53 | self.verticalLayout.addWidget(self.appLabel) 54 | self.appBox = QtWidgets.QComboBox(self.verticalLayoutWidget) 55 | self.appBox.setObjectName("appBox") 56 | self.appBox.addItem("") 57 | self.appBox.addItem("") 58 | self.appBox.addItem("") 59 | self.verticalLayout.addWidget(self.appBox) 60 | spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) 61 | self.verticalLayout.addItem(spacerItem2) 62 | self.speedLabel = QtWidgets.QLabel(self.verticalLayoutWidget) 63 | self.speedLabel.setObjectName("speedLabel") 64 | self.verticalLayout.addWidget(self.speedLabel) 65 | self.speedSlider = QtWidgets.QSlider(self.verticalLayoutWidget) 66 | self.speedSlider.setMinimum(1) 67 | self.speedSlider.setMaximum(4) 68 | self.speedSlider.setProperty("value", 3) 69 | self.speedSlider.setOrientation(QtCore.Qt.Horizontal) 70 | self.speedSlider.setObjectName("speedSlider") 71 | self.verticalLayout.addWidget(self.speedSlider) 72 | spacerItem3 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) 73 | self.verticalLayout.addItem(spacerItem3) 74 | self.skippedPixelsLabel = QtWidgets.QLabel(self.verticalLayoutWidget) 75 | self.skippedPixelsLabel.setObjectName("skippedPixelsLabel") 76 | self.verticalLayout.addWidget(self.skippedPixelsLabel) 77 | self.label_4 = QtWidgets.QLabel(self.verticalLayoutWidget) 78 | self.label_4.setStyleSheet("font-size: 10px;") 79 | self.label_4.setObjectName("label_4") 80 | self.verticalLayout.addWidget(self.label_4) 81 | self.skippedPixelSlider = QtWidgets.QSlider(self.verticalLayoutWidget) 82 | self.skippedPixelSlider.setMinimum(1) 83 | self.skippedPixelSlider.setMaximum(12) 84 | self.skippedPixelSlider.setSingleStep(1) 85 | self.skippedPixelSlider.setProperty("value", 5) 86 | self.skippedPixelSlider.setOrientation(QtCore.Qt.Horizontal) 87 | self.skippedPixelSlider.setObjectName("skippedPixelSlider") 88 | self.verticalLayout.addWidget(self.skippedPixelSlider) 89 | spacerItem4 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) 90 | self.verticalLayout.addItem(spacerItem4) 91 | self.horizontalLayout = QtWidgets.QHBoxLayout() 92 | self.horizontalLayout.setObjectName("horizontalLayout") 93 | self.ignorePixelBox = QtWidgets.QCheckBox(self.verticalLayoutWidget) 94 | self.ignorePixelBox.setObjectName("ignorePixelBox") 95 | self.horizontalLayout.addWidget(self.ignorePixelBox, 0, QtCore.Qt.AlignHCenter) 96 | self.ditherBox = QtWidgets.QCheckBox(self.verticalLayoutWidget) 97 | self.ditherBox.setObjectName("ditherBox") 98 | self.horizontalLayout.addWidget(self.ditherBox, 0, QtCore.Qt.AlignHCenter) 99 | self.verticalLayout.addLayout(self.horizontalLayout) 100 | spacerItem5 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) 101 | self.verticalLayout.addItem(spacerItem5) 102 | self.coordinateButton = QtWidgets.QPushButton(self.verticalLayoutWidget) 103 | self.coordinateButton.setObjectName("coordinateButton") 104 | self.verticalLayout.addWidget(self.coordinateButton) 105 | self.MouseCoordinateLabel = QtWidgets.QLabel(self.verticalLayoutWidget) 106 | self.verticalLayout.addWidget(self.MouseCoordinateLabel, 0, QtCore.Qt.AlignHCenter) 107 | spacerItem6 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) 108 | self.verticalLayout.addItem(spacerItem6) 109 | self.setBoundsButton = QtWidgets.QPushButton(self.verticalLayoutWidget) 110 | self.setBoundsButton.setObjectName("setBoundsButton") 111 | self.verticalLayout.addWidget(self.setBoundsButton) 112 | self.widthLabel = QtWidgets.QLabel(self.verticalLayoutWidget) 113 | self.widthLabel.setObjectName("widthLabel") 114 | self.verticalLayout.addWidget(self.widthLabel, 0, QtCore.Qt.AlignHCenter) 115 | spacerItem7 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) 116 | self.verticalLayout.addItem(spacerItem7) 117 | self.drawButton = QtWidgets.QPushButton(self.verticalLayoutWidget) 118 | palette = QtGui.QPalette() 119 | brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) 120 | brush.setStyle(QtCore.Qt.SolidPattern) 121 | palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.WindowText, brush) 122 | gradient = QtGui.QRadialGradient(0.5, 0.5, 0.5, 0.5, 0.5) 123 | gradient.setSpread(QtGui.QGradient.PadSpread) 124 | gradient.setCoordinateMode(QtGui.QGradient.ObjectBoundingMode) 125 | gradient.setColorAt(0.0, QtGui.QColor(0, 134, 22)) 126 | gradient.setColorAt(1.0, QtGui.QColor(0, 74, 26)) 127 | brush = QtGui.QBrush(gradient) 128 | palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Button, brush) 129 | brush = QtGui.QBrush(QtGui.QColor(0, 255, 0)) 130 | brush.setStyle(QtCore.Qt.SolidPattern) 131 | palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Light, brush) 132 | brush = QtGui.QBrush(QtGui.QColor(0, 212, 0)) 133 | brush.setStyle(QtCore.Qt.SolidPattern) 134 | palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Midlight, brush) 135 | brush = QtGui.QBrush(QtGui.QColor(0, 85, 0)) 136 | brush.setStyle(QtCore.Qt.SolidPattern) 137 | palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Dark, brush) 138 | brush = QtGui.QBrush(QtGui.QColor(0, 113, 0)) 139 | brush.setStyle(QtCore.Qt.SolidPattern) 140 | palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Mid, brush) 141 | brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) 142 | brush.setStyle(QtCore.Qt.SolidPattern) 143 | palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Text, brush) 144 | brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) 145 | brush.setStyle(QtCore.Qt.SolidPattern) 146 | palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.BrightText, brush) 147 | brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) 148 | brush.setStyle(QtCore.Qt.SolidPattern) 149 | palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.ButtonText, brush) 150 | gradient = QtGui.QRadialGradient(0.5, 0.5, 0.5, 0.5, 0.5) 151 | gradient.setSpread(QtGui.QGradient.PadSpread) 152 | gradient.setCoordinateMode(QtGui.QGradient.ObjectBoundingMode) 153 | gradient.setColorAt(0.0, QtGui.QColor(0, 134, 22)) 154 | gradient.setColorAt(1.0, QtGui.QColor(0, 74, 26)) 155 | brush = QtGui.QBrush(gradient) 156 | palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Base, brush) 157 | gradient = QtGui.QRadialGradient(0.5, 0.5, 0.5, 0.5, 0.5) 158 | gradient.setSpread(QtGui.QGradient.PadSpread) 159 | gradient.setCoordinateMode(QtGui.QGradient.ObjectBoundingMode) 160 | gradient.setColorAt(0.0, QtGui.QColor(0, 134, 22)) 161 | gradient.setColorAt(1.0, QtGui.QColor(0, 74, 26)) 162 | brush = QtGui.QBrush(gradient) 163 | palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Window, brush) 164 | brush = QtGui.QBrush(QtGui.QColor(0, 0, 0)) 165 | brush.setStyle(QtCore.Qt.SolidPattern) 166 | palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Shadow, brush) 167 | brush = QtGui.QBrush(QtGui.QColor(127, 212, 127)) 168 | brush.setStyle(QtCore.Qt.SolidPattern) 169 | palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.AlternateBase, brush) 170 | brush = QtGui.QBrush(QtGui.QColor(255, 255, 220)) 171 | brush.setStyle(QtCore.Qt.SolidPattern) 172 | palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.ToolTipBase, brush) 173 | brush = QtGui.QBrush(QtGui.QColor(0, 0, 0)) 174 | brush.setStyle(QtCore.Qt.SolidPattern) 175 | palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.ToolTipText, brush) 176 | brush = QtGui.QBrush(QtGui.QColor(0, 0, 0, 128)) 177 | brush.setStyle(QtCore.Qt.SolidPattern) 178 | palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.PlaceholderText, brush) 179 | brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) 180 | brush.setStyle(QtCore.Qt.SolidPattern) 181 | palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.WindowText, brush) 182 | gradient = QtGui.QRadialGradient(0.5, 0.5, 0.5, 0.5, 0.5) 183 | gradient.setSpread(QtGui.QGradient.PadSpread) 184 | gradient.setCoordinateMode(QtGui.QGradient.ObjectBoundingMode) 185 | gradient.setColorAt(0.0, QtGui.QColor(0, 134, 22)) 186 | gradient.setColorAt(1.0, QtGui.QColor(0, 74, 26)) 187 | brush = QtGui.QBrush(gradient) 188 | palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Button, brush) 189 | brush = QtGui.QBrush(QtGui.QColor(0, 255, 0)) 190 | brush.setStyle(QtCore.Qt.SolidPattern) 191 | palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Light, brush) 192 | brush = QtGui.QBrush(QtGui.QColor(0, 212, 0)) 193 | brush.setStyle(QtCore.Qt.SolidPattern) 194 | palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Midlight, brush) 195 | brush = QtGui.QBrush(QtGui.QColor(0, 85, 0)) 196 | brush.setStyle(QtCore.Qt.SolidPattern) 197 | palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Dark, brush) 198 | brush = QtGui.QBrush(QtGui.QColor(0, 113, 0)) 199 | brush.setStyle(QtCore.Qt.SolidPattern) 200 | palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Mid, brush) 201 | brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) 202 | brush.setStyle(QtCore.Qt.SolidPattern) 203 | palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Text, brush) 204 | brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) 205 | brush.setStyle(QtCore.Qt.SolidPattern) 206 | palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.BrightText, brush) 207 | brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) 208 | brush.setStyle(QtCore.Qt.SolidPattern) 209 | palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.ButtonText, brush) 210 | gradient = QtGui.QRadialGradient(0.5, 0.5, 0.5, 0.5, 0.5) 211 | gradient.setSpread(QtGui.QGradient.PadSpread) 212 | gradient.setCoordinateMode(QtGui.QGradient.ObjectBoundingMode) 213 | gradient.setColorAt(0.0, QtGui.QColor(0, 134, 22)) 214 | gradient.setColorAt(1.0, QtGui.QColor(0, 74, 26)) 215 | brush = QtGui.QBrush(gradient) 216 | palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Base, brush) 217 | gradient = QtGui.QRadialGradient(0.5, 0.5, 0.5, 0.5, 0.5) 218 | gradient.setSpread(QtGui.QGradient.PadSpread) 219 | gradient.setCoordinateMode(QtGui.QGradient.ObjectBoundingMode) 220 | gradient.setColorAt(0.0, QtGui.QColor(0, 134, 22)) 221 | gradient.setColorAt(1.0, QtGui.QColor(0, 74, 26)) 222 | brush = QtGui.QBrush(gradient) 223 | palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Window, brush) 224 | brush = QtGui.QBrush(QtGui.QColor(0, 0, 0)) 225 | brush.setStyle(QtCore.Qt.SolidPattern) 226 | palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Shadow, brush) 227 | brush = QtGui.QBrush(QtGui.QColor(127, 212, 127)) 228 | brush.setStyle(QtCore.Qt.SolidPattern) 229 | palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.AlternateBase, brush) 230 | brush = QtGui.QBrush(QtGui.QColor(255, 255, 220)) 231 | brush.setStyle(QtCore.Qt.SolidPattern) 232 | palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.ToolTipBase, brush) 233 | brush = QtGui.QBrush(QtGui.QColor(0, 0, 0)) 234 | brush.setStyle(QtCore.Qt.SolidPattern) 235 | palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.ToolTipText, brush) 236 | brush = QtGui.QBrush(QtGui.QColor(0, 0, 0, 128)) 237 | brush.setStyle(QtCore.Qt.SolidPattern) 238 | palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.PlaceholderText, brush) 239 | brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) 240 | brush.setStyle(QtCore.Qt.SolidPattern) 241 | palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.WindowText, brush) 242 | gradient = QtGui.QRadialGradient(0.5, 0.5, 0.5, 0.5, 0.5) 243 | gradient.setSpread(QtGui.QGradient.PadSpread) 244 | gradient.setCoordinateMode(QtGui.QGradient.ObjectBoundingMode) 245 | gradient.setColorAt(0.0, QtGui.QColor(0, 134, 22)) 246 | gradient.setColorAt(1.0, QtGui.QColor(0, 74, 26)) 247 | brush = QtGui.QBrush(gradient) 248 | palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Button, brush) 249 | brush = QtGui.QBrush(QtGui.QColor(0, 255, 0)) 250 | brush.setStyle(QtCore.Qt.SolidPattern) 251 | palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Light, brush) 252 | brush = QtGui.QBrush(QtGui.QColor(0, 212, 0)) 253 | brush.setStyle(QtCore.Qt.SolidPattern) 254 | palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Midlight, brush) 255 | brush = QtGui.QBrush(QtGui.QColor(0, 85, 0)) 256 | brush.setStyle(QtCore.Qt.SolidPattern) 257 | palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Dark, brush) 258 | brush = QtGui.QBrush(QtGui.QColor(0, 113, 0)) 259 | brush.setStyle(QtCore.Qt.SolidPattern) 260 | palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Mid, brush) 261 | brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) 262 | brush.setStyle(QtCore.Qt.SolidPattern) 263 | palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Text, brush) 264 | brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) 265 | brush.setStyle(QtCore.Qt.SolidPattern) 266 | palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.BrightText, brush) 267 | brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) 268 | brush.setStyle(QtCore.Qt.SolidPattern) 269 | palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.ButtonText, brush) 270 | gradient = QtGui.QRadialGradient(0.5, 0.5, 0.5, 0.5, 0.5) 271 | gradient.setSpread(QtGui.QGradient.PadSpread) 272 | gradient.setCoordinateMode(QtGui.QGradient.ObjectBoundingMode) 273 | gradient.setColorAt(0.0, QtGui.QColor(0, 134, 22)) 274 | gradient.setColorAt(1.0, QtGui.QColor(0, 74, 26)) 275 | brush = QtGui.QBrush(gradient) 276 | palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Base, brush) 277 | gradient = QtGui.QRadialGradient(0.5, 0.5, 0.5, 0.5, 0.5) 278 | gradient.setSpread(QtGui.QGradient.PadSpread) 279 | gradient.setCoordinateMode(QtGui.QGradient.ObjectBoundingMode) 280 | gradient.setColorAt(0.0, QtGui.QColor(0, 134, 22)) 281 | gradient.setColorAt(1.0, QtGui.QColor(0, 74, 26)) 282 | brush = QtGui.QBrush(gradient) 283 | palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Window, brush) 284 | brush = QtGui.QBrush(QtGui.QColor(0, 0, 0)) 285 | brush.setStyle(QtCore.Qt.SolidPattern) 286 | palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Shadow, brush) 287 | brush = QtGui.QBrush(QtGui.QColor(0, 170, 0)) 288 | brush.setStyle(QtCore.Qt.SolidPattern) 289 | palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.AlternateBase, brush) 290 | brush = QtGui.QBrush(QtGui.QColor(255, 255, 220)) 291 | brush.setStyle(QtCore.Qt.SolidPattern) 292 | palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.ToolTipBase, brush) 293 | brush = QtGui.QBrush(QtGui.QColor(0, 0, 0)) 294 | brush.setStyle(QtCore.Qt.SolidPattern) 295 | palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.ToolTipText, brush) 296 | brush = QtGui.QBrush(QtGui.QColor(0, 0, 0, 128)) 297 | brush.setStyle(QtCore.Qt.SolidPattern) 298 | palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.PlaceholderText, brush) 299 | self.drawButton.setPalette(palette) 300 | self.drawButton.setStyleSheet("background-color: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.5, fy:0.5, stop:0 rgba(0, 134, 22, 255), stop:1 rgba(0, 74, 26, 255));\n" 301 | "font-weight: bold;\n" 302 | "color: white;\n" 303 | "height: 30px;\n" 304 | "") 305 | self.drawButton.setObjectName("drawButton") 306 | self.verticalLayout.addWidget(self.drawButton) 307 | spacerItem8 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) 308 | self.verticalLayout.addItem(spacerItem8) 309 | self.errorLabel = QtWidgets.QLabel(self.verticalLayoutWidget) 310 | self.errorLabel.setStyleSheet("color: rgb(170, 0, 0);\n" 311 | "font-weight: bold;\n" 312 | "") 313 | self.errorLabel.setObjectName("errorLabel") 314 | self.verticalLayout.addWidget(self.errorLabel, 0, QtCore.Qt.AlignHCenter) 315 | MainWindow.setCentralWidget(self.centralwidget) 316 | self.menubar = QtWidgets.QMenuBar(MainWindow) 317 | self.menubar.setGeometry(QtCore.QRect(0, 0, 299, 21)) 318 | self.menubar.setObjectName("menubar") 319 | MainWindow.setMenuBar(self.menubar) 320 | self.statusbar = QtWidgets.QStatusBar(MainWindow) 321 | self.statusbar.setObjectName("statusbar") 322 | MainWindow.setStatusBar(self.statusbar) 323 | 324 | # Custom values 325 | self.width = 0 326 | self.height = 0 327 | self.startPosition = (0, 0) 328 | self.ignorePixels = False 329 | self.dither = False 330 | self.speed = 3 331 | self.pixelInterval = 5 332 | self.url = "" 333 | self.app = 0 334 | self.colors, self.coordinates = utils.getPalette(self.app) 335 | self.drawingThread = None 336 | 337 | # Signals 338 | self.coordinateButton.clicked.connect(self.displayMouseCoordinates) 339 | self.setBoundsButton.clicked.connect(self.setBounds) 340 | self.ditherBox.clicked.connect(self.setDither) 341 | self.ignorePixelBox.clicked.connect(self.setIgnorePixel) 342 | self.speedSlider.valueChanged.connect(self.setSpeed) 343 | self.skippedPixelSlider.valueChanged.connect(self.setPixelInterval) 344 | self.appBox.currentIndexChanged.connect(self.setApp) 345 | self.urlTextBox.textChanged.connect(self.setUrl) 346 | self.drawButton.clicked.connect(self.draw) 347 | 348 | # Collect keyboard events 349 | listener = Listener( 350 | on_press=self.on_press) 351 | listener.start() 352 | 353 | 354 | self.retranslateUi(MainWindow) 355 | QtCore.QMetaObject.connectSlotsByName(MainWindow) 356 | 357 | def retranslateUi(self, MainWindow): 358 | _translate = QtCore.QCoreApplication.translate 359 | MainWindow.setWindowTitle(_translate("MainWindow", "DrawBot")) 360 | MainWindow.setWindowIcon(QtGui.QIcon('drawbot.ico')) 361 | self.title.setText(_translate("MainWindow", "DrawBot par @IV2FI")) 362 | self.urlTextBox.setPlaceholderText(_translate("MainWindow", "Url de l\'image à dessiner")) 363 | self.appLabel.setText(_translate("MainWindow", "Sur quoi vais-je dessiner ?")) 364 | self.appBox.setItemText(0, _translate("MainWindow", "Gartic Phone")) 365 | self.appBox.setItemText(1, _translate("MainWindow", "Skribbl")) 366 | self.appBox.setItemText(2, _translate("MainWindow", "Paint")) 367 | self.speedLabel.setText(_translate("MainWindow", "Vitesse")) 368 | self.skippedPixelsLabel.setText(_translate("MainWindow", "Pixels ignorés")) 369 | self.label_4.setText(_translate("MainWindow", "Moins on en ignore, plus c\'est précis (mais lent)")) 370 | self.ignorePixelBox.setText(_translate("MainWindow", "Ignorer pixels isolés")) 371 | self.ditherBox.setText(_translate("MainWindow", "Dither")) 372 | self.coordinateButton.setText(_translate("MainWindow", "Obtenir les coordonnées de la souris (au clic suivant)")) 373 | self.MouseCoordinateLabel.setText(_translate("MainWindow", "Les coordonnées s\'afficheront ici")) 374 | self.setBoundsButton.setText(_translate("MainWindow", "Définir la taille du dessin")) 375 | self.widthLabel.setText(_translate("MainWindow", "Actuellement : Aucun.")) 376 | self.drawButton.setText(_translate("MainWindow", "Dessine !")) 377 | self.errorLabel.setText(_translate("MainWindow", "")) 378 | 379 | def on_press(self, key): 380 | if key == Key.esc and self.drawingThread != None: 381 | self.exit_event.set() 382 | 383 | def setApp(self, value): 384 | self.app = value 385 | self.colors, self.coordinates = utils.getPalette(self.app) 386 | 387 | def setUrl(self, value): 388 | self.url = value 389 | 390 | def setSpeed(self, value): 391 | self.speed = value 392 | 393 | def setPixelInterval(self, value): 394 | self.pixelInterval = value 395 | self.skippedPixelsLabel.setText("Pixels ignorés : " + str(value)) 396 | 397 | def setDither(self): 398 | self.dither = self.ditherBox.isChecked() 399 | 400 | def setIgnorePixel(self): 401 | self.ignorePixels = self.ignorePixelBox.isChecked() 402 | 403 | def setBounds(self): 404 | t = threading.Thread(target=self.setBoundsWorker) 405 | t.start() 406 | 407 | def setBoundsWorker(self): 408 | self.widthLabel.setText("En cours de selection...") 409 | self.MouseCoordinateLabel.adjustSize() 410 | bounds = utils.getBounds() 411 | self.width = abs(bounds[0][0] - bounds[1][0]) 412 | self.height = abs(bounds[0][1] - bounds[1][1]) 413 | self.startPosition = (bounds[0][0], bounds[0][1]) 414 | self.widthLabel.setText(str(self.width) + ' x ' + str(self.height) + ' px') 415 | 416 | def displayMouseCoordinates(self): 417 | t = threading.Thread(target=self.displayMouseCoordinatesWorker) 418 | t.start() 419 | 420 | def displayMouseCoordinatesWorker(self): 421 | self.MouseCoordinateLabel.setText(str(utils.getNextMouseClickPositionCoordinates())) 422 | 423 | def draw(self): 424 | if self.url != "" and self.width != 0: 425 | self.exit_event = threading.Event() 426 | self.errorLabel.setText("") 427 | self.drawingThread = threading.Thread(target=self.drawWorker) 428 | self.drawingThread.start() 429 | else: 430 | if self.url == "": 431 | self.errorLabel.setText("J'ai besoin d'une URL") 432 | elif self.width == 0: 433 | self.errorLabel.setText("J'ai besoin de la taille de dessin voulue") 434 | 435 | def drawWorker(self): 436 | try: 437 | draw = drawbot.DrawBot(self.width, self.height, self.startPosition, self.ignorePixels, self.dither, self.speed, self.pixelInterval, self.url, self.colors, self.coordinates) 438 | draw.draw(self.exit_event) 439 | except Exception as error: 440 | print(error) 441 | self.errorLabel.setText("L'URL n'est pas bonne ou pas une image") 442 | pass 443 | self.drawingThread = None 444 | 445 | if __name__ == "__main__": 446 | import sys 447 | app = QtWidgets.QApplication(sys.argv) 448 | MainWindow = QtWidgets.QMainWindow() 449 | ui = Ui_MainWindow() 450 | ui.setupUi(MainWindow) 451 | MainWindow.show() 452 | sys.exit(app.exec_()) 453 | -------------------------------------------------------------------------------- /app.spec: -------------------------------------------------------------------------------- 1 | # -*- mode: python ; coding: utf-8 -*- 2 | 3 | block_cipher = None 4 | 5 | 6 | a = Analysis(['app.py', 'drawbot.py', 'utils.py'], 7 | pathex=['C:\\Users\\victo\\Documents\\code\\DrawBot'], 8 | binaries=[('colorPalettes//', 'colorPalettes'), ('drawbot.ico', '.')], 9 | datas=[], 10 | hiddenimports=[], 11 | hookspath=[], 12 | runtime_hooks=[], 13 | excludes=[], 14 | win_no_prefer_redirects=False, 15 | win_private_assemblies=False, 16 | cipher=block_cipher, 17 | noarchive=False) 18 | pyz = PYZ(a.pure, a.zipped_data, 19 | cipher=block_cipher) 20 | exe = EXE(pyz, 21 | a.scripts, 22 | [], 23 | exclude_binaries=True, 24 | name='DrawBot', 25 | debug=False, 26 | bootloader_ignore_signals=False, 27 | strip=False, 28 | upx=True, 29 | console=False, 30 | icon='drawbot.ico') 31 | coll = COLLECT(exe, 32 | a.binaries, 33 | a.zipfiles, 34 | a.datas, 35 | strip=False, 36 | upx=True, 37 | upx_exclude=[], 38 | name='DrawBot') 39 | -------------------------------------------------------------------------------- /app.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | MainWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 299 10 | 613 11 | 12 | 13 | 14 | DrawBot 15 | 16 | 17 | 18 | 19 | 20 | 0 21 | 0 22 | 300 23 | 581 24 | 25 | 26 | 27 | 28 | 20 29 | 30 | 31 | 20 32 | 33 | 34 | 20 35 | 36 | 37 | 20 38 | 39 | 40 | 41 | 42 | font-weight:bold; 43 | 44 | 45 | DrawBot par @IV2FI 46 | 47 | 48 | 49 | 50 | 51 | 52 | Qt::Vertical 53 | 54 | 55 | 56 | 20 57 | 40 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | Url de l'image à dessiner 69 | 70 | 71 | 72 | 73 | 74 | 75 | Qt::Vertical 76 | 77 | 78 | 79 | 20 80 | 40 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | Sur quoi vais-je dessiner ? 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | Gartic Phone 100 | 101 | 102 | 103 | 104 | Skribbl 105 | 106 | 107 | 108 | 109 | Paint 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | Qt::Vertical 118 | 119 | 120 | 121 | 20 122 | 40 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | Vitesse 131 | 132 | 133 | 134 | 135 | 136 | 137 | 1 138 | 139 | 140 | 4 141 | 142 | 143 | 3 144 | 145 | 146 | Qt::Horizontal 147 | 148 | 149 | 150 | 151 | 152 | 153 | Qt::Vertical 154 | 155 | 156 | 157 | 20 158 | 40 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | Pixels ignorés 167 | 168 | 169 | 170 | 171 | 172 | 173 | font-size: 10px; 174 | 175 | 176 | Moins on en ignore, plus c'est précis (mais lent) 177 | 178 | 179 | 180 | 181 | 182 | 183 | 1 184 | 185 | 186 | 12 187 | 188 | 189 | 1 190 | 191 | 192 | 5 193 | 194 | 195 | Qt::Horizontal 196 | 197 | 198 | 199 | 200 | 201 | 202 | Qt::Vertical 203 | 204 | 205 | 206 | 20 207 | 40 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | Ignorer pixels isolés 218 | 219 | 220 | 221 | 222 | 223 | 224 | Dither 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | Qt::Vertical 234 | 235 | 236 | 237 | 20 238 | 40 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | Obtenir les coordonnées de la souris (au clic suivant) 247 | 248 | 249 | 250 | 251 | 252 | 253 | Les coordonnées s'afficheront ici 254 | 255 | 256 | 257 | 258 | 259 | 260 | Qt::Vertical 261 | 262 | 263 | 264 | 20 265 | 40 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | Définir la largeur du dessin 274 | 275 | 276 | 277 | 278 | 279 | 280 | Actuellement : Aucun. 281 | 282 | 283 | 284 | 285 | 286 | 287 | Qt::Vertical 288 | 289 | 290 | 291 | 20 292 | 40 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 255 306 | 255 307 | 255 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 0 317 | 134 318 | 22 319 | 320 | 321 | 322 | 323 | 0 324 | 74 325 | 26 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 0 335 | 255 336 | 0 337 | 338 | 339 | 340 | 341 | 342 | 343 | 0 344 | 212 345 | 0 346 | 347 | 348 | 349 | 350 | 351 | 352 | 0 353 | 85 354 | 0 355 | 356 | 357 | 358 | 359 | 360 | 361 | 0 362 | 113 363 | 0 364 | 365 | 366 | 367 | 368 | 369 | 370 | 255 371 | 255 372 | 255 373 | 374 | 375 | 376 | 377 | 378 | 379 | 255 380 | 255 381 | 255 382 | 383 | 384 | 385 | 386 | 387 | 388 | 255 389 | 255 390 | 255 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 0 400 | 134 401 | 22 402 | 403 | 404 | 405 | 406 | 0 407 | 74 408 | 26 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 0 420 | 134 421 | 22 422 | 423 | 424 | 425 | 426 | 0 427 | 74 428 | 26 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 0 438 | 0 439 | 0 440 | 441 | 442 | 443 | 444 | 445 | 446 | 127 447 | 212 448 | 127 449 | 450 | 451 | 452 | 453 | 454 | 455 | 255 456 | 255 457 | 220 458 | 459 | 460 | 461 | 462 | 463 | 464 | 0 465 | 0 466 | 0 467 | 468 | 469 | 470 | 471 | 472 | 473 | 0 474 | 0 475 | 0 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 255 485 | 255 486 | 255 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 0 496 | 134 497 | 22 498 | 499 | 500 | 501 | 502 | 0 503 | 74 504 | 26 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 0 514 | 255 515 | 0 516 | 517 | 518 | 519 | 520 | 521 | 522 | 0 523 | 212 524 | 0 525 | 526 | 527 | 528 | 529 | 530 | 531 | 0 532 | 85 533 | 0 534 | 535 | 536 | 537 | 538 | 539 | 540 | 0 541 | 113 542 | 0 543 | 544 | 545 | 546 | 547 | 548 | 549 | 255 550 | 255 551 | 255 552 | 553 | 554 | 555 | 556 | 557 | 558 | 255 559 | 255 560 | 255 561 | 562 | 563 | 564 | 565 | 566 | 567 | 255 568 | 255 569 | 255 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 0 579 | 134 580 | 22 581 | 582 | 583 | 584 | 585 | 0 586 | 74 587 | 26 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 0 599 | 134 600 | 22 601 | 602 | 603 | 604 | 605 | 0 606 | 74 607 | 26 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 0 617 | 0 618 | 0 619 | 620 | 621 | 622 | 623 | 624 | 625 | 127 626 | 212 627 | 127 628 | 629 | 630 | 631 | 632 | 633 | 634 | 255 635 | 255 636 | 220 637 | 638 | 639 | 640 | 641 | 642 | 643 | 0 644 | 0 645 | 0 646 | 647 | 648 | 649 | 650 | 651 | 652 | 0 653 | 0 654 | 0 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 255 664 | 255 665 | 255 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 0 675 | 134 676 | 22 677 | 678 | 679 | 680 | 681 | 0 682 | 74 683 | 26 684 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 0 693 | 255 694 | 0 695 | 696 | 697 | 698 | 699 | 700 | 701 | 0 702 | 212 703 | 0 704 | 705 | 706 | 707 | 708 | 709 | 710 | 0 711 | 85 712 | 0 713 | 714 | 715 | 716 | 717 | 718 | 719 | 0 720 | 113 721 | 0 722 | 723 | 724 | 725 | 726 | 727 | 728 | 255 729 | 255 730 | 255 731 | 732 | 733 | 734 | 735 | 736 | 737 | 255 738 | 255 739 | 255 740 | 741 | 742 | 743 | 744 | 745 | 746 | 255 747 | 255 748 | 255 749 | 750 | 751 | 752 | 753 | 754 | 755 | 756 | 757 | 0 758 | 134 759 | 22 760 | 761 | 762 | 763 | 764 | 0 765 | 74 766 | 26 767 | 768 | 769 | 770 | 771 | 772 | 773 | 774 | 775 | 776 | 777 | 0 778 | 134 779 | 22 780 | 781 | 782 | 783 | 784 | 0 785 | 74 786 | 26 787 | 788 | 789 | 790 | 791 | 792 | 793 | 794 | 795 | 0 796 | 0 797 | 0 798 | 799 | 800 | 801 | 802 | 803 | 804 | 0 805 | 170 806 | 0 807 | 808 | 809 | 810 | 811 | 812 | 813 | 255 814 | 255 815 | 220 816 | 817 | 818 | 819 | 820 | 821 | 822 | 0 823 | 0 824 | 0 825 | 826 | 827 | 828 | 829 | 830 | 831 | 0 832 | 0 833 | 0 834 | 835 | 836 | 837 | 838 | 839 | 840 | 841 | background-color: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.5, fy:0.5, stop:0 rgba(0, 134, 22, 255), stop:1 rgba(0, 74, 26, 255)); 842 | font-weight: bold; 843 | color: white; 844 | height: 30px; 845 | 846 | 847 | 848 | Dessine ! 849 | 850 | 851 | 852 | 853 | 854 | 855 | Qt::Vertical 856 | 857 | 858 | 859 | 20 860 | 40 861 | 862 | 863 | 864 | 865 | 866 | 867 | 868 | color: rgb(170, 0, 0); 869 | font-weight: bold; 870 | 871 | 872 | 873 | Message d'erreur 874 | 875 | 876 | 877 | 878 | 879 | 880 | 881 | 882 | 883 | 0 884 | 0 885 | 299 886 | 21 887 | 888 | 889 | 890 | 891 | 892 | 893 | 894 | 895 | -------------------------------------------------------------------------------- /colorPalettes/garticColors.txt: -------------------------------------------------------------------------------- 1 | 0 0 0 102 102 102 0 80 205 255 255 255 170 170 170 38 201 255 1 116 32 105 21 6 150 65 18 17 176 60 255 0 19 255 120 41 176 112 28 153 0 78 203 90 87 255 193 38 255 0 143 254 175 168 -------------------------------------------------------------------------------- /colorPalettes/garticCoordinates.txt: -------------------------------------------------------------------------------- 1 | (412,394) (459,387) (507,392) (413,443) (457,442) (504,442) (411,495) (461,497) (506,496) (410,544) (457,543) (505,546) (412,597) (459,599) (509,601) (411,648) (459,648) (507,645) -------------------------------------------------------------------------------- /colorPalettes/paintColors.txt: -------------------------------------------------------------------------------- 1 | 0 0 0 127 127 127 136 0 21 237 28 36 255 127 39 255 242 0 34 177 76 0 162 232 63 72 204 163 73 164 255 255 255 195 195 195 185 122 87 255 174 201 255 201 14 239 228 176 181 230 29 153 217 234 112 146 190 200 191 231 -------------------------------------------------------------------------------- /colorPalettes/paintCoordinates.txt: -------------------------------------------------------------------------------- 1 | (882,60) (901,58) (924,60) (948,61) (966,59) (995,59) (1013,57) (1034,61) (1054,60) (1077,59) (883,85) (902,81) (928,84) (945,83) (968,84) (991,84) (1014,84) (1034,84) (1056,83) (1079,85) -------------------------------------------------------------------------------- /colorPalettes/skribblColors.txt: -------------------------------------------------------------------------------- 1 | 255 255 255 193 193 193 239 19 11 255 113 0 255 228 0 0 204 0 0 178 255 35 31 211 163 0 186 211 124 170 160 82 45 0 0 0 76 76 76 116 11 7 194 56 0 232 162 0 0 85 16 0 86 158 14 8 101 85 0 105 167 85 116 99 48 13 -------------------------------------------------------------------------------- /colorPalettes/skribblCoordinates.txt: -------------------------------------------------------------------------------- 1 | (553,948) (574,947) (602,946) (629,946) (655,946) (683,948) (714,948) (735,946) (759,947) (787,948) (814,946) (552,975) (577,977) (600,973) (631,978) (651,977) (684,974) (707,974) (732,973) (761,973) (785,974) (812,976) -------------------------------------------------------------------------------- /drawbot.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IV2FI/DrawBot/62994ea5e7da2b255d418d4f759f121ac5269000/drawbot.ico -------------------------------------------------------------------------------- /drawbot.py: -------------------------------------------------------------------------------- 1 | from PIL import Image, ImageFilter 2 | from pynput.mouse import Controller, Button 3 | from PIL import Image, ImageFilter, UnidentifiedImageError 4 | import time 5 | import sys 6 | import requests 7 | from io import BytesIO 8 | import math 9 | 10 | mouse = Controller() 11 | 12 | class DrawBot: 13 | def __init__(self, desiredWidth, desiredHeight, startPosition, ignoreSoloPixels, dither, speed, pixelInterval, url, colors, coordinates): 14 | self.colorCoordinates = coordinates 15 | self.colors = colors 16 | self.speed = self.convertSpeed(speed) 17 | self.speedByPixel = self.convertSpeedByPixel(speed) 18 | self.startPosition = startPosition 19 | self.setUpColorPalettes(colors) 20 | self.setUpImageToDraw(url, dither, desiredWidth, desiredHeight) 21 | self.pixelLinesToDraw = self.extractPixelLinesToDraw(pixelInterval, ignoreSoloPixels) 22 | 23 | def setUpImageToDraw(self, url, dither, desiredWidth, desiredHeight): 24 | response = requests.get(url) 25 | self.img = Image.open(BytesIO(response.content)) 26 | fillColor = (255,255,255) 27 | self.img = self.img.convert("RGBA") 28 | if self.img.mode in ('RGBA', 'LA'): 29 | background = Image.new(self.img.mode[:-1], self.img.size, fillColor) 30 | background.paste(self.img, self.img.split()[-1]) 31 | self.img = background 32 | self.img = self.img.convert("RGB").quantize(palette=self.palette, dither=dither) 33 | maxSize = (desiredWidth, desiredHeight) 34 | self.img.thumbnail(maxSize, Image.ANTIALIAS) 35 | self.width, self.height = self.img.size 36 | self.img = self.img.convert("RGB") 37 | 38 | def setUpColorPalettes(self, colors): 39 | paletteColors = colors 40 | for i in range(768-len(colors)): 41 | paletteColors.append(0) 42 | self.palette = Image.new("P", (16, 16)) 43 | self.palette.putpalette(paletteColors) 44 | 45 | def changeColor(self, r, g, b): 46 | found = False 47 | for i in range(0, len(self.colors), 3): 48 | if r == self.colors[i] and g == self.colors[i+1] and b == self.colors[i+2]: 49 | mouse.position = self.colorCoordinates[int(i/3)] 50 | found = True 51 | break 52 | if found: 53 | self.click() 54 | 55 | def extractPixelLinesToDraw(self, pixelInterval, ignoreSoloPixels): 56 | drawVerticallyLines, nbLinesVertical = self.extractLinesToDraw(True, pixelInterval, ignoreSoloPixels) 57 | drawHorizontallyLines, nbLinesHorizontal = self.extractLinesToDraw(False, pixelInterval, ignoreSoloPixels) 58 | if nbLinesHorizontal <= nbLinesVertical: 59 | return drawHorizontallyLines 60 | return drawVerticallyLines 61 | 62 | def extractLinesToDraw(self, vertically, pixelInterval, ignoreSoloPixels): 63 | '''Get the lines to draw vertically or horizontally''' 64 | if not vertically: 65 | bound1 = self.height 66 | bound2 = self.width 67 | else: 68 | bound1 = self.width 69 | bound2 = self.height 70 | lines = {} 71 | nbLinesToDraw = 0 72 | for i in range(0, bound1, pixelInterval): 73 | lineColor = None 74 | for j in range(0, bound2, pixelInterval): 75 | if not vertically: 76 | r, g, b = self.img.getpixel((j, i)) 77 | else: 78 | r, g, b = self.img.getpixel((i, j)) 79 | if not vertically: 80 | currentPosition = (j+self.startPosition[0], i+self.startPosition[1]) 81 | else: 82 | currentPosition = (i+self.startPosition[0], j+self.startPosition[1]) 83 | if lineColor == None: 84 | lineColor = (r, g, b) 85 | lineStart = currentPosition 86 | elif lineColor != (r, g, b): 87 | if lineColor not in lines: 88 | lines[lineColor] = [] 89 | if (ignoreSoloPixels and lineStart != lineEnd) or not ignoreSoloPixels: 90 | lines[lineColor].append([lineStart, lineEnd]) 91 | if lineColor != (255,255,255): 92 | nbLinesToDraw += 1 93 | lineColor = (r, g, b) 94 | lineStart = currentPosition 95 | lineEnd = currentPosition 96 | if lineColor not in lines: 97 | lines[lineColor] = [] 98 | if (ignoreSoloPixels and lineStart != lineEnd) or not ignoreSoloPixels: 99 | lines[lineColor].append([lineStart, lineEnd]) 100 | if lineColor != (255,255,255): 101 | nbLinesToDraw += 1 102 | lineColor = None 103 | return [lines, nbLinesToDraw] 104 | 105 | def draw(self, exit_event): 106 | for key, value in self.pixelLinesToDraw.items(): 107 | if key != (255,255,255) and key != (0,0,0): 108 | self.changeColor(key[0], key[1], key[2]) 109 | for j in value: 110 | if exit_event.is_set(): 111 | break 112 | self.drawLine(j) 113 | if self.speed == 0.1 or self.speed == 0.00001: 114 | time.sleep(0.1) 115 | if (0,0,0) in self.pixelLinesToDraw: 116 | self.changeColor(0, 0, 0) 117 | for j in self.pixelLinesToDraw[(0,0,0)]: 118 | for i in j: 119 | if exit_event.is_set(): 120 | break 121 | self.drawLine(j) 122 | 123 | def drawLine(self, coordinates): 124 | mouse.position = coordinates[0] 125 | mouse.press(Button.left) 126 | mouse.move(abs(coordinates[1][0] - coordinates[0][0]), abs(coordinates[1][1] - coordinates[0][1])) 127 | if (abs(coordinates[1][0] - coordinates[0][0]) > 0 or abs(coordinates[1][1] - coordinates[0][1]) > 0): 128 | time.sleep(self.speed) 129 | else: 130 | time.sleep(self.speedByPixel) 131 | mouse.release(Button.left) 132 | 133 | def convertSpeed(self, speed): 134 | if speed == 1: 135 | return 0.1 136 | if speed == 2: 137 | return 0.00001 138 | if speed == 3: 139 | return 0.000000001 140 | if speed == 4: 141 | return 0.0000000000000001 142 | 143 | def convertSpeedByPixel(self, speed): 144 | if speed == 1: 145 | return 0.00001 146 | if speed == 2: 147 | return 0.000000001 148 | if speed == 3: 149 | return 0.0000000000000001 150 | if speed == 4: 151 | return 0.0000000000000001 152 | 153 | 154 | def click(self): 155 | mouse.press(Button.left) 156 | mouse.release(Button.left) 157 | -------------------------------------------------------------------------------- /utils.py: -------------------------------------------------------------------------------- 1 | from pynput.mouse import Controller, Button, Listener 2 | from pynput import keyboard 3 | from queue import Queue 4 | import os 5 | 6 | mouse = Controller() 7 | queue = Queue() 8 | clicked = 0 9 | start = 0 10 | 11 | def getPalette(app): 12 | if app == 0: 13 | app = "gartic" 14 | elif app == 1: 15 | app = "skribbl" 16 | else: 17 | app = "paint" 18 | coordinatesFile = os.path.dirname(os.path.abspath(__file__)) + "\\colorPalettes\\" + app + "Coordinates.txt" 19 | colorFiles = os.path.dirname(os.path.abspath(__file__)) + "\\colorPalettes\\" + app + "Colors.txt" 20 | coordinates = [tuple(int(i) for i in t.strip('()').split(',')) for t in open(coordinatesFile).read().split()] 21 | colors = [int(t) for t in open(colorFiles).read().split()] 22 | return [colors, coordinates] 23 | 24 | 25 | def getMouseCoordinatesOnce(x, y, button, pressed): 26 | if not pressed: 27 | return False 28 | queue.put((x,y)) 29 | 30 | def getMouseCoordinatesTwice(x, y, button, pressed): 31 | global clicked 32 | global start 33 | if pressed and button == Button.left: 34 | clicked += 1 35 | if clicked == 1 : 36 | start = (x,y) 37 | elif clicked == 2: 38 | clicked = 0 39 | queue.put([start, (x,y)]) 40 | return False 41 | 42 | 43 | def getNextMouseClickPositionCoordinates(): 44 | listener = Listener(on_click=getMouseCoordinatesOnce) 45 | listener.start() 46 | return queue.get() 47 | 48 | def getBounds(): 49 | listener = Listener(on_click=getMouseCoordinatesTwice) 50 | listener.start() 51 | return queue.get() 52 | --------------------------------------------------------------------------------