toto10 commited on
Commit
395def2
·
1 Parent(s): 7e6b1e2

c5e5aafbd355d40c9a6098a76e091f0ce9686827f74aacd3a679fc72967ac606

Browse files
Files changed (50) hide show
  1. Auto-Photoshop-StableDiffusion-Plugin/icon/discard_all.svg +1 -0
  2. Auto-Photoshop-StableDiffusion-Plugin/icon/discard_all_border.png +0 -0
  3. Auto-Photoshop-StableDiffusion-Plugin/icon/discard_selected.png +0 -0
  4. Auto-Photoshop-StableDiffusion-Plugin/icon/discard_selected.svg +1 -0
  5. Auto-Photoshop-StableDiffusion-Plugin/icon/discard_selected_border.png +0 -0
  6. Auto-Photoshop-StableDiffusion-Plugin/icon/ftcopy.svg +153 -0
  7. Auto-Photoshop-StableDiffusion-Plugin/icon/icon_D.png +0 -0
  8. Auto-Photoshop-StableDiffusion-Plugin/icon/icon_N.png +0 -0
  9. Auto-Photoshop-StableDiffusion-Plugin/icon/image-search.svg +15 -0
  10. Auto-Photoshop-StableDiffusion-Plugin/icon/layer_to_selection.svg +8 -0
  11. Auto-Photoshop-StableDiffusion-Plugin/icon/reset_settings.png +0 -0
  12. Auto-Photoshop-StableDiffusion-Plugin/icon/reset_settings2.png +0 -0
  13. Auto-Photoshop-StableDiffusion-Plugin/icon/search.svg +19 -0
  14. Auto-Photoshop-StableDiffusion-Plugin/icon/writing-icon.svg +1 -0
  15. Auto-Photoshop-StableDiffusion-Plugin/index.html +0 -0
  16. Auto-Photoshop-StableDiffusion-Plugin/index.js +0 -0
  17. Auto-Photoshop-StableDiffusion-Plugin/install.py +53 -0
  18. Auto-Photoshop-StableDiffusion-Plugin/jimp/browser/lib/jimp.min.js +0 -0
  19. Auto-Photoshop-StableDiffusion-Plugin/manifest.json +141 -0
  20. Auto-Photoshop-StableDiffusion-Plugin/outpaint.js +518 -0
  21. Auto-Photoshop-StableDiffusion-Plugin/output_image.png +0 -0
  22. Auto-Photoshop-StableDiffusion-Plugin/package-lock.json +0 -0
  23. Auto-Photoshop-StableDiffusion-Plugin/package.json +55 -0
  24. Auto-Photoshop-StableDiffusion-Plugin/psapi.js +1598 -0
  25. Auto-Photoshop-StableDiffusion-Plugin/requirements.txt +26 -0
  26. Auto-Photoshop-StableDiffusion-Plugin/scripts/__pycache__/main.cpython-310.pyc +0 -0
  27. Auto-Photoshop-StableDiffusion-Plugin/scripts/__pycache__/test.cpython-310.pyc +0 -0
  28. Auto-Photoshop-StableDiffusion-Plugin/scripts/main.py +105 -0
  29. Auto-Photoshop-StableDiffusion-Plugin/scripts/test.py +5 -0
  30. Auto-Photoshop-StableDiffusion-Plugin/sdapi_py_re.js +814 -0
  31. Auto-Photoshop-StableDiffusion-Plugin/selection.js +167 -0
  32. Auto-Photoshop-StableDiffusion-Plugin/server/python_server/__pycache__/img2imgapi.cpython-310.pyc +0 -0
  33. Auto-Photoshop-StableDiffusion-Plugin/server/python_server/__pycache__/metadata_to_json.cpython-310.pyc +0 -0
  34. Auto-Photoshop-StableDiffusion-Plugin/server/python_server/__pycache__/prompt_shortcut.cpython-310.pyc +0 -0
  35. Auto-Photoshop-StableDiffusion-Plugin/server/python_server/__pycache__/search.cpython-310.pyc +0 -0
  36. Auto-Photoshop-StableDiffusion-Plugin/server/python_server/__pycache__/serverHelper.cpython-310.pyc +0 -0
  37. Auto-Photoshop-StableDiffusion-Plugin/server/python_server/__pycache__/serverMain.cpython-310.pyc +0 -0
  38. Auto-Photoshop-StableDiffusion-Plugin/server/python_server/control_net.py +65 -0
  39. Auto-Photoshop-StableDiffusion-Plugin/server/python_server/img2imgapi.py +163 -0
  40. Auto-Photoshop-StableDiffusion-Plugin/server/python_server/init_images/.gitignore +4 -0
  41. Auto-Photoshop-StableDiffusion-Plugin/server/python_server/metadata_to_json.py +78 -0
  42. Auto-Photoshop-StableDiffusion-Plugin/server/python_server/output/.gitignore +4 -0
  43. Auto-Photoshop-StableDiffusion-Plugin/server/python_server/prompt_shortcut - Copy.json +12 -0
  44. Auto-Photoshop-StableDiffusion-Plugin/server/python_server/prompt_shortcut.py +61 -0
  45. Auto-Photoshop-StableDiffusion-Plugin/server/python_server/search.py +24 -0
  46. Auto-Photoshop-StableDiffusion-Plugin/server/python_server/serverHelper.py +64 -0
  47. Auto-Photoshop-StableDiffusion-Plugin/server/python_server/serverMain.py +495 -0
  48. Auto-Photoshop-StableDiffusion-Plugin/start_server.bat +51 -0
  49. Auto-Photoshop-StableDiffusion-Plugin/start_server.sh +36 -0
  50. Auto-Photoshop-StableDiffusion-Plugin/start_server_MacOS.sh +17 -0
Auto-Photoshop-StableDiffusion-Plugin/icon/discard_all.svg ADDED
Auto-Photoshop-StableDiffusion-Plugin/icon/discard_all_border.png ADDED
Auto-Photoshop-StableDiffusion-Plugin/icon/discard_selected.png ADDED
Auto-Photoshop-StableDiffusion-Plugin/icon/discard_selected.svg ADDED
Auto-Photoshop-StableDiffusion-Plugin/icon/discard_selected_border.png ADDED
Auto-Photoshop-StableDiffusion-Plugin/icon/ftcopy.svg ADDED
Auto-Photoshop-StableDiffusion-Plugin/icon/icon_D.png ADDED
Auto-Photoshop-StableDiffusion-Plugin/icon/icon_N.png ADDED
Auto-Photoshop-StableDiffusion-Plugin/icon/image-search.svg ADDED
Auto-Photoshop-StableDiffusion-Plugin/icon/layer_to_selection.svg ADDED
Auto-Photoshop-StableDiffusion-Plugin/icon/reset_settings.png ADDED
Auto-Photoshop-StableDiffusion-Plugin/icon/reset_settings2.png ADDED
Auto-Photoshop-StableDiffusion-Plugin/icon/search.svg ADDED
Auto-Photoshop-StableDiffusion-Plugin/icon/writing-icon.svg ADDED
Auto-Photoshop-StableDiffusion-Plugin/index.html ADDED
The diff for this file is too large to render. See raw diff
 
Auto-Photoshop-StableDiffusion-Plugin/index.js ADDED
The diff for this file is too large to render. See raw diff
 
Auto-Photoshop-StableDiffusion-Plugin/install.py ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from pathlib import Path
3
+ from launch import git, run
4
+ import launch
5
+ import sys
6
+
7
+ # launch.run(f'git pull', f"updating auto-photoshop plugin",
8
+ # f"Couldn't update auto-photoshop plugin")
9
+
10
+
11
+ REPO_LOCATION = Path(__file__).parent
12
+ # auto_update = os.environ.get("AUTO_UPDATE", "True").lower() in {"true", "yes"}
13
+ auto_update = True
14
+ extension_branch = "master"
15
+ # extension_branch = "horde_native"
16
+ # extension_branch = "auto_extension_ccx_1_1_7"
17
+
18
+ if auto_update:
19
+ print("[Auto-Photoshop-SD] Attempting auto-update...")
20
+
21
+ try:
22
+
23
+ checkout_result = run(f'"{git}" -C "{REPO_LOCATION}" checkout {extension_branch}', "[Auto-Photoshop-SD] switch branch to extension branch.")
24
+ print("checkout_result:",checkout_result)
25
+
26
+ branch_result = run(f'"{git}" -C "{REPO_LOCATION}" branch', "[Auto-Photoshop-SD] Current Branch.")
27
+ print("branch_result:",branch_result)
28
+
29
+ fetch_result = run(f'"{git}" -C "{REPO_LOCATION}" fetch', "[Auto-Photoshop-SD] Fetch upstream.")
30
+ print("fetch_result:",fetch_result)
31
+
32
+ pull_result = run(f'"{git}" -C "{REPO_LOCATION}" pull', "[Auto-Photoshop-SD] Pull upstream.")
33
+ print("pull_result:",pull_result)
34
+
35
+ except Exception as e:
36
+ print("[Auto-Photoshop-SD] Auto-update failed:")
37
+ print(e)
38
+ print("[Auto-Photoshop-SD] Ensure git was used to install extension.")
39
+
40
+
41
+ # print("Auto-Photoshop-SD plugin is installing")
42
+
43
+ package_name = 'duckduckgo_search'
44
+ package_version= '3.7.1'
45
+ if not launch.is_installed(package_name):
46
+ launch.run_pip(f"install {package_name}=={package_version}", "requirements for Auto-Photoshop Image Search")
47
+ else:# it's installed but we need to check for update
48
+ import pkg_resources
49
+
50
+ version = pkg_resources.get_distribution(package_name).version
51
+ if(version != package_version):
52
+ print(f'{package_name} version: {version} will update to version: {package_version}')
53
+ launch.run_pip(f"install {package_name}=={package_version}", "update requirements for Auto-Photoshop Image Search")
Auto-Photoshop-StableDiffusion-Plugin/jimp/browser/lib/jimp.min.js ADDED
The diff for this file is too large to render. See raw diff
 
Auto-Photoshop-StableDiffusion-Plugin/manifest.json ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "id": "auto.photoshop.stable.diffusion.plugin",
3
+ "name": "Auto Photoshop Stable Diffusion Plugin",
4
+ "version": "1.1.0",
5
+ "host": [
6
+ {
7
+ "app": "PS",
8
+ "minVersion": "24.0.0"
9
+ }
10
+ ],
11
+ "main": "index.html",
12
+ "manifestVersion": 5,
13
+ "requiredPermissions": {
14
+ "network": {
15
+ "domains": "all"
16
+ },
17
+ "launchProcess": {
18
+ "schemes": [
19
+ "http",
20
+ "https",
21
+ "mailto"
22
+ ],
23
+ "extensions": [
24
+ ".png",
25
+ ".jpg",
26
+ ".pdf",
27
+ ""
28
+ ]
29
+ },
30
+ "clipboard": "readAndWrite",
31
+ "localFileSystem": "request",
32
+ "ipc": {
33
+ "enablePluginCommunication": true
34
+ }
35
+ },
36
+ "entrypoints": [
37
+ {
38
+ "type": "panel",
39
+ "id": "vanilla",
40
+ "label": {
41
+ "default": "Auto-Photoshop-SD",
42
+ "en-US": "Auto-Photoshop-SD",
43
+ "es-ES": "Auto-Photoshop-SD"
44
+ },
45
+ "minimumSize": {
46
+ "width": 400,
47
+ "height": 800
48
+ },
49
+ "maximumSize": {
50
+ "width": 1200,
51
+ "height": 10000
52
+ },
53
+ "preferredDockedSize": {
54
+ "width": 150,
55
+ "height": 800
56
+ },
57
+ "preferredFloatingSize": {
58
+ "width": 300,
59
+ "height": 800
60
+ },
61
+ "commands": [
62
+ {
63
+ "id": "show_alert",
64
+ "label": {
65
+ "default": "Show Alert",
66
+ "en-US": "Show Alert (US)",
67
+ "es-ES": "Show Alert (ES)"
68
+ }
69
+ }
70
+ ],
71
+ "icons": [
72
+ {
73
+ "width": 32,
74
+ "height": 32,
75
+ "path": "icon/icon_D.png",
76
+ "scale": [
77
+ 1,
78
+ 2
79
+ ],
80
+ "theme": [
81
+ "dark",
82
+ "darkest"
83
+ ],
84
+ "species": [
85
+ "generic"
86
+ ]
87
+ },
88
+ {
89
+ "width": 32,
90
+ "height": 32,
91
+ "path": "icon/icon_N.png",
92
+ "scale": [
93
+ 1,
94
+ 2
95
+ ],
96
+ "theme": [
97
+ "lightest",
98
+ "light"
99
+ ],
100
+ "species": [
101
+ "generic"
102
+ ]
103
+ }
104
+ ]
105
+ }
106
+ ],
107
+ "icons": [
108
+ {
109
+ "width": 32,
110
+ "height": 32,
111
+ "path": "icon/icon_D.png",
112
+ "scale": [
113
+ 1,
114
+ 2
115
+ ],
116
+ "theme": [
117
+ "dark",
118
+ "darkest"
119
+ ],
120
+ "species": [
121
+ "generic"
122
+ ]
123
+ },
124
+ {
125
+ "width": 32,
126
+ "height": 32,
127
+ "path": "icon/icon_N.png",
128
+ "scale": [
129
+ 1,
130
+ 2
131
+ ],
132
+ "theme": [
133
+ "lightest",
134
+ "light"
135
+ ],
136
+ "species": [
137
+ "generic"
138
+ ]
139
+ }
140
+ ]
141
+ }
Auto-Photoshop-StableDiffusion-Plugin/outpaint.js ADDED
@@ -0,0 +1,518 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const app = window.require('photoshop').app
2
+
3
+ const batchPlay = require('photoshop').action.batchPlay
4
+ const psapi = require('./psapi')
5
+
6
+ async function moveLayersToGroup(group_id) {
7
+ const activeLayers = await app.activeDocument.activeLayers
8
+ const layerIDs = activeLayers.map((layer) => layer.id)
9
+ const { executeAsModal } = require('photoshop').core
10
+ await executeAsModal(async () => {
11
+ await psapi.moveToGroupCommand(group_id, layerIDs)
12
+ })
13
+ }
14
+
15
+ async function createSnapshot() {
16
+ const { executeAsModal } = require('photoshop').core
17
+ //get all layers,
18
+ //duplicate the layers
19
+ //create a group
20
+ //move the duplicate layers to the group
21
+ let snapshotLayer, snapshotGroup
22
+ try {
23
+ const selectionInfo = await psapi.getSelectionInfoExe()
24
+ await psapi.unSelectMarqueeExe()
25
+
26
+ //get all layers
27
+ const allLayers = await app.activeDocument.layers
28
+
29
+ // const allLayerNames = allLayers.map(
30
+ // layer => `${layer.name} (${layer.opacity} %)`
31
+ // )
32
+ // for (layer of allLayerNames){
33
+ // console.log(layer)
34
+ // }
35
+ //duplicate the layers
36
+ let duplicatedLayers = []
37
+
38
+ // const group_id = await createGroup()
39
+ const groupLayer = await psapi.createEmptyGroup()
40
+
41
+ console.log('createSnapshot(), group_id:', groupLayer.id)
42
+ // let bHasBackground = false
43
+ let indexOffset = 0
44
+
45
+ const result1 = await executeAsModal(async () => {
46
+ for (layer of allLayers) {
47
+ if (layer.id == 1) {
48
+ //skip the background layer
49
+ // bHasBackground = true
50
+ indexOffset = 1
51
+ continue
52
+ }
53
+ if (layer.visible) {
54
+ const copyLayer = await layer.duplicate()
55
+ duplicatedLayers.push(copyLayer)
56
+ }
57
+ }
58
+
59
+ const layerIDs = duplicatedLayers.map((layer) => layer.id)
60
+ console.log('createSnapshot, layerIDs:', layerIDs)
61
+
62
+ //select the layer since layerIDs don't seem to have an affect on moveToGroupCommand(), don't know why!!!!
63
+ psapi.selectLayers(duplicatedLayers)
64
+ let group_index = await psapi.getLayerIndex(groupLayer.id)
65
+
66
+ await psapi.moveToGroupCommand(group_index - indexOffset, layerIDs)
67
+
68
+ await psapi.collapseGroup(duplicatedLayers[0])
69
+ snapshotLayer = app.activeDocument.activeLayers[0]
70
+ await psapi.createSolidLayer(255, 255, 255)
71
+ const whiteSolidLayer = app.activeDocument.activeLayers[0]
72
+ await snapshotLayer.moveAbove(whiteSolidLayer)
73
+ snapshotGroup = await psapi.createEmptyGroup()
74
+ let snapshot_group_index = await psapi.getLayerIndex(
75
+ snapshotGroup.id
76
+ )
77
+
78
+ await psapi.selectLayers([snapshotLayer, whiteSolidLayer])
79
+ await psapi.moveToGroupCommand(
80
+ snapshot_group_index - indexOffset,
81
+ []
82
+ )
83
+ await psapi.selectLayers([snapshotGroup])
84
+ await psapi.reSelectMarqueeExe(selectionInfo)
85
+ await psapi.createMaskExe()
86
+ // await psapi.selectLayerChannelCommand()
87
+ // await psapi.createSolidLayer(0, 0, 0)
88
+ })
89
+
90
+ return [snapshotLayer, snapshotGroup]
91
+ } catch (e) {
92
+ console.warn('createSnapshot Error:', e)
93
+ }
94
+ }
95
+
96
+ function executeCommand(batchPlayCommandFunc) {
97
+ const { executeAsModal } = require('photoshop').core
98
+ try {
99
+ executeAsModal(async () => {
100
+ await batchPlayCommandFunc()
101
+ })
102
+ } catch (e) {
103
+ console.warn('executeCommand error:', e)
104
+ }
105
+ }
106
+
107
+ async function snapAndFillExe(session_id) {
108
+ //create a snapshot of canvas
109
+ //select opaque pixel and create black fill layer
110
+ //create a snapshot of mask
111
+ //set initial image
112
+ //set mask image
113
+
114
+ try {
115
+ let snapAndFillLayers = []
116
+ await executeAsModal(async (context) => {
117
+ const history_id = await context.hostControl.suspendHistory({
118
+ documentID: app.activeDocument.id, //TODO: change this to the session document id
119
+ name: 'Img2Img layers',
120
+ })
121
+ const selectionInfo = await psapi.getSelectionInfoExe()
122
+ // await psapi.unSelectMarqueeExe()
123
+
124
+ //create a snapshot of canvas
125
+ // let [snapshotLayer,snapshotGroup] = await createSnapshot()
126
+ await psapi.snapshot_layerExe()
127
+ const snapshotLayer = await app.activeDocument.activeLayers[0]
128
+ const snapshotGroup = await psapi.createEmptyGroup()
129
+ snapshotLayer.name = 'Init Image Snapshot -- temporary'
130
+ snapshotGroup.name = 'Init Image Group -- temporary'
131
+
132
+ // snapshotGroup.name = `${snapshotGroup.name}_init_image`
133
+ await psapi.createSolidLayer(255, 255, 255)
134
+ const whiteSolidLayer = await app.activeDocument.activeLayers[0]
135
+ whiteSolidLayer.name = 'Background Color -- temporary'
136
+ snapshotLayer.moveAbove(whiteSolidLayer)
137
+ console.log('[snapshotLayer,snapshotGroup]:', [
138
+ snapshotLayer,
139
+ snapshotGroup,
140
+ ])
141
+
142
+ //create a snapshot of mask
143
+ await psapi.reSelectMarqueeExe(selectionInfo)
144
+ // let [snapshotMaskLayer,snapshotMaskGroup] = await createSnapshot()
145
+
146
+ await psapi.selectLayers([snapshotGroup])
147
+ await psapi.reSelectMarqueeExe(selectionInfo)
148
+ await psapi.createClippingMaskExe()
149
+
150
+ await psapi.selectLayers([snapshotGroup])
151
+
152
+ snapAndFillLayers = [snapshotLayer, snapshotGroup, whiteSolidLayer]
153
+
154
+ // g_init_image_related_layers['init_image_group'] = snapshotGroup
155
+ // g_init_image_related_layers['init_image_layer'] = snapshotLayer
156
+ // g_init_image_related_layers['solid_white'] = whiteSolidLayer
157
+
158
+ const image_info = await psapi.silentSetInitImage(
159
+ snapshotGroup,
160
+ session_id
161
+ )
162
+ const image_name = image_info['name']
163
+ const path = `./server/python_server/init_images/${image_name}`
164
+
165
+ g_viewer_manager.initializeInitImage(
166
+ snapshotGroup,
167
+ snapshotLayer,
168
+ whiteSolidLayer,
169
+ path
170
+ ) //this will be called once a session and will add the first init image to th viewer manager
171
+
172
+ for (layer of snapAndFillLayers) {
173
+ layer.visible = false
174
+ }
175
+ await psapi.reSelectMarqueeExe(selectionInfo)
176
+ const layer_util = require('./utility/layer')
177
+ await layer_util.collapseFolderExe([snapshotGroup], false)
178
+ await context.hostControl.resumeHistory(history_id)
179
+ })
180
+ console.log('snapAndFillLayers: ', snapAndFillLayers)
181
+ return snapAndFillLayers
182
+ } catch (e) {
183
+ console.error(`snapAndFill error: ${e}`)
184
+ }
185
+ return []
186
+ }
187
+
188
+ async function addClippingMaskToLayer(layer, selectionInfo) {
189
+ await psapi.selectLayers([layer]) //select the layer
190
+ await psapi.reSelectMarqueeExe(selectionInfo) //reselect the selection
191
+ await psapi.createClippingMaskExe() //this will create an cliping mask and select the mask of the layer
192
+ await psapi.selectLayers([layer]) //reselect the layer instead of the mask
193
+ await psapi.reSelectMarqueeExe(selectionInfo) //reselect the selection
194
+
195
+ ////test addClippingMaskToLayer
196
+ // await executeAsModal(
197
+ // async ()=>{
198
+ // await outpaint.addClippingMaskToLayer(await app.activeDocument.activeLayers[0],await psapi.getSelectionInfoExe()
199
+ // )})
200
+ }
201
+
202
+ async function outpaintExe(session_id) {
203
+ //create a snapshot of canvas
204
+ //select opaque pixel and create black fill layer
205
+ //create a snapshot of mask
206
+ //set initial image
207
+ //set mask image
208
+
209
+ try {
210
+ let outpaintLayers = []
211
+ await executeAsModal(async (context) => {
212
+ const history_id = await context.hostControl.suspendHistory({
213
+ documentID: app.activeDocument.id, //TODO: change this to the session document id
214
+ name: 'Outpaint Mask Related layers',
215
+ })
216
+ const selectionInfo = await psapi.getSelectionInfoExe()
217
+ // await psapi.unSelectMarqueeExe()
218
+
219
+ //create a snapshot of canvas
220
+ // let [snapshotLayer,snapshotGroup] = await createSnapshot()
221
+ await psapi.snapshot_layerExe()
222
+ const snapshotLayer = await app.activeDocument.activeLayers[0]
223
+ snapshotLayer.name = 'Init Image Snapshot -- temporary'
224
+ const snapshotGroup = await psapi.createEmptyGroup()
225
+ // snapshotGroup.name = `${snapshotGroup.name}_init_image`
226
+ snapshotGroup.name = 'Init Image Group -- temporary'
227
+ await psapi.createSolidLayer(255, 255, 255) //solid white inside the Init Image Group
228
+ const whiteSolidLayer = await app.activeDocument.activeLayers[0]
229
+ whiteSolidLayer.name = 'Background Color -- temporary'
230
+ snapshotLayer.moveAbove(whiteSolidLayer) //move the snapshot layer to be the first layer in "Init Image Group"
231
+ console.log('[snapshotLayer,snapshotGroup]:', [
232
+ snapshotLayer,
233
+ snapshotGroup,
234
+ ])
235
+
236
+ //select opaque pixel and create black fill layer
237
+ await psapi.selectLayers([snapshotLayer])
238
+ await psapi.selectLayerChannelCommand()
239
+ const snapshotMaskGroup = await psapi.createEmptyGroup()
240
+
241
+ await psapi.createSolidLayer(0, 0, 0)
242
+ let solid_black_layer = app.activeDocument.activeLayers[0]
243
+ //create a snapshot of mask
244
+ await psapi.reSelectMarqueeExe(selectionInfo)
245
+ // let [snapshotMaskLayer,snapshotMaskGroup] = await createSnapshot()
246
+ await psapi.snapshot_layerExe()
247
+ const snapshotMaskLayer = await app.activeDocument.activeLayers[0]
248
+ snapshotMaskLayer.name = 'Mask -- Paint White to Mask -- temporary'
249
+ // const snapshotMaskGroup = await psapi.createEmptyGroup()
250
+
251
+ // snapshotMaskGroup.name = `${snapshotMaskGroup.name}_mask`
252
+ snapshotMaskGroup.name = 'Mask Group -- temporary'
253
+ snapshotMaskLayer.moveBelow(solid_black_layer)
254
+ await snapshotMaskGroup.moveAbove(snapshotGroup)
255
+ await solid_black_layer.delete() //
256
+
257
+ await addClippingMaskToLayer(snapshotGroup, selectionInfo)
258
+
259
+ const mask_info = await psapi.silentSetInitImageMask(
260
+ snapshotMaskGroup,
261
+ session_id
262
+ )
263
+ snapshotMaskGroup.visible = false
264
+
265
+ const image_info = await psapi.silentSetInitImage(
266
+ snapshotGroup,
267
+ session_id
268
+ )
269
+ snapshotGroup.visible = false
270
+
271
+ const init_image_name = image_info['name']
272
+ const init_path = `./server/python_server/init_images/${init_image_name}`
273
+
274
+ await psapi.reSelectMarqueeExe(selectionInfo)
275
+
276
+ await addClippingMaskToLayer(snapshotMaskGroup, selectionInfo)
277
+
278
+ await psapi.reSelectMarqueeExe(selectionInfo)
279
+
280
+ // await psapi.silentSetInitImageMask(snapshotMaskGroup,session_id)
281
+
282
+ const mask_name = mask_info['name']
283
+ const mask_path = `./server/python_server/init_images/${mask_name}`
284
+ await psapi.reSelectMarqueeExe(selectionInfo)
285
+ //set initial image
286
+ //set mask image
287
+ outpaintLayers = [
288
+ snapshotMaskGroup,
289
+ snapshotMaskLayer,
290
+ snapshotLayer,
291
+ snapshotGroup,
292
+ whiteSolidLayer,
293
+ ]
294
+ // g_mask_related_layers['mask_group'] = snapshotMaskGroup
295
+ // g_mask_related_layers['white_mark'] = snapshotMaskLayer
296
+ // // g_mask_related_layers['solid_black'] = blackSolidLayer
297
+ g_viewer_manager.initializeMask(
298
+ snapshotMaskGroup,
299
+ snapshotMaskLayer,
300
+ null,
301
+ mask_path,
302
+ mask_info['base64']
303
+ )
304
+ // g_init_image_related_layers['init_image_group'] = snapshotGroup
305
+ // g_init_image_related_layers['init_image_layer'] = snapshotLayer
306
+ // g_init_image_related_layers['solid_white'] = whiteSolidLayer
307
+ g_viewer_manager.initializeInitImage(
308
+ snapshotGroup,
309
+ snapshotLayer,
310
+ whiteSolidLayer,
311
+ init_path
312
+ ) //this will be called once a session and will add the first init image to th viewer manager
313
+
314
+ for (layer of outpaintLayers) {
315
+ layer.visible = false
316
+ }
317
+
318
+ //collapse the folders
319
+ const layer_util = require('./utility/layer')
320
+ await layer_util.collapseFolderExe(
321
+ [snapshotGroup, snapshotMaskGroup],
322
+ false
323
+ )
324
+ await context.hostControl.resumeHistory(history_id)
325
+ })
326
+ console.log('outpaintLayers 2: ', outpaintLayers)
327
+ return outpaintLayers
328
+ } catch (e) {
329
+ console.error(`outpaintExe error: ${e}`)
330
+ }
331
+ return []
332
+ }
333
+
334
+ async function inpaintFasterExe(session_id) {
335
+ //
336
+ //create a snapshot of canvas
337
+ //select opaque pixel and create black fill layer
338
+ //create a snapshot of mask
339
+ //set initial image
340
+ //set mask image
341
+ try {
342
+ let inpaintLayers = []
343
+ await executeAsModal(async (context) => {
344
+ const history_id = await context.hostControl.suspendHistory({
345
+ documentID: app.activeDocument.id,
346
+ name: 'Inpaint Mask Related layers',
347
+ })
348
+ const original_white_mark_layer = await app.activeDocument
349
+ .activeLayers[0]
350
+ original_white_mark_layer.visible = false
351
+
352
+ const selectionInfo = await psapi.getSelectionInfoExe()
353
+
354
+ //duplicate the current active layer and use it as the white mark layer
355
+ const white_mark_layer =
356
+ await app.activeDocument.activeLayers[0].duplicate()
357
+ white_mark_layer.visible = true
358
+ const mask_layer_opacity = await white_mark_layer.opacity
359
+ white_mark_layer.opacity = 100 //make sure the opacity is full
360
+ await psapi.selectLayers([white_mark_layer])
361
+ await psapi.reSelectMarqueeExe(selectionInfo)
362
+ await psapi.createClippingMaskExe()
363
+ await psapi.reSelectMarqueeExe(selectionInfo)
364
+
365
+ white_mark_layer.visible = false
366
+ white_mark_layer.name = 'Mask -- Paint White to Mask -- temporary'
367
+ // white_mark_layer.visible = true
368
+
369
+ //create a snapshot of canvas
370
+
371
+ // let [snapshotLayer,snapshotGroup] = await createSnapshot()
372
+ // await psapi.snapshot_layer()
373
+ await psapi.unselectActiveLayersExe() //invisible layer will cause problem with merging "command is not available" type of error
374
+ // await psapi.mergeVisibleExe()
375
+ await psapi.snapshot_layerExe()
376
+
377
+ const snapshotLayer = await app.activeDocument.activeLayers[0]
378
+ snapshotLayer.name = 'Init Image Snapshot -- temporary'
379
+ const snapshotGroup = await psapi.createEmptyGroup()
380
+ snapshotGroup.name = 'Init Image Group -- temporary'
381
+ await psapi.createSolidLayer(255, 255, 255)
382
+ const whiteSolidLayer = await app.activeDocument.activeLayers[0]
383
+ whiteSolidLayer.name = 'Background Color -- temporary'
384
+ await snapshotLayer.moveAbove(whiteSolidLayer)
385
+
386
+ await psapi.selectLayers([snapshotGroup])
387
+ await psapi.reSelectMarqueeExe(selectionInfo)
388
+ await psapi.createClippingMaskExe()
389
+ await psapi.reSelectMarqueeExe(selectionInfo)
390
+
391
+ const maskGroup = await psapi.createEmptyGroup()
392
+ // maskGroup.name = `${maskGroup.name}_mask`
393
+
394
+ maskGroup.name = 'Mask Group -- temporary'
395
+
396
+ await psapi.createSolidLayer(0, 0, 0)
397
+ const blackSolidLayer = await app.activeDocument.activeLayers[0]
398
+ blackSolidLayer.name = "Don't Edit -- temporary"
399
+ // snapshotLayer.moveAbove(blackSolidLayer)
400
+ white_mark_layer.moveAbove(blackSolidLayer)
401
+ white_mark_layer.visible = true
402
+ await psapi.reSelectMarqueeExe(selectionInfo)
403
+
404
+ console.log('[snapshotLayer,maskGroup]:', [
405
+ snapshotLayer,
406
+ maskGroup,
407
+ ])
408
+ // //select opaque pixel and create black fill layer
409
+ // await psapi.selectLayers([snapshotLayer])
410
+ // await psapi.selectLayerChannelCommand()
411
+ // const snapshotMaskGroup = await psapi.createEmptyGroup()
412
+
413
+ // await psapi.createSolidLayer(0, 0, 0)
414
+ // let solid_black_layer = app.activeDocument.activeLayers[0]
415
+ // //create a snapshot of mask
416
+ // await psapi.reSelectMarqueeExe(selectionInfo)
417
+ // // let [snapshotMaskLayer,snapshotMaskGroup] = await createSnapshot()
418
+ // await psapi.snapshot_layer()
419
+ // const snapshotMaskLayer = await app.activeDocument.activeLayers[0]
420
+ // // const snapshotMaskGroup = await psapi.createEmptyGroup()
421
+
422
+ // snapshotMaskGroup.name = `${snapshotMaskGroup.name}_mask`
423
+ // snapshotMaskLayer.moveBelow(solid_black_layer)
424
+ // await snapshotMaskGroup.moveAbove(snapshotGroup)
425
+ // solid_black_layer.delete()
426
+
427
+ await psapi.selectLayers([maskGroup])
428
+ await psapi.reSelectMarqueeExe(selectionInfo)
429
+ await psapi.createClippingMaskExe()
430
+ await psapi.reSelectMarqueeExe(selectionInfo)
431
+
432
+ // await psapi.selectLayers([snapshotGroup])
433
+
434
+ await psapi.selectLayers([maskGroup])
435
+ // await psapi.silentSetInitImageMask(maskGroup,session_id)
436
+ const mask_info = await psapi.silentSetInitImageMask(
437
+ maskGroup,
438
+ session_id
439
+ )
440
+ maskGroup.visible = false
441
+ //hide the mask so you can take screenshot of the init image
442
+ const mask_name = mask_info['name']
443
+ const mask_path = `./server/python_server/init_images/${mask_name}`
444
+
445
+ await psapi.reSelectMarqueeExe(selectionInfo)
446
+ await psapi.selectLayers([snapshotGroup])
447
+
448
+ const image_info = await psapi.silentSetInitImage(
449
+ snapshotGroup,
450
+ session_id
451
+ )
452
+ const image_name = image_info['name']
453
+ const path = `./server/python_server/init_images/${image_name}`
454
+
455
+ await psapi.reSelectMarqueeExe(selectionInfo)
456
+ // await psapi.selectLayers([snapshotMaskGroup])
457
+ // await psapi.setInitImageMask(snapshotMaskGroup)
458
+ // //set initial image
459
+ // //set mask image
460
+
461
+ await psapi.selectLayers([maskGroup])
462
+ inpaintLayers = [
463
+ maskGroup,
464
+ white_mark_layer,
465
+ blackSolidLayer,
466
+ snapshotGroup,
467
+ snapshotLayer,
468
+ whiteSolidLayer,
469
+ ]
470
+ // g_mask_related_layers['mask_group'] = maskGroup
471
+ // g_mask_related_layers['white_mark'] = white_mark_layer
472
+ // g_mask_related_layers['solid_black'] = blackSolidLayer
473
+ g_viewer_manager.initializeMask(
474
+ maskGroup,
475
+ white_mark_layer,
476
+ blackSolidLayer,
477
+ mask_path,
478
+ mask_info['bases64']
479
+ )
480
+ // g_init_image_related_layers['init_image_group'] = snapshotGroup
481
+ // g_init_image_related_layers['init_image_layer'] = snapshotLayer
482
+ // g_init_image_related_layers['solid_white'] = whiteSolidLayer
483
+ g_viewer_manager.initializeInitImage(
484
+ snapshotGroup,
485
+ snapshotLayer,
486
+ whiteSolidLayer,
487
+ path
488
+ ) //this will be called once a session and will add the first init image to th viewer manager
489
+ for (layer of inpaintLayers) {
490
+ layer.visible = false
491
+ }
492
+ const layer_util = require('./utility/layer')
493
+
494
+ await layer_util.collapseFolderExe(
495
+ [snapshotGroup, maskGroup],
496
+ false
497
+ )
498
+ white_mark_layer.opacity = mask_layer_opacity // restore the opacity
499
+ // original_white_mark_layer.visible = true// leave it off so we can toggle using the viewer manager
500
+ await context.hostControl.resumeHistory(history_id)
501
+ })
502
+ return inpaintLayers
503
+ } catch (e) {
504
+ console.warn('inpaintFasterExe error:', e)
505
+ }
506
+ return []
507
+ }
508
+ module.exports = {
509
+ createSnapshot,
510
+
511
+ moveLayersToGroup,
512
+ executeCommand,
513
+ outpaintExe,
514
+ // outpaintFasterExe,
515
+ inpaintFasterExe,
516
+ snapAndFillExe,
517
+ addClippingMaskToLayer,
518
+ }
Auto-Photoshop-StableDiffusion-Plugin/output_image.png ADDED
Auto-Photoshop-StableDiffusion-Plugin/package-lock.json ADDED
The diff for this file is too large to render. See raw diff
 
Auto-Photoshop-StableDiffusion-Plugin/package.json ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "uxp-template-default-starter",
3
+ "version": "1.0.0",
4
+ "description": "Default template for creating Adobe UXP based photoshop plugin.",
5
+ "author": "Adobe Inc",
6
+ "license": "Apache-2.0",
7
+ "dependencies": {
8
+ "@types/react": "^18.2.6",
9
+ "@types/react-dom": "^18.2.4",
10
+ "fastify": "^4.10.2",
11
+ "jimp": "^0.16.2",
12
+ "md5": "^2.3.0",
13
+ "mobx": "^6.9.0",
14
+ "mobx-react": "^7.6.0",
15
+ "react": "^18.2.0",
16
+ "react-dom": "^18.2.0"
17
+ },
18
+ "main": "index.js",
19
+ "directories": {
20
+ "test": "test"
21
+ },
22
+ "devDependencies": {
23
+ "@babel/core": "^7.21.8",
24
+ "@babel/plugin-proposal-object-rest-spread": "^7.20.7",
25
+ "@babel/plugin-syntax-class-properties": "^7.12.13",
26
+ "@babel/plugin-transform-react-jsx": "^7.21.5",
27
+ "babel-loader": "^9.1.2",
28
+ "clean-webpack-plugin": "^4.0.0",
29
+ "copy-webpack-plugin": "^11.0.0",
30
+ "css-loader": "^6.7.3",
31
+ "file-loader": "^6.2.0",
32
+ "nodemon": "^2.0.22",
33
+ "prettier": "2.8.3",
34
+ "style-loader": "^3.3.2",
35
+ "terser-webpack-plugin": "^3.0.8",
36
+ "ts-loader": "^9.4.2",
37
+ "typescript": "^5.0.4",
38
+ "webpack": "^5.82.1",
39
+ "webpack-cli": "^5.1.1"
40
+ },
41
+ "scripts": {
42
+ "test": "echo \"Error: no test specified\" && exit 1",
43
+ "build": "cd ultimate_sd_upscaler && npx webpack --config webpack.config.js",
44
+ "watch": "cd ultimate_sd_upscaler && npx webpack --config webpack.config.js --watch"
45
+ },
46
+ "repository": {
47
+ "type": "git",
48
+ "url": "git+https://github.com/AbdullahAlfaraj/Auto-Photoshop-StableDiffusion-Plugin.git"
49
+ },
50
+ "keywords": [],
51
+ "bugs": {
52
+ "url": "https://github.com/AbdullahAlfaraj/Auto-Photoshop-StableDiffusion-Plugin/issues"
53
+ },
54
+ "homepage": "https://github.com/AbdullahAlfaraj/Auto-Photoshop-StableDiffusion-Plugin#readme"
55
+ }
Auto-Photoshop-StableDiffusion-Plugin/psapi.js ADDED
@@ -0,0 +1,1598 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const app = window.require('photoshop').app
2
+ const batchPlay = require('photoshop').action.batchPlay
3
+ const { executeAsModal } = require('photoshop').core
4
+ // const export_png = require('./export_png')
5
+
6
+ // const { layerToSelection } = require('./helper')
7
+
8
+ const storage = require('uxp').storage
9
+ const fs = storage.localFileSystem
10
+
11
+ async function createSolidLayer(r, g, b) {
12
+ console.warn('this function is deprecated')
13
+ await executeAsModal(async () => {
14
+ const result = await batchPlay(
15
+ [
16
+ {
17
+ _obj: 'make',
18
+ _target: [
19
+ {
20
+ _ref: 'contentLayer',
21
+ },
22
+ ],
23
+ using: {
24
+ _obj: 'contentLayer',
25
+ type: {
26
+ _obj: 'solidColorLayer',
27
+ color: {
28
+ _obj: 'RGBColor',
29
+ red: r,
30
+ grain: g,
31
+ blue: b,
32
+ },
33
+ },
34
+ },
35
+ _options: {
36
+ dialogOptions: 'dontDisplay',
37
+ },
38
+ },
39
+ ],
40
+ {
41
+ synchronousExecution: true,
42
+ modalBehavior: 'execute',
43
+ }
44
+ )
45
+ })
46
+ }
47
+
48
+ async function makeGroupCommand() {
49
+ const result = await batchPlay(
50
+ [
51
+ {
52
+ _obj: 'make',
53
+ _target: [
54
+ {
55
+ _ref: 'layerSection',
56
+ },
57
+ ],
58
+ layerSectionStart: 405,
59
+ layerSectionEnd: 406,
60
+ name: 'Group 16',
61
+ _options: {
62
+ dialogOptions: 'dontDisplay',
63
+ },
64
+ },
65
+ ],
66
+ {
67
+ synchronousExecution: true,
68
+ modalBehavior: 'execute',
69
+ }
70
+ )
71
+
72
+ console.log('makeGroupCommand: ', result)
73
+
74
+ return result
75
+ }
76
+ async function createEmptyGroup(name = 'New Group') {
77
+ let groupLayer
78
+ await executeAsModal(async () => {
79
+ await makeGroupCommand()
80
+ groupLayer = app.activeDocument.activeLayers[0]
81
+ groupLayer.name = name
82
+ })
83
+ console.log('groupLayer:', groupLayer)
84
+ return groupLayer
85
+ }
86
+
87
+ async function moveToGroupCommand(to_index, layerIDs) {
88
+ const batchPlay = require('photoshop').action.batchPlay
89
+ console.log('to_index:', to_index)
90
+ console.log('layerIDs:', layerIDs)
91
+
92
+ const result = await batchPlay(
93
+ [
94
+ {
95
+ _obj: 'move',
96
+ _target: [
97
+ {
98
+ _ref: 'layer',
99
+ _enum: 'ordinal',
100
+ _value: 'targetEnum',
101
+ },
102
+ ],
103
+ to: {
104
+ _ref: 'layer',
105
+ _index: to_index,
106
+ },
107
+ adjustment: false,
108
+ version: 5,
109
+ layerID: layerIDs,
110
+ _options: {
111
+ dialogOptions: 'dontDisplay',
112
+ },
113
+ },
114
+ ],
115
+ {
116
+ synchronousExecution: true,
117
+ modalBehavior: 'execute',
118
+ }
119
+ )
120
+ }
121
+ function MoveToGroupExe(toIndex, layerIDs) {
122
+ try {
123
+ executeAsModal(async () => {
124
+ await moveToGroupCommand(toIndex, layerIDs)
125
+ })
126
+ } catch (e) {
127
+ console.warn('executeCommand error:', e)
128
+ }
129
+ }
130
+
131
+ async function getIndexCommand(layer_id) {
132
+ const idx = batchPlay(
133
+ [
134
+ {
135
+ _obj: 'get',
136
+ _target: [
137
+ {
138
+ _property: 'itemIndex',
139
+ },
140
+ {
141
+ _ref: 'layer',
142
+ // _name: 'myGroup'
143
+ _id: layer_id,
144
+ },
145
+ ],
146
+ _options: {
147
+ dialogOptions: 'dontDisplay',
148
+ },
149
+ },
150
+ ],
151
+ { synchronousExecution: true }
152
+ )[0]['itemIndex']
153
+ console.log('index:', idx)
154
+ return idx
155
+ }
156
+
157
+ async function getLayerIndex(layer_id) {
158
+ const { executeAsModal } = require('photoshop').core
159
+ try {
160
+ let index
161
+ await executeAsModal(async () => {
162
+ index = await getIndexCommand(layer_id)
163
+ console.log('getIndex: ', index)
164
+ })
165
+ return index
166
+ } catch (e) {
167
+ console.warn('getIndex error:', e)
168
+ }
169
+ }
170
+
171
+ async function unselectActiveLayers() {
172
+ const layers = await app.activeDocument.activeLayers
173
+ for (layer of layers) {
174
+ layer.selected = false
175
+ }
176
+ }
177
+ async function unselectActiveLayersExe() {
178
+ await executeAsModal(async () => {
179
+ await unselectActiveLayers()
180
+ })
181
+ }
182
+ async function selectLayers(layers) {
183
+ await unselectActiveLayers()
184
+ for (layer of layers) {
185
+ try {
186
+ if (layer) {
187
+ const is_visible = layer.visible // don't change the visibility when selecting the layer
188
+ layer.selected = true
189
+ layer.visible = is_visible
190
+ }
191
+ } catch (e) {
192
+ console.warn(e)
193
+ }
194
+ }
195
+ }
196
+
197
+ async function setVisibleExe(layer, is_visible) {
198
+ try {
199
+ await executeAsModal(async () => {
200
+ layer.visible = is_visible
201
+ })
202
+ } catch (e) {
203
+ console.warn(e)
204
+ }
205
+ }
206
+ async function selectLayersExe(layers) {
207
+ await executeAsModal(async () => {
208
+ await selectLayers(layers)
209
+ })
210
+ }
211
+ async function selectGroup(layer) {
212
+ await unselectActiveLayers()
213
+ layer.parent.selected = true
214
+ }
215
+ async function collapseGroup(layer) {
216
+ await selectGroup(layer)
217
+ await app.activeDocument.activeLayers[0].merge()
218
+ }
219
+
220
+ async function createMaskCommand() {
221
+ const batchPlay = require('photoshop').action.batchPlay
222
+
223
+ const result = await batchPlay(
224
+ [
225
+ {
226
+ _obj: 'make',
227
+ new: {
228
+ _class: 'channel',
229
+ },
230
+ at: {
231
+ _ref: 'channel',
232
+ _enum: 'channel',
233
+ _value: 'mask',
234
+ },
235
+ using: {
236
+ _enum: 'userMaskEnabled',
237
+ _value: 'revealSelection',
238
+ },
239
+ _options: {
240
+ dialogOptions: 'dontDisplay',
241
+ },
242
+ },
243
+ ],
244
+ {
245
+ synchronousExecution: true,
246
+ modalBehavior: 'execute',
247
+ }
248
+ )
249
+ }
250
+
251
+ async function createMaskExe() {
252
+ const { executeAsModal } = require('photoshop').core
253
+ await executeAsModal(createMaskCommand)
254
+ }
255
+
256
+ //unselect the rectangular marquee selection area
257
+ async function unSelectMarqueeCommand() {
258
+ const batchPlay = require('photoshop').action.batchPlay
259
+
260
+ const result = await batchPlay(
261
+ [
262
+ {
263
+ _obj: 'set',
264
+ _target: [
265
+ {
266
+ _ref: 'channel',
267
+ _property: 'selection',
268
+ },
269
+ ],
270
+ to: {
271
+ _enum: 'ordinal',
272
+ _value: 'none',
273
+ },
274
+ _options: {
275
+ dialogOptions: 'dontDisplay',
276
+ },
277
+ },
278
+ ],
279
+ {
280
+ synchronousExecution: true,
281
+ modalBehavior: 'execute',
282
+ }
283
+ )
284
+
285
+ return result
286
+ }
287
+ async function unSelectMarqueeExe() {
288
+ try {
289
+ await executeAsModal(unSelectMarqueeCommand)
290
+ } catch (e) {
291
+ console.warn(e)
292
+ }
293
+ }
294
+
295
+ //REFACTOR: move to selection.js
296
+ async function selectMarqueeRectangularToolExe() {
297
+ async function selectMarqueeRectangularToolCommand() {
298
+ const result = await batchPlay(
299
+ [
300
+ {
301
+ _obj: 'select',
302
+ _target: [
303
+ {
304
+ _ref: 'marqueeRectTool',
305
+ },
306
+ ],
307
+ _options: {
308
+ dialogOptions: 'dontDisplay',
309
+ },
310
+ },
311
+ ],
312
+ {
313
+ synchronousExecution: true,
314
+ modalBehavior: 'execute',
315
+ }
316
+ )
317
+ return result
318
+ }
319
+ await executeAsModal(async () => {
320
+ await selectMarqueeRectangularToolCommand()
321
+ })
322
+ }
323
+
324
+ async function promptForMarqueeTool() {
325
+ console.warn('promptForMarqueeTool is deprecated use Notification class')(
326
+ async () => {
327
+ const r1 = await dialog_box.prompt(
328
+ 'Please Select a Rectangular Area',
329
+ 'You Forgot to select a Rectangular Area',
330
+ ['Cancel', 'Rectangular Marquee']
331
+ )
332
+ if ((r1 || 'Rectangular Marquee') !== 'Rectangular Marquee') {
333
+ /* cancelled or No */
334
+ console.log('cancel')
335
+ } else {
336
+ /* Yes */
337
+ console.log('Rectangular Marquee')
338
+ selectMarqueeRectangularToolExe()
339
+ }
340
+ }
341
+ )()
342
+ }
343
+
344
+ async function selectLayerChannelCommand() {
345
+ // const result = await batchPlay(
346
+ // [
347
+ // {
348
+ // _obj: 'set',
349
+ // _target: [
350
+ // {
351
+ // _ref: 'channel',
352
+ // _property: 'selection'
353
+ // }
354
+ // ],
355
+ // to: {
356
+ // _ref: [
357
+ // {
358
+ // _ref: 'channel',
359
+ // _enum: 'channel',
360
+ // _value: 'transparencyEnum'
361
+ // },
362
+ // {
363
+ // _ref: 'layer',
364
+ // _name: 'Group 5'
365
+ // }
366
+ // ]
367
+ // },
368
+ // _options: {
369
+ // dialogOptions: 'dontDisplay'
370
+ // }
371
+ // }
372
+ // ],
373
+ // {
374
+ // synchronousExecution: false,
375
+ // modalBehavior: 'execute'
376
+ // }
377
+ // )
378
+ const batchPlay = require('photoshop').action.batchPlay
379
+
380
+ const result = await batchPlay(
381
+ [
382
+ {
383
+ _obj: 'set',
384
+ _target: [
385
+ {
386
+ _ref: 'channel',
387
+ _property: 'selection',
388
+ },
389
+ ],
390
+ to: {
391
+ _ref: 'channel',
392
+ _enum: 'channel',
393
+ _value: 'transparencyEnum',
394
+ },
395
+ _options: {
396
+ dialogOptions: 'dontDisplay',
397
+ },
398
+ },
399
+ ],
400
+ {
401
+ synchronousExecution: true,
402
+ modalBehavior: 'execute',
403
+ }
404
+ )
405
+ }
406
+
407
+ async function getSelectionInfoCommand() {
408
+ // console.warn('getSelectionInfoCommand is deprecated use SelectionInfoDesc')
409
+ const result = await batchPlay(
410
+ [
411
+ {
412
+ _obj: 'get',
413
+ _target: [
414
+ {
415
+ _property: 'selection',
416
+ },
417
+ {
418
+ _ref: 'document',
419
+ _id: app.activeDocument._id,
420
+ },
421
+ ],
422
+ _options: {
423
+ dialogOptions: 'dontDisplay',
424
+ },
425
+ },
426
+ ],
427
+ {
428
+ synchronousExecution: true,
429
+ modalBehavior: 'execute',
430
+ }
431
+ )
432
+
433
+ return result
434
+ }
435
+
436
+ function isSelectionValid(selection) {
437
+ // console.warn(
438
+ // 'isSelectionValid is deprecated use selection.isSelectionValid instead'
439
+ // )
440
+ if (
441
+ selection && // check if the selection is defined
442
+ selection.hasOwnProperty('left') &&
443
+ selection.hasOwnProperty('right') &&
444
+ selection.hasOwnProperty('top') &&
445
+ selection.hasOwnProperty('bottom')
446
+ ) {
447
+ return true
448
+ }
449
+
450
+ return false
451
+ }
452
+
453
+ async function getSelectionInfoExe() {
454
+ // console.log('getSelectionInfo was called')
455
+ // console.warn(
456
+ // 'getSelectionInfoExe is deprecated use selection.getSelectionInfoExe instead'
457
+ // )
458
+ try {
459
+ const selection = (await executeAsModal(getSelectionInfoCommand))[0]
460
+ .selection
461
+
462
+ if (isSelectionValid(selection)) {
463
+ let selection_info = {
464
+ left: selection.left._value,
465
+ right: selection.right._value,
466
+ bottom: selection.bottom._value,
467
+ top: selection.top._value,
468
+ height: selection.bottom._value - selection.top._value,
469
+ width: selection.right._value - selection.left._value,
470
+ }
471
+ // console.dir({selection_info})
472
+ return selection_info
473
+ }
474
+ } catch (e) {
475
+ console.warn('selection info error', e)
476
+ }
477
+ }
478
+
479
+ async function reSelectMarqueeCommand(selectionInfo) {
480
+ const result = await batchPlay(
481
+ [
482
+ {
483
+ _obj: 'set',
484
+ _target: [
485
+ {
486
+ _ref: 'channel',
487
+ _property: 'selection',
488
+ },
489
+ ],
490
+ to: {
491
+ _obj: 'rectangle',
492
+ top: {
493
+ _unit: 'pixelsUnit',
494
+ _value: selectionInfo.top,
495
+ },
496
+ left: {
497
+ _unit: 'pixelsUnit',
498
+ _value: selectionInfo.left,
499
+ },
500
+ bottom: {
501
+ _unit: 'pixelsUnit',
502
+ _value: selectionInfo.bottom,
503
+ },
504
+ right: {
505
+ _unit: 'pixelsUnit',
506
+ _value: selectionInfo.right,
507
+ },
508
+ },
509
+ _options: {
510
+ dialogOptions: 'dontDisplay',
511
+ },
512
+ },
513
+ ],
514
+ {
515
+ synchronousExecution: true,
516
+ modalBehavior: 'execute',
517
+ }
518
+ )
519
+ }
520
+ async function reSelectMarqueeExe(selectionInfo) {
521
+ try {
522
+ if (isSelectionValid(selectionInfo)) {
523
+ //only try to reactivate the selection area if it is valid
524
+ await executeAsModal(async () => {
525
+ await reSelectMarqueeCommand(selectionInfo)
526
+ })
527
+ }
528
+ } catch (e) {
529
+ console.warn(e)
530
+ }
531
+ }
532
+
533
+ async function snapshot_layer() {
534
+ let psAction = require('photoshop').action
535
+ // const ids = (await app.activeDocument.activeLayers).map(layer => layer.id)
536
+ const ids = await app.activeDocument.layers.map((layer) => layer.id)
537
+ let command = [
538
+ // Select All Layers current layer
539
+ {
540
+ _obj: 'selectAllLayers',
541
+ _target: [
542
+ { _enum: 'ordinal', _ref: 'layer', _value: 'targetEnum' },
543
+ ],
544
+ },
545
+ // Duplicate current layer
546
+ // {"ID":[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],"_obj":"duplicate","_target":[{"_enum":"ordinal","_ref":"layer","_value":"targetEnum"}],"version":5},
547
+ {
548
+ ID: ids,
549
+ _obj: 'duplicate',
550
+ _target: [
551
+ { _enum: 'ordinal', _ref: 'layer', _value: 'targetEnum' },
552
+ ],
553
+ // version: 5
554
+ },
555
+
556
+ // Merge Layers
557
+ { _obj: 'mergeLayersNew' },
558
+ // Make
559
+ {
560
+ _obj: 'make',
561
+ at: { _enum: 'channel', _ref: 'channel', _value: 'mask' },
562
+ new: { _class: 'channel' },
563
+ using: { _enum: 'userMaskEnabled', _value: 'revealSelection' },
564
+ },
565
+ // Set Selection
566
+ {
567
+ _obj: 'set',
568
+ _target: [{ _property: 'selection', _ref: 'channel' }],
569
+ to: { _enum: 'ordinal', _ref: 'channel', _value: 'targetEnum' },
570
+ },
571
+ ]
572
+ const result = await psAction.batchPlay(command, {
573
+ synchronousExecution: true,
574
+ modalBehavior: 'execute',
575
+ })
576
+ console.log('snapshot_layer: result: ', result)
577
+ return result
578
+ }
579
+ async function snapshot_layer_new() {
580
+ //similar to snapshot_layer() but fixes the problem with smart effects
581
+
582
+ let psAction = require('photoshop').action
583
+
584
+ const ids = await app.activeDocument.layers.map((layer) => layer.id)
585
+ const selection_info = await getSelectionInfoExe()
586
+
587
+ let create_snapshot_layer_command = [
588
+ // Select All Layers current layer
589
+ {
590
+ _obj: 'selectAllLayers',
591
+ _target: [
592
+ { _enum: 'ordinal', _ref: 'layer', _value: 'targetEnum' },
593
+ ],
594
+ },
595
+ // Duplicate current layer
596
+
597
+ {
598
+ ID: ids,
599
+ _obj: 'duplicate',
600
+ _target: [
601
+ { _enum: 'ordinal', _ref: 'layer', _value: 'targetEnum' },
602
+ ],
603
+ // version: 5
604
+ },
605
+
606
+ // Merge Layers
607
+ { _obj: 'mergeLayersNew' },
608
+ ]
609
+ const result = await psAction.batchPlay(create_snapshot_layer_command, {
610
+ synchronousExecution: true,
611
+ modalBehavior: 'execute',
612
+ })
613
+ await reSelectMarqueeExe(selection_info) //reselect the selection area for the mask
614
+ //make a mask of the selection area
615
+ const make_mask_command = [
616
+ // Make
617
+ {
618
+ _obj: 'make',
619
+ at: { _enum: 'channel', _ref: 'channel', _value: 'mask' },
620
+ new: { _class: 'channel' },
621
+ using: { _enum: 'userMaskEnabled', _value: 'revealSelection' },
622
+ },
623
+ // // Set Selection
624
+ // {
625
+ // _obj: 'set',
626
+ // _target: [{ _property: 'selection', _ref: 'channel' }],
627
+ // to: { _enum: 'ordinal', _ref: 'channel', _value: 'targetEnum' },
628
+ // },
629
+ ]
630
+ const result_2 = await psAction.batchPlay(make_mask_command, {
631
+ synchronousExecution: true,
632
+ modalBehavior: 'execute',
633
+ })
634
+ await reSelectMarqueeExe(selection_info) //reselect the selection area again so we don't break other functionality
635
+
636
+ console.log('snapshot_layer: result: ', result)
637
+ return result
638
+ }
639
+
640
+ async function snapshot_layerExe() {
641
+ try {
642
+ await executeAsModal(
643
+ async () => {
644
+ await snapshot_layer_new()
645
+ },
646
+ {
647
+ commandName: 'Action Commands',
648
+ }
649
+ )
650
+ } catch (e) {
651
+ console.error(e)
652
+ }
653
+ }
654
+
655
+ async function snapshot_layer_no_slide() {
656
+ let psAction = require('photoshop').action
657
+ // const ids = (await app.activeDocument.activeLayers).map(layer => layer.id)
658
+ const ids = await app.activeDocument.layers.map((layer) => layer.id)
659
+ let command = [
660
+ // Select All Layers current layer
661
+ {
662
+ _obj: 'selectAllLayers',
663
+ _target: [
664
+ { _enum: 'ordinal', _ref: 'layer', _value: 'targetEnum' },
665
+ ],
666
+ },
667
+ // Duplicate current layer
668
+ // {"ID":[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],"_obj":"duplicate","_target":[{"_enum":"ordinal","_ref":"layer","_value":"targetEnum"}],"version":5},
669
+ {
670
+ ID: ids,
671
+ _obj: 'duplicate',
672
+ _target: [
673
+ { _enum: 'ordinal', _ref: 'layer', _value: 'targetEnum' },
674
+ ],
675
+ // version: 5
676
+ },
677
+
678
+ // // Merge Layers
679
+ // { _obj: 'mergeLayersNew' },
680
+ // // Make
681
+ // {
682
+ // _obj: 'make',
683
+ // at: { _enum: 'channel', _ref: 'channel', _value: 'mask' },
684
+ // new: { _class: 'channel' },
685
+ // using: { _enum: 'userMaskEnabled', _value: 'revealSelection' },
686
+ // },
687
+ // // Set Selection
688
+ // {
689
+ // _obj: 'set',
690
+ // _target: [{ _property: 'selection', _ref: 'channel' }],
691
+ // to: { _enum: 'ordinal', _ref: 'channel', _value: 'targetEnum' },
692
+ // },
693
+ ]
694
+ const result = await psAction.batchPlay(command, {
695
+ synchronousExecution: true,
696
+ modalBehavior: 'execute',
697
+ })
698
+ console.log('snapshot_layer: result: ', result)
699
+ return result
700
+ }
701
+
702
+ async function snapshot_layer_no_slide_Exe() {
703
+ try {
704
+ await executeAsModal(
705
+ async () => {
706
+ await snapshot_layer_no_slide()
707
+ },
708
+ {
709
+ commandName: 'Action Commands',
710
+ }
711
+ )
712
+ } catch (e) {
713
+ console.error(e)
714
+ }
715
+ }
716
+
717
+ // await runModalFunction();
718
+
719
+ async function fillAndGroup() {
720
+ let result
721
+ let psAction = require('photoshop').action
722
+
723
+ // let newCommand =[
724
+ // // snapshotLayer
725
+
726
+ // // makeGroupCommand
727
+
728
+ // // Make fill layer
729
+ // {"_obj":"make","_target":[{"_ref":"contentLayer"}],"using":{"_obj":"contentLayer","type":{"_obj":"solidColorLayer","color":{"_obj":"RGBColor","blue":255.0,"grain":255.0,"red":255.0}}}},
730
+
731
+ // ]
732
+
733
+ let command = [
734
+ // Make fill layer
735
+ {
736
+ _obj: 'make',
737
+ _target: [{ _ref: 'contentLayer' }],
738
+ using: {
739
+ _obj: 'contentLayer',
740
+ type: {
741
+ _obj: 'solidColorLayer',
742
+ color: {
743
+ _obj: 'RGBColor',
744
+ blue: 255.0,
745
+ grain: 255.0,
746
+ red: 255.0,
747
+ },
748
+ },
749
+ },
750
+ },
751
+ // Move current layer
752
+ // {"_obj":"move","_target":[{"_enum":"ordinal","_ref":"layer","_value":"targetEnum"}],"adjustment":false,"layerID":[17],"to":{"_index":7,"_ref":"layer"},"version":5},
753
+ // Select layer “Layer 4 copy”
754
+ // {"_obj":"select","_target":[{"_name":"Layer 4 copy","_ref":"layer"}],"layerID":[17,15],"makeVisible":false,"selectionModifier":{"_enum":"selectionModifierType","_value":"addToSelectionContinuous"}},
755
+ // Make Group
756
+ // {"_obj":"make","_target":[{"_ref":"layerSection"}],"from":{"_enum":"ordinal","_ref":"layer","_value":"targetEnum"},"layerSectionEnd":19,"layerSectionStart":18,"name":"Group 1"}
757
+ ]
758
+ const snapshotLayer = await app.activeDocument.activeLayers[0]
759
+ await makeGroupCommand()
760
+ const groupLayer = app.activeDocument.activeLayers[0]
761
+ result = await psAction.batchPlay(command, {})
762
+ const fillLayer = app.activeDocument.activeLayers[0]
763
+ snapshotLayer.moveAbove(fillLayer)
764
+ // await app.activeDocument.activeLayers[0].moveAbove()
765
+ // const layerIDs = []
766
+ // const to_index = await getIndexCommand(groupLayer.id)
767
+ // await moveToGroupCommand(to_index, layerIDs)
768
+ }
769
+
770
+ async function fillAndGroupExe() {
771
+ await require('photoshop').core.executeAsModal(fillAndGroup, {
772
+ commandName: 'Action Commands',
773
+ })
774
+ }
775
+ async function fastSnapshot() {
776
+ await snapshot_layerExe()
777
+ await fillAndGroupExe()
778
+ }
779
+
780
+ function layerToFileName(layer, session_id) {
781
+ file_name = `${layer.name}_${layer.id}_${session_id}`
782
+ return file_name
783
+ }
784
+ function layerNameToFileName(layer_name, layer_id, session_id) {
785
+ file_name = `${layer_name}_${layer_id}_${session_id}`
786
+ return file_name
787
+ }
788
+
789
+ async function silentSetInitImage(layer, session_id) {
790
+ try {
791
+ const html_manip = require('./utility/html_manip')
792
+ const io = require('./utility/io')
793
+ // const layer = await app.activeDocument.activeLayers[0]
794
+ const old_name = layer.name
795
+
796
+ // image_name = await app.activeDocument.activeLayers[0].name
797
+
798
+ //convert layer name to a file name
799
+ let image_name = layerNameToFileName(old_name, layer.id, session_id)
800
+ image_name = `${image_name}.png`
801
+
802
+ //the width and height of the exported image
803
+ const width = html_manip.getWidth()
804
+ const height = html_manip.getHeight()
805
+
806
+ //get the selection from the canvas as base64 png, make sure to resize to the width and height slider
807
+ const selectionInfo = g_generation_session.selectionInfo
808
+ // const base64_image = await io.IO.getSelectionFromCanvasAsBase64Silent(
809
+ // selectionInfo,
810
+ // true,
811
+ // width,
812
+ // height
813
+ // )
814
+
815
+ const use_silent_mode = html_manip.getUseSilentMode()
816
+ // if (use_silent_mode) {
817
+ // base64_image = await io.IO.getSelectionFromCanvasAsBase64Silent(
818
+ // selectionInfo,
819
+ // true,
820
+ // width,
821
+ // height
822
+ // )
823
+ // } else {
824
+ // base64_image = await io.IO.getSelectionFromCanvasAsBase64NonSilent(
825
+ // layer,
826
+
827
+ // image_name,
828
+ // width,
829
+ // height
830
+ // )
831
+ // }
832
+ const base64_image =
833
+ await io.IO.getSelectionFromCanvasAsBase64Interface(
834
+ width,
835
+ height,
836
+ layer,
837
+ selectionInfo,
838
+ true,
839
+ use_silent_mode,
840
+ image_name
841
+ )
842
+ //save base64 as file in the init_images directory
843
+ const init_entry = await getInitImagesDir()
844
+ await io.IO.base64PngToPngFile(base64_image, init_entry, image_name)
845
+
846
+ g_init_image_name = image_name
847
+ console.log(image_name)
848
+
849
+ const path = `${g_init_images_dir}/${image_name}`
850
+
851
+ //store the base64 init image and also set it as the active/latest init image
852
+ g_generation_session.base64initImages[path] = base64_image
853
+ g_generation_session.activeBase64InitImage = base64_image
854
+
855
+ const init_src = base64ToSrc(g_generation_session.activeBase64InitImage)
856
+ html_manip.setInitImageSrc(init_src)
857
+
858
+ return (image_info = { name: image_name, base64: base64_image })
859
+ } catch (e) {
860
+ console.error(`psapi.js silentSetInitImage error:, ${e}`)
861
+ }
862
+ }
863
+ async function silentSetInitImageMask(layer, session_id) {
864
+ try {
865
+ const html_manip = require('./utility/html_manip')
866
+
867
+ // const layer = await app.activeDocument.activeLayers[0]
868
+ const old_name = layer.name
869
+
870
+ image_name = layerNameToFileName(old_name, layer.id, session_id)
871
+ image_name = `${image_name}.png`
872
+ const width = html_manip.getWidth()
873
+ const height = html_manip.getHeight()
874
+
875
+ //get the selection from the canvas as base64 png, make sure to resize to the width and height slider
876
+ const selectionInfo = g_generation_session.selectionInfo
877
+
878
+ const use_silent_mode = html_manip.getUseSilentMode()
879
+
880
+ const base64_image =
881
+ await io.IO.getSelectionFromCanvasAsBase64Interface(
882
+ width,
883
+ height,
884
+ layer,
885
+ selectionInfo,
886
+ true,
887
+ use_silent_mode,
888
+ image_name
889
+ )
890
+
891
+ //save base64 as file in the init_images directory
892
+ const init_entry = await getInitImagesDir()
893
+ await io.IO.base64PngToPngFile(base64_image, init_entry, image_name)
894
+
895
+ g_init_image_mask_name = image_name // this is the name we will send to the server
896
+
897
+ console.log(image_name)
898
+
899
+ const path = `${g_init_images_dir}/${image_name}`
900
+ g_generation_session.base64maskImage[path] = base64_image
901
+ g_generation_session.activeBase64MaskImage = base64_image
902
+
903
+ const mask_src = base64ToSrc(g_generation_session.activeBase64MaskImage)
904
+ html_manip.setInitImageMaskSrc(mask_src)
905
+ return (image_info = { name: image_name, base64: base64_image })
906
+ } catch (e) {
907
+ console.error(`psapi.js setInitImageMask error: `, e)
908
+ }
909
+ }
910
+ async function setInitImage(layer, session_id) {
911
+ try {
912
+ const html_manip = require('./utility/html_manip')
913
+ // const layer = await app.activeDocument.activeLayers[0]
914
+ const old_name = layer.name
915
+
916
+ // image_name = await app.activeDocument.activeLayers[0].name
917
+
918
+ //convert layer name to a file name
919
+ let image_name = layerNameToFileName(old_name, layer.id, session_id)
920
+ image_name = `${image_name}.png`
921
+
922
+ //the width and height of the exported image
923
+ const width = html_manip.getWidth()
924
+ const height = html_manip.getHeight()
925
+ const image_buffer = await newExportPng(
926
+ layer,
927
+ image_name,
928
+ width,
929
+ height
930
+ )
931
+ const base64_image = _arrayBufferToBase64(image_buffer) //convert the buffer to base64
932
+ //send the base64 to the server to save the file in the desired directory
933
+ await sdapi.requestSavePng(base64_image, image_name)
934
+
935
+ g_init_image_name = image_name
936
+ console.log(image_name)
937
+
938
+ const image_src = await sdapi.getInitImage(g_init_image_name)
939
+ let ini_image_element = document.getElementById('init_image')
940
+ ini_image_element.src = image_src
941
+ const path = `${g_init_images_dir}/${image_name}`
942
+
943
+ g_generation_session.base64initImages[path] = base64_image
944
+ g_generation_session.activeBase64InitImage =
945
+ g_generation_session.base64initImages[path]
946
+
947
+ const init_src = base64ToSrc(g_generation_session.activeBase64InitImage)
948
+ html_manip.setInitImageSrc(init_src)
949
+
950
+ return (image_info = { name: image_name, base64: base64_image })
951
+ } catch (e) {
952
+ console.error(`psapi.js setInitImage error:, ${e}`)
953
+ }
954
+ }
955
+ async function setInitImageMask(layer, session_id) {
956
+ try {
957
+ const html_manip = require('./utility/html_manip')
958
+
959
+ // const layer = await app.activeDocument.activeLayers[0]
960
+ const old_name = layer.name
961
+
962
+ //get the active layer name
963
+ // image_name = await app.activeDocument.activeLayers[0].name
964
+ // image_name = layerNameToFileName(old_name,layer.id,random_session_id)
965
+ image_name = layerNameToFileName(old_name, layer.id, session_id)
966
+ image_name = `${image_name}.png`
967
+ const width = html_manip.getWidth()
968
+ const height = html_manip.getHeight()
969
+ image_buffer = await newExportPng(layer, image_name, width, height)
970
+ g_init_image_mask_name = image_name // this is the name we will send to the server
971
+ // g_init_mask_layer = layer
972
+ // g_mask_related_layers = {}
973
+
974
+ console.log(image_name)
975
+ base64_image = _arrayBufferToBase64(image_buffer) //convert the buffer to base64
976
+ //send the base64 to the server to save the file in the desired directory
977
+ await sdapi.requestSavePng(base64_image, image_name)
978
+
979
+ const image_src = await sdapi.getInitImage(g_init_image_mask_name) // we should replace this with getInitImagePath which return path to local disk
980
+ const ini_image_mask_element =
981
+ document.getElementById('init_image_mask')
982
+ ini_image_mask_element.src = image_src
983
+ ini_image_mask_element.dataset.layer_id = layer.id
984
+
985
+ const path = `${g_init_images_dir}/${image_name}`
986
+ g_generation_session.base64maskImage[path] = base64_image
987
+ g_generation_session.activeBase64MaskImage =
988
+ g_generation_session.base64maskImage[path]
989
+ //create viewer init image obj
990
+ {
991
+ }
992
+ // return image_name
993
+ const mask_src = base64ToSrc(g_generation_session.activeBase64MaskImage)
994
+ html_manip.setInitImageMaskSrc(mask_src)
995
+ return (image_info = { name: image_name, base64: base64_image })
996
+ } catch (e) {
997
+ console.error(`psapi.js setInitImageMask error: `, e)
998
+ }
999
+ }
1000
+
1001
+ // remove the generated mask related layers from the canvas and "layers" panel
1002
+
1003
+ // async function cleanSnapAndFill(layers){
1004
+ // // we can delete this function and use cleanLayers() instead
1005
+ // //delete init image group
1006
+ // //delete init image (snapshot layer)
1007
+ // //delete fill layer
1008
+
1009
+ // for (layer of layers){
1010
+ // try{
1011
+
1012
+ // await executeAsModal(async ()=>{await layer.delete()})
1013
+ // }catch(e){
1014
+ // console.warn("cleanSnapAndFill, issue deleting a layer",e)
1015
+ // }
1016
+ // }
1017
+ // return []
1018
+ // }
1019
+
1020
+ async function cleanLayers(layers) {
1021
+ // g_init_image_related_layers = {}
1022
+ // g_mask_related_layers = {}
1023
+ // await loadViewerImages()// we should move loadViewerImages to a new file viewer.js
1024
+ console.log('cleanLayers() -> layers:', layers)
1025
+ for (layer of layers) {
1026
+ try {
1027
+ if (layer_util.Layer.doesLayerExist(layer)) {
1028
+ await executeAsModal(async () => {
1029
+ await layer.delete()
1030
+ })
1031
+ }
1032
+ } catch (e) {
1033
+ console.warn(
1034
+ 'warning attempting to a delete layer,layer.name: ',
1035
+ layer.name,
1036
+ layer,
1037
+ e
1038
+ )
1039
+ continue
1040
+ }
1041
+ }
1042
+ return []
1043
+ }
1044
+
1045
+ // async function cleanLayersOutpaint(layers){
1046
+ // //delete group mask layer
1047
+ // //delete mask layer
1048
+ // //delete group init image layer
1049
+ // //delete init image layer (snapshot layer)
1050
+ // //delete fill layer
1051
+
1052
+ // for (layer of layers){
1053
+ // try {
1054
+ // await executeAsModal(async ()=>{await layer.delete()})}
1055
+ // catch(e){
1056
+ // console.warn("warning attempting to a delete layer: ",e)
1057
+ // }
1058
+ // }
1059
+
1060
+ // return []
1061
+ // }
1062
+ // async function cleanLayersInpaint(layers){
1063
+ // //delete group mask layer
1064
+ // //delete white mask layer
1065
+ // //delete the black fill layer
1066
+ // //delete init image layer (snapshot layer)
1067
+
1068
+ // for (layer of layers){
1069
+ // await executeAsModal(async ()=>{await layer.delete()})
1070
+ // }
1071
+
1072
+ // return []
1073
+ // }
1074
+ async function createClippingMaskExe() {
1075
+ const batchPlay = require('photoshop').action.batchPlay
1076
+
1077
+ async function createClippingMaskCommand() {
1078
+ const result = await batchPlay(
1079
+ [
1080
+ {
1081
+ _obj: 'make',
1082
+ new: {
1083
+ _class: 'channel',
1084
+ },
1085
+ at: {
1086
+ _ref: 'channel',
1087
+ _enum: 'channel',
1088
+ _value: 'mask',
1089
+ },
1090
+ using: {
1091
+ _enum: 'userMaskEnabled',
1092
+ _value: 'revealSelection',
1093
+ },
1094
+ _options: {
1095
+ dialogOptions: 'dontDisplay',
1096
+ },
1097
+ },
1098
+ ],
1099
+ {
1100
+ synchronousExecution: true,
1101
+ modalBehavior: 'execute',
1102
+ }
1103
+ )
1104
+ }
1105
+
1106
+ await executeAsModal(async () => {
1107
+ await createClippingMaskCommand()
1108
+ })
1109
+ }
1110
+ //REFACTOR: delete and replace with getSelectionInfoExe()
1111
+ async function checkIfSelectionAreaIsActive() {
1112
+ try {
1113
+ let isSelectionAreaValid = await getSelectionInfoExe()
1114
+ return isSelectionAreaValid
1115
+ } catch (e) {
1116
+ console.warn(e)
1117
+ }
1118
+ }
1119
+ async function saveUniqueDocumentIdExe(new_id) {
1120
+ const batchPlay = require('photoshop').action.batchPlay
1121
+
1122
+ async function saveUniqueDocumentIdCommand() {
1123
+ const batchPlay = require('photoshop').action.batchPlay
1124
+
1125
+ const result = await batchPlay(
1126
+ [
1127
+ {
1128
+ _obj: 'set',
1129
+ _target: [
1130
+ {
1131
+ _ref: 'property',
1132
+ _property: 'fileInfo',
1133
+ },
1134
+ {
1135
+ _ref: 'document',
1136
+ _enum: 'ordinal',
1137
+ _value: 'targetEnum',
1138
+ },
1139
+ ],
1140
+ to: {
1141
+ _obj: 'fileInfo',
1142
+ caption: new_id,
1143
+ keywords: [new_id],
1144
+ },
1145
+ _options: {
1146
+ dialogOptions: 'dontDisplay',
1147
+ },
1148
+ },
1149
+ ],
1150
+ {
1151
+ synchronousExecution: true,
1152
+ modalBehavior: 'execute',
1153
+ }
1154
+ )
1155
+ }
1156
+
1157
+ await executeAsModal(async () => {
1158
+ await saveUniqueDocumentIdCommand()
1159
+ })
1160
+ }
1161
+
1162
+ async function readUniqueDocumentIdExe() {
1163
+ const batchPlay = require('photoshop').action.batchPlay
1164
+
1165
+ async function readUniqueDocumentIdCommand() {
1166
+ const batchPlay = require('photoshop').action.batchPlay
1167
+
1168
+ const result = await batchPlay(
1169
+ [
1170
+ {
1171
+ _obj: 'get',
1172
+ _target: [
1173
+ {
1174
+ _ref: 'property',
1175
+ _property: 'fileInfo',
1176
+ },
1177
+ {
1178
+ _ref: 'document',
1179
+ _enum: 'ordinal',
1180
+ _value: 'targetEnum',
1181
+ },
1182
+ ],
1183
+ // to: {
1184
+ // _obj: 'fileInfo',
1185
+ // caption: new_id,
1186
+ // keywords: [new_id]
1187
+ // },
1188
+ _options: {
1189
+ dialogOptions: 'dontDisplay',
1190
+ },
1191
+ },
1192
+ ],
1193
+ {
1194
+ synchronousExecution: true,
1195
+ modalBehavior: 'execute',
1196
+ }
1197
+ )
1198
+ console.log('readUniqueDocumentIdCommand: result ', result)
1199
+ return result
1200
+ }
1201
+
1202
+ let uniqueDocumentId = ''
1203
+ try {
1204
+ await executeAsModal(async () => {
1205
+ uniqueDocumentId = (await readUniqueDocumentIdCommand())[0].fileInfo
1206
+ .caption
1207
+ if (typeof uniqueDocumentId === 'string') {
1208
+ uniqueDocumentId = uniqueDocumentId.trim()
1209
+ }
1210
+ })
1211
+ } catch (e) {
1212
+ console.warn('readUniqueDocumentIdExe: ', e)
1213
+ uniqueDocumentId = ''
1214
+ }
1215
+
1216
+ return uniqueDocumentId
1217
+ }
1218
+
1219
+ const readPng = async (image_name) => {
1220
+ //it will save the document then read it. store it in memory
1221
+ // image_name = 'test.png'
1222
+ try {
1223
+ let img_buffer
1224
+ await executeAsModal(
1225
+ async (control) => {
1226
+ const folder = await fs.getTemporaryFolder()
1227
+ // const pluginFolder = await fs.getPluginFolder()
1228
+
1229
+ // let init_images_dir = await pluginFolder.getEntry(
1230
+ // './server/python_server/init_images'
1231
+ // )
1232
+
1233
+ const file = await folder.createFile(image_name, {
1234
+ overwrite: true,
1235
+ })
1236
+
1237
+ const currentDocument = app.activeDocument
1238
+ await currentDocument.saveAs.png(
1239
+ file,
1240
+ // {
1241
+ // compression: 6,
1242
+ // },
1243
+ null,
1244
+ true
1245
+ )
1246
+
1247
+ const arrayBuffer = await file.read({ format: formats.binary })
1248
+ // console.log(arrayBuffer, 'arrayBuffer') ;
1249
+ img_buffer = arrayBuffer
1250
+ },
1251
+
1252
+ { commandName: 'readPng' }
1253
+ )
1254
+
1255
+ return img_buffer
1256
+ } catch (e) {
1257
+ console.warn(e)
1258
+ }
1259
+ }
1260
+
1261
+ async function selectCanvasCommand() {
1262
+ // const result = await batchPlay(
1263
+ // [
1264
+ // {
1265
+ // _obj: "historyStateChanged",
1266
+ // documentID: 1044,
1267
+ // ID: 1058,
1268
+ // name: "Select Canvas",
1269
+ // hasEnglish: true,
1270
+ // itemIndex: 7,
1271
+ // commandID: 1017,
1272
+ // _options: {
1273
+ // dialogOptions: "dontDisplay"
1274
+ // }
1275
+ // }
1276
+ // ],{
1277
+ // synchronousExecution: true,
1278
+ // modalBehavior: "execute"
1279
+ // });
1280
+
1281
+ const result = await batchPlay(
1282
+ [
1283
+ {
1284
+ _obj: 'set',
1285
+ _target: [
1286
+ {
1287
+ _ref: 'channel',
1288
+ _property: 'selection',
1289
+ },
1290
+ ],
1291
+ to: {
1292
+ _enum: 'ordinal',
1293
+ _value: 'allEnum',
1294
+ },
1295
+ _options: {
1296
+ dialogOptions: 'dontDisplay',
1297
+ },
1298
+ },
1299
+ ],
1300
+ {
1301
+ synchronousExecution: true,
1302
+ modalBehavior: 'execute',
1303
+ }
1304
+ )
1305
+
1306
+ return result
1307
+ }
1308
+ async function selectCanvasExe() {
1309
+ await executeAsModal(
1310
+ async () => {
1311
+ await selectCanvasCommand()
1312
+ },
1313
+ { commandName: 'selectCanvasExe' }
1314
+ )
1315
+ }
1316
+ async function newExportPng(layer, image_name, width, height) {
1317
+ //store layers we want to export in variables
1318
+ // let layerToExports =
1319
+ // create new document
1320
+ // duplicate the layers to the new documnet
1321
+ //select the layer channel selectLayerChannelCommand
1322
+ //document.crop
1323
+ //export using readPng()
1324
+
1325
+ try {
1326
+ //get the active layers
1327
+ // const layersToExport = app.activeDocument.activeLayers
1328
+
1329
+ //create new document
1330
+ // let exportDoc = await executeAsModal(app.documents.add)
1331
+ let exportDoc
1332
+ const makeDoc = async () => {
1333
+ let exportDoc = await app.documents.add({
1334
+ width: width,
1335
+ height: height,
1336
+ resolution: await app.activeDocument.resolution,
1337
+ mode: 'RGBColorMode',
1338
+ fill: 'transparent',
1339
+ })
1340
+ }
1341
+ let image_buffer
1342
+ await executeAsModal(
1343
+ async () => {
1344
+ // await app.documents.add()
1345
+ await makeDoc()
1346
+ exportDoc = app.activeDocument
1347
+
1348
+ console.log('exportDoc.id: ', exportDoc.id)
1349
+ // for (layer of layersToExport) {
1350
+
1351
+ console.log(layer.id)
1352
+ const dupLayer = await layer.duplicate(exportDoc)
1353
+ await selectLayers([dupLayer])
1354
+ // await selectLayerChannelCommand()
1355
+ await selectCanvasExe()
1356
+ const canvas_selection_info = await getSelectionInfoExe()
1357
+ await layerToSelection(canvas_selection_info)
1358
+ // const selection_info = await getSelectionInfoExe()
1359
+ // await exportDoc.crop(selection_info)
1360
+ // export_image_name = `${layer.name}.png`
1361
+ image_buffer = await readPng(image_name)
1362
+ await exportDoc.closeWithoutSaving()
1363
+ },
1364
+ { commandName: 'NewExportPng' }
1365
+ )
1366
+ return image_buffer
1367
+ // }
1368
+ } catch (e) {
1369
+ console.error(`newExportPng error: ,${e}`)
1370
+ }
1371
+ }
1372
+
1373
+ async function tempExportPng(layer, image_name, width, height) {
1374
+ //store layers we want to export in variables
1375
+ // let layerToExports =
1376
+ // create new document
1377
+ // duplicate the layers to the new documnet
1378
+ //select the layer channel selectLayerChannelCommand
1379
+ //document.crop
1380
+ //export using readPng()
1381
+
1382
+ try {
1383
+ //get the active layers
1384
+ // const layersToExport = app.activeDocument.activeLayers
1385
+
1386
+ //create new document
1387
+ // let exportDoc = await executeAsModal(app.documents.add)
1388
+ let exportDoc
1389
+ const makeDoc = async () => {
1390
+ let exportDoc = await app.documents.add({
1391
+ width: width,
1392
+ height: height,
1393
+ resolution: await app.activeDocument.resolution,
1394
+ mode: 'RGBColorMode',
1395
+ fill: 'transparent',
1396
+ })
1397
+ }
1398
+ await executeAsModal(
1399
+ async () => {
1400
+ // await app.documents.add()
1401
+ await makeDoc()
1402
+ exportDoc = app.activeDocument
1403
+
1404
+ console.log('exportDoc.id: ', exportDoc.id)
1405
+ // for (layer of layersToExport) {
1406
+
1407
+ console.log(layer.id)
1408
+ const dupLayer = await layer.duplicate(exportDoc)
1409
+ await selectLayers([dupLayer])
1410
+ // await selectLayerChannelCommand()
1411
+ await selectCanvasExe()
1412
+ const canvas_selection_info = await getSelectionInfoExe()
1413
+ await layerToSelection(canvas_selection_info)
1414
+ // const selection_info = await getSelectionInfoExe()
1415
+ // await exportDoc.crop(selection_info)
1416
+ // export_image_name = `${layer.name}.png`
1417
+ await readPng(image_name)
1418
+ await exportDoc.closeWithoutSaving()
1419
+ },
1420
+ { commandName: 'tempExportPng' }
1421
+ )
1422
+ // }
1423
+ } catch (e) {
1424
+ console.error(`newExportPng error: ,${e}`)
1425
+ }
1426
+ }
1427
+ async function mergeVisibleCommand() {
1428
+ const result = await batchPlay(
1429
+ [
1430
+ {
1431
+ _obj: 'mergeVisible',
1432
+ duplicate: true,
1433
+ _isCommand: true,
1434
+ // "_options": {
1435
+ // // "dialogOptions": "dontDisplay"
1436
+ // }
1437
+ },
1438
+ ],
1439
+ {
1440
+ synchronousExecution: true,
1441
+ modalBehavior: 'execute',
1442
+ }
1443
+ )
1444
+
1445
+ return result
1446
+ }
1447
+
1448
+ async function mergeVisibleExe() {
1449
+ await executeAsModal(async () => {
1450
+ await mergeVisibleCommand()
1451
+ })
1452
+ }
1453
+
1454
+ async function layerToSelection(selection_info) {
1455
+ //store active layer for later
1456
+
1457
+ try {
1458
+ //Store selection info
1459
+ //unSelect
1460
+ //move layer
1461
+ //scale layer
1462
+ //Select from selection info
1463
+ // let selection_info = await getSelectionInfo()
1464
+
1465
+ console.log('selection_info:', selection_info)
1466
+
1467
+ console.log('unSelect')
1468
+
1469
+ function getLayerSize(layer) {
1470
+ console.log('layer.bounds:')
1471
+ console.dir(layer.bounds)
1472
+ const bounds = layer.bounds
1473
+ const height = bounds.bottom - bounds.top
1474
+ const width = bounds.right - bounds.left
1475
+ return {
1476
+ height: height,
1477
+ width: width,
1478
+ left: bounds.left,
1479
+ right: bounds.right,
1480
+ top: bounds.top,
1481
+ bottom: bounds.bottom,
1482
+ }
1483
+ }
1484
+ //scale layer
1485
+ async function scaleLayer(layer, selection_info) {
1486
+ console.log('scaleLayer got called')
1487
+ // const activeLayer = getActiveLayer()
1488
+ // const activeLayer = await app.activeDocument.activeLayers[0]
1489
+
1490
+ let layer_info = getLayerSize(layer)
1491
+ scale_x_ratio = (selection_info.width / layer_info.width) * 100
1492
+ scale_y_ratio = (selection_info.height / layer_info.height) * 100
1493
+ console.log('scale_x_y_ratio:', scale_x_ratio, scale_y_ratio)
1494
+ await layer.scale(scale_x_ratio, scale_y_ratio)
1495
+ }
1496
+
1497
+ async function moveLayerExe(layerToMove, selection_info) {
1498
+ let layer_info = getLayerSize(layerToMove)
1499
+ top_dist = layer_info.top - selection_info.top
1500
+ left_dist = layer_info.left - selection_info.left
1501
+ await layerToMove.translate(-left_dist, -top_dist)
1502
+ }
1503
+ // const activeLayer = await getActiveLayer()
1504
+
1505
+ //store all active layers
1506
+ const activeLayers = await app.activeDocument.activeLayers
1507
+ await unSelectMarqueeExe()
1508
+ // await executeAsModal(unSelect, {'commandName': 'unSelect'})
1509
+ // await executeAsModal(scaleLayer, {'commandName': 'scaleLayer'})
1510
+
1511
+ await executeAsModal(
1512
+ async () => {
1513
+ for (let layer of activeLayers) {
1514
+ await selectLayers([layer]) // make sure only one layer is selected
1515
+ await scaleLayer(layer, selection_info) //scale to selection size
1516
+ await moveLayerExe(layer, selection_info) //move to selection
1517
+ }
1518
+ },
1519
+ { commandName: 'moveLayerExe' }
1520
+ )
1521
+
1522
+ // await reselect(selection_info)
1523
+ } catch (e) {
1524
+ console.warn(e)
1525
+ }
1526
+ }
1527
+ function executeCommandExe(commandFunc) {
1528
+ try {
1529
+ ;(async () => {
1530
+ await executeAsModal(async () => {
1531
+ await commandFunc()
1532
+ })
1533
+ })()
1534
+ } catch (e) {
1535
+ console.warn(e)
1536
+ }
1537
+ }
1538
+ async function executeDescExe(Desc) {
1539
+ try {
1540
+ await executeAsModal(async () => {
1541
+ const result = await batchPlay([Desc], {
1542
+ synchronousExecution: true,
1543
+ modalBehavior: 'execute',
1544
+ })
1545
+ console.log(result)
1546
+ })
1547
+ } catch (e) {
1548
+ console.warn(e)
1549
+ }
1550
+ }
1551
+ module.exports = {
1552
+ createSolidLayer,
1553
+ createEmptyGroup,
1554
+ getLayerIndex,
1555
+ collapseGroup,
1556
+ moveToGroupCommand,
1557
+ MoveToGroupExe,
1558
+ selectLayers,
1559
+ selectLayersExe,
1560
+ unselectActiveLayers,
1561
+ unselectActiveLayersExe,
1562
+ createMaskExe,
1563
+ getSelectionInfoExe,
1564
+ unSelectMarqueeCommand,
1565
+ unSelectMarqueeExe,
1566
+ reSelectMarqueeExe,
1567
+ selectLayerChannelCommand,
1568
+ snapshot_layer,
1569
+ snapshot_layerExe,
1570
+ fillAndGroupExe,
1571
+ fastSnapshot,
1572
+ setInitImage,
1573
+ setInitImageMask,
1574
+
1575
+ layerToFileName,
1576
+ layerNameToFileName,
1577
+ // cleanLayersOutpaint,
1578
+ // cleanLayersInpaint,
1579
+ // cleanSnapAndFill,
1580
+ cleanLayers,
1581
+ createClippingMaskExe,
1582
+ checkIfSelectionAreaIsActive,
1583
+ selectMarqueeRectangularToolExe,
1584
+ promptForMarqueeTool,
1585
+ saveUniqueDocumentIdExe,
1586
+ readUniqueDocumentIdExe,
1587
+ newExportPng,
1588
+ mergeVisibleExe,
1589
+ selectCanvasExe,
1590
+ layerToSelection,
1591
+ isSelectionValid,
1592
+ snapshot_layer_no_slide_Exe,
1593
+ setVisibleExe,
1594
+ silentSetInitImage,
1595
+ silentSetInitImageMask,
1596
+ executeCommandExe,
1597
+ executeDescExe,
1598
+ }
Auto-Photoshop-StableDiffusion-Plugin/requirements.txt ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ anyio==3.6.2
2
+ asyncio==3.4.3
3
+ certifi==2022.12.7
4
+ charset-normalizer==2.1.1
5
+ click==8.1.3
6
+ fastapi==0.88.0
7
+ h11==0.14.0
8
+ httpcore==0.16.3
9
+ httptools==0.5.0
10
+ httpx==0.23.1
11
+ idna==3.4
12
+ Pillow==9.3.0
13
+ pydantic==1.10.2
14
+ python-dotenv==0.21.0
15
+ PyYAML==6.0
16
+ requests==2.28.1
17
+ rfc3986==1.5.0
18
+ sniffio==1.3.0
19
+ starlette==0.22.0
20
+ typing_extensions==4.4.0
21
+ urllib3==1.26.13
22
+ uvicorn==0.20.0
23
+ # uvloop==0.17.0
24
+ watchfiles==0.18.1
25
+ websockets==10.4
26
+ duckduckgo_search==3.7.1
Auto-Photoshop-StableDiffusion-Plugin/scripts/__pycache__/main.cpython-310.pyc ADDED
Binary file (2.4 kB). View file
 
Auto-Photoshop-StableDiffusion-Plugin/scripts/__pycache__/test.cpython-310.pyc ADDED
Binary file (181 Bytes). View file
 
Auto-Photoshop-StableDiffusion-Plugin/scripts/main.py ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from modules import scripts, processing, shared, images, devices, ui, lowvram
2
+ import gradio
3
+ import requests
4
+ import time
5
+ import PIL.Image
6
+ import base64
7
+ import io
8
+ import os.path
9
+ import numpy
10
+ import itertools
11
+ import gradio as gr
12
+ import torch
13
+ from fastapi import FastAPI
14
+ from fastapi import APIRouter, Request
15
+ from fastapi.responses import StreamingResponse
16
+ from modules import script_callbacks, scripts, shared
17
+
18
+
19
+ import sys
20
+ python_server_dir = 'server/python_server'
21
+ extension_dir = scripts.basedir()
22
+ python_server_full_path = os.path.join(extension_dir,python_server_dir)
23
+ print("python_server_full_path: ",python_server_full_path)
24
+ sys.path.insert(0, python_server_full_path)
25
+ import search
26
+ import img2imgapi
27
+ import serverMain
28
+
29
+ router = APIRouter()
30
+
31
+ # @router.get("/config")
32
+ # async def get_state():
33
+ # print("hello get /config auto-photoshop-sd")
34
+ # res = "hello get /config auto-photoshop-sd"
35
+ # return {"res": res}
36
+
37
+ @router.post('/search/image/')
38
+ async def searchImage(request:Request):
39
+ try:
40
+ json = await request.json()
41
+ except:
42
+ json = {}
43
+
44
+
45
+ try:
46
+ keywords = json.get('keywords','cute cats')
47
+ images = await search.imageSearch(keywords)
48
+ print(images)
49
+
50
+
51
+ return {"images":images}
52
+ except:
53
+ print("keywords",keywords)
54
+ # print(f'{request}')
55
+ return {"error": "error message: can't preform an image search"}
56
+
57
+
58
+ @router.post('/mask/expansion/')
59
+ async def maskExpansionHandler(request:Request):
60
+ try:
61
+ json = await request.json()
62
+ except:
63
+ json = {}
64
+
65
+ # print("mask expansion json :",json)
66
+ try:
67
+ # keywords = json.get('keywords','cute dogs')
68
+ base64_mask_image = json['mask']
69
+ mask_expansion = json['mask_expansion']
70
+ #convert base64 to img
71
+
72
+ await img2imgapi.base64ToPng(base64_mask_image,"original_mask.png")#save a copy of the mask
73
+
74
+ mask_image = img2imgapi.b64_2_img(base64_mask_image)
75
+
76
+ expanded_mask_img = img2imgapi.maskExpansion(mask_image,mask_expansion)
77
+ base64_expanded_mask_image = img2imgapi.img_2_b64(expanded_mask_img)
78
+ await img2imgapi.base64ToPng(base64_expanded_mask_image,"expanded_mask.png")#save a copy of the mask
79
+
80
+
81
+ return {"mask":base64_expanded_mask_image}
82
+
83
+ except:
84
+ # print("request",request)
85
+ raise Exception(f"couldn't preform mask expansion",json)
86
+ # return response
87
+ return {"error": "error message: can't preform an mask expansion"}
88
+
89
+
90
+
91
+ def on_app_started(demo: gr.Blocks, app: FastAPI):
92
+ # print("hello on_app_started auto-photoshop-plugin")
93
+
94
+ if shared.cmd_opts.api:
95
+ app.include_router(serverMain.router, prefix="/sdapi/auto-photoshop-sd", tags=['Auto Photoshop SD Plugin API'])
96
+ # app.include_router(router, prefix="/sdapi/auto-photoshop-sd", tags=['Auto Photoshop SD Plugin API'])
97
+
98
+
99
+ else:
100
+ print("COMMANDLINE_ARGS does not contain --api, API won't be mounted.")
101
+
102
+ # logger.warning("COMMANDLINE_ARGS does not contain --api, API won't be mounted.")
103
+ # if you wanted to do anything massive to the UI, you could modify demo, but why?
104
+
105
+ script_callbacks.on_app_started(on_app_started)
Auto-Photoshop-StableDiffusion-Plugin/scripts/test.py ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ # import sys
2
+ # sys.path.insert(0, 'server/python_server')
3
+ # import search
4
+
5
+ # print("hello test.py")
Auto-Photoshop-StableDiffusion-Plugin/sdapi_py_re.js ADDED
@@ -0,0 +1,814 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const { getDummyBase64, getDummyBase64_2 } = require('./utility/dummy')
2
+ const { base64ToBase64Url } = require('./utility/general')
3
+ const { getExtensionType } = require('./utility/html_manip')
4
+ const py_re = require('./utility/sdapi/python_replacement')
5
+ const Enum = require('./enum')
6
+ const control_net = require('./utility/tab/control_net')
7
+ const api = require('./utility/api')
8
+ //javascript plugin can't read images from local directory so we send a request to local server to read the image file and send it back to plugin as image string base64
9
+
10
+ async function getInitImage(init_image_name) {
11
+ console.log('getInitImage(): get Init Image from the server :')
12
+ const payload = {
13
+ init_image_name: init_image_name,
14
+ }
15
+
16
+ // const full_url = 'http://127.0.0.1:8000/getInitImage/'
17
+ // console.log(full_url)
18
+ // console.log('getInitImage payload:', payload)
19
+ // let request = await fetch(full_url, {
20
+ // method: 'POST',
21
+ // headers: {
22
+ // Accept: 'application/json',
23
+ // 'Content-Type': 'application/json',
24
+ // },
25
+ // body: JSON.stringify(payload),
26
+ // // "body": payload
27
+ // })
28
+
29
+ // let json = await request.json()
30
+
31
+ // console.log('json:')
32
+ // console.dir(json)
33
+ // base64data = json.init_image_str
34
+ // image_src = `data:image/png;base64, ${base64data}`
35
+ console.warn('this function is deprecated!')
36
+ const image_src =
37
+ 'https://im ages.pexels.com/photos/1386604/pexels-photo-1386604.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1'
38
+ return image_src
39
+
40
+ // console.log(img.src)
41
+
42
+ // let img_blob = await (await fetch(img.src)).blob()
43
+ // console.log("img_blob:")
44
+ // console.dir(img_blob)
45
+ }
46
+ //REFACTOR: move this function to io.js
47
+ async function requestSavePng(base64_image, image_name) {
48
+ try {
49
+ console.log('requestSavePng():')
50
+
51
+ const uniqueDocumentId = await getUniqueDocumentId()
52
+ const folder = `${uniqueDocumentId}/init_images`
53
+ const init_entry = await getInitImagesDir()
54
+ saveFileInSubFolder(base64_image, folder, image_name)
55
+ console.warn('this function is deprecated')
56
+ } catch (e) {
57
+ console.warn(e)
58
+ return {}
59
+ }
60
+ }
61
+ async function requestTxt2Img(payload) {
62
+ try {
63
+ console.log('requestTxt2Img(): about to send a fetch request')
64
+
65
+ // const full_url = 'http://127.0.0.1:8000/txt2img/'
66
+ // console.log(full_url)
67
+
68
+ // let request = await fetch(full_url, {
69
+ // method: 'POST',
70
+ // headers: {
71
+ // Accept: 'application/json',
72
+ // 'Content-Type': 'application/json',
73
+ // },
74
+ // body: JSON.stringify(payload),
75
+ // // "body": payload
76
+ // })
77
+
78
+ // let json = await request.json()
79
+ let json = await py_re.txt2ImgRequest(payload)
80
+ console.log('requestTxt2Img json:', json)
81
+
82
+ return json
83
+ } catch (e) {
84
+ console.warn(e)
85
+ return {}
86
+ }
87
+ }
88
+
89
+ async function requestImg2Img(payload) {
90
+ console.log('requestImg2Img(): about to send a fetch request')
91
+ try {
92
+ // const full_url = 'http://127.0.0.1:8000/img2img/'
93
+ // console.log(full_url)
94
+ // console.log('requestImg2Img payload is: ', payload)
95
+ // let request = await fetch(full_url, {
96
+ // method: 'POST',
97
+ // headers: {
98
+ // Accept: 'application/json',
99
+ // 'Content-Type': 'application/json',
100
+ // },
101
+ // body: JSON.stringify(payload),
102
+ // // "body": payload
103
+ // })
104
+
105
+ // let json = await request.json()
106
+ let json = await py_re.img2ImgRequest(g_sd_url, payload)
107
+ console.log('requestImg2Img json:')
108
+ console.dir(json)
109
+
110
+ return json
111
+ } catch (e) {
112
+ console.warn(e)
113
+ return {}
114
+ }
115
+ }
116
+
117
+ async function requestProgress() {
118
+ let json = {}
119
+ try {
120
+ console.log('requestProgress: ')
121
+
122
+ const full_url = `${g_sd_url}/sdapi/v1/progress?skip_current_image=false`
123
+ let request = await fetch(full_url)
124
+ json = await request.json()
125
+ console.log('progress json:', json)
126
+
127
+ return json
128
+ } catch (e) {
129
+ console.warn(e)
130
+ // console.log('json: ', json)
131
+ }
132
+ }
133
+
134
+ async function requestGetModels() {
135
+ console.log('requestGetModels: ')
136
+ let json = []
137
+ const full_url = `${g_sd_url}/sdapi/v1/sd-models`
138
+ try {
139
+ let request = await fetch(full_url)
140
+ json = await request.json()
141
+ console.log('models json:')
142
+ console.dir(json)
143
+ } catch (e) {
144
+ console.warn(`issues requesting from ${full_url}`, e)
145
+ }
146
+ return json
147
+ }
148
+
149
+ async function requestGetSamplers() {
150
+ let json = null
151
+ try {
152
+ console.log('requestGetSamplers: ')
153
+
154
+ const full_url = `${g_sd_url}/sdapi/v1/samplers`
155
+ let request = await fetch(full_url)
156
+ json = await request.json()
157
+ console.log('samplers json:', json)
158
+ } catch (e) {
159
+ console.warn(e)
160
+ }
161
+ return json
162
+ }
163
+
164
+ async function requestSwapModel(model_title) {
165
+ console.log('requestSwapModel: ')
166
+ // const full_url = 'http://127.0.0.1:8000/swapModel'
167
+
168
+ const full_url = `${g_sd_url}/sdapi/v1/options`
169
+ payload = {
170
+ sd_model_checkpoint: model_title,
171
+ }
172
+ let request = await fetch(full_url, {
173
+ method: 'POST',
174
+ headers: {
175
+ Accept: 'application/json',
176
+ 'Content-Type': 'application/json',
177
+ },
178
+ body: JSON.stringify(payload),
179
+ // "body": payload
180
+ })
181
+
182
+ let json = await request.json()
183
+
184
+ console.log('models json:')
185
+ console.dir(json)
186
+
187
+ return json
188
+ }
189
+
190
+ async function requestInterrupt() {
191
+ const full_url = `${g_sd_url}/sdapi/v1/interrupt`
192
+ try {
193
+ console.log('requestInterrupt: ')
194
+
195
+ payload = ''
196
+ let request = await fetch(full_url, {
197
+ method: 'POST',
198
+ headers: {
199
+ Accept: 'application/json',
200
+ 'Content-Type': 'application/json',
201
+ },
202
+ // body: JSON.stringify(payload)
203
+ // "body": payload
204
+ })
205
+
206
+ console.log('interrupt request:', request)
207
+ let json = await request.json()
208
+
209
+ return json
210
+ } catch (e) {
211
+ console.warn(e)
212
+ }
213
+ }
214
+
215
+ async function getVersionRequest() {
216
+ // version = "v0.0.0"
217
+ console.log('requestGetSamplers: ')
218
+ const current_version = g_version
219
+ // try {
220
+ // const full_url = 'http://127.0.0.1:8000/version'
221
+ // let request = await fetch(full_url)
222
+ // let json = await request.json()
223
+ // console.log('version json:', json)
224
+ // version = json['version']
225
+
226
+ // return version
227
+ // } catch (e) {
228
+ // console.warn(e)
229
+ // version = 'v0.0.0'
230
+
231
+ // return version
232
+ // }
233
+ return current_version
234
+ }
235
+
236
+ async function changeSdUrl(new_sd_url) {
237
+ // version = "v0.0.0"
238
+ console.log('changeSdUrl: new_sd_url:', new_sd_url)
239
+ try {
240
+ payload = {
241
+ sd_url: new_sd_url,
242
+ }
243
+
244
+ // const full_url = `${g_sd_url}/sd_url/`
245
+ // console.log('changeSdUrl: payload: ', payload)
246
+ // let request = await fetch(full_url, {
247
+ // method: 'POST',
248
+ // headers: {
249
+ // Accept: 'application/json',
250
+ // 'Content-Type': 'application/json',
251
+ // },
252
+ // body: JSON.stringify(payload),
253
+ // })
254
+
255
+ g_sd_url = new_sd_url
256
+ // console.log('changeSdUrl: request: ', request)
257
+ } catch (e) {
258
+ console.warn(e)
259
+ }
260
+ }
261
+
262
+ // function printTheJSONInPrettyFormat(json) {
263
+ // // var badJSON = document.getElementById('prettyJSONFormat').value;
264
+ // // var parseJSON = JSON.parse(badJSON);
265
+ // // var JSONInPrettyFormat = JSON.stringify(json, undefined, 4);
266
+ // // return
267
+ // }
268
+ async function loadHistory(uniqueDocumentId) {
269
+ let json = {}
270
+ try {
271
+ payload = {
272
+ uniqueDocumentId: uniqueDocumentId,
273
+ }
274
+ json = await py_re.loadHistory(payload)
275
+ // const full_url = 'http://127.0.0.1:8000/history/load'
276
+
277
+ // let request = await fetch(full_url, {
278
+ // method: 'POST',
279
+ // headers: {
280
+ // Accept: 'application/json',
281
+ // 'Content-Type': 'application/json',
282
+ // },
283
+ // body: JSON.stringify(payload),
284
+ // })
285
+
286
+ // json = await request.json()
287
+ // console.log('loadHistory:', json)
288
+
289
+ // console.log('loadPromptShortcut: request: ',request)
290
+ } catch (e) {
291
+ console.warn(e)
292
+ }
293
+
294
+ return [json['image_paths'], json['metadata_jsons'], json['base64_images']]
295
+ }
296
+ async function loadPromptShortcut() {
297
+ // console.log('loadPromptShortcut:')
298
+ let prompt_shortcut_json = {}
299
+ try {
300
+ // payload = {}
301
+
302
+ // const full_url = 'http://127.0.0.1:8000/prompt_shortcut/load'
303
+
304
+ // let request = await fetch(full_url, {
305
+ // method: 'POST',
306
+ // headers: {
307
+ // Accept: 'application/json',
308
+ // 'Content-Type': 'application/json',
309
+ // },
310
+ // body: JSON.stringify(payload),
311
+ // })
312
+
313
+ // json = await request.json()
314
+ prompt_shortcut_json = await py_re.loadPromptShortcut(
315
+ 'prompt_shortcut.json'
316
+ )
317
+ console.log('loadPromptShortcut:', prompt_shortcut_json)
318
+ // console.log('loadPromptShortcut: request: ',request)
319
+ } catch (e) {
320
+ console.warn(e)
321
+ prompt_shortcut_json = {}
322
+ }
323
+ return prompt_shortcut_json
324
+ // return json['prompt_shortcut']
325
+ }
326
+
327
+ async function savePromptShortcut(prompt_shortcut) {
328
+ // console.log('loadPromptShortcut:')
329
+ let json = prompt_shortcut
330
+ try {
331
+ // payload = { prompt_shortcut: prompt_shortcut }
332
+
333
+ // const full_url = 'http://127.0.0.1:8000/prompt_shortcut/save'
334
+
335
+ // let request = await fetch(full_url, {
336
+ // method: 'POST',
337
+ // headers: {
338
+ // Accept: 'application/json',
339
+ // 'Content-Type': 'application/json',
340
+ // },
341
+ // body: JSON.stringify(payload),
342
+ // })
343
+
344
+ // json = await request.json()
345
+ await py_re.savePromptShortcut(json, 'prompt_shortcut.json')
346
+ console.log('savePromptShortcut:', json)
347
+ // console.log('loadPromptShortcut: request: ',request)
348
+ } catch (e) {
349
+ console.warn(e)
350
+ }
351
+
352
+ return json['prompt_shortcut']
353
+ }
354
+ async function setInpaintMaskWeight(value) {
355
+ const full_url = `${g_sd_url}/sdapi/v1/options`
356
+ try {
357
+ const payload = {
358
+ inpainting_mask_weight: value,
359
+ }
360
+ await fetch(full_url, {
361
+ method: 'POST',
362
+ headers: {
363
+ Accept: 'application/json',
364
+ 'Content-Type': 'application/json',
365
+ },
366
+ body: JSON.stringify(payload),
367
+ })
368
+ } catch (e) {
369
+ console.warn(e)
370
+ }
371
+ }
372
+
373
+ async function requestGetConfig() {
374
+ console.log('requestGetConfig: ')
375
+ let json = []
376
+ const full_url = `${g_sd_url}/config`
377
+ try {
378
+ let request = await fetch(full_url)
379
+ json = await request.json()
380
+ console.log('models json:')
381
+ console.dir(json)
382
+ } catch (e) {
383
+ console.warn(`issues requesting from ${full_url}`, e)
384
+ }
385
+ return json
386
+ }
387
+ async function requestGetOptions() {
388
+ console.log('requestGetOptions: ')
389
+ let json = null
390
+ const full_url = `${g_sd_url}/sdapi/v1/options`
391
+ try {
392
+ let request = await fetch(full_url)
393
+ if (request.status === 404) {
394
+ return null
395
+ }
396
+
397
+ json = await request.json()
398
+ console.log('models json:')
399
+ console.dir(json)
400
+ } catch (e) {
401
+ console.warn(`issues requesting from ${full_url}`, e)
402
+ }
403
+ return json
404
+ }
405
+
406
+ async function imageSearch(keywords) {
407
+ let json = {}
408
+ const extension_url = py_re.getExtensionUrl()
409
+
410
+ const full_url = `${extension_url}/search/image/`
411
+ try {
412
+ payload = {
413
+ keywords: keywords,
414
+ }
415
+
416
+ let request = await fetch(full_url, {
417
+ method: 'POST',
418
+ headers: {
419
+ Accept: 'application/json',
420
+ 'Content-Type': 'application/json',
421
+ },
422
+ body: JSON.stringify(payload),
423
+ })
424
+
425
+ json = await request.json()
426
+ console.log('imageSearch:', json)
427
+
428
+ return json['images']
429
+ } catch (e) {
430
+ console.warn(e)
431
+ }
432
+ return []
433
+ }
434
+
435
+ // async function requestHorde(payload) {
436
+ // payload = {
437
+ // prompt: 'string',
438
+ // params: {
439
+ // sampler_name: 'k_lms',
440
+ // toggles: [1, 4],
441
+ // cfg_scale: 5,
442
+ // denoising_strength: 0.75,
443
+ // seed: 'string',
444
+ // height: 512,
445
+ // width: 512,
446
+ // seed_variation: 1,
447
+ // post_processing: ['GFPGAN'],
448
+ // karras: false,
449
+ // tiling: false,
450
+ // steps: 30,
451
+ // n: 1,
452
+ // },
453
+ // nsfw: false,
454
+ // trusted_workers: true,
455
+ // censor_nsfw: false,
456
+ // workers: ['4c79ab19-8e6c-4054-83b3-773b7ce71ece'],
457
+ // models: ['stable_diffusion'],
458
+ // // source_image: 'string',
459
+ // // source_processing: 'img2img',
460
+ // // source_mask: 'string',
461
+ // r2: true,
462
+ // shared: false,
463
+ // }
464
+ // try {
465
+ // console.log('requestHorde():')
466
+
467
+ // const full_url = 'https://stablehorde.net/api/v2/generate/async'
468
+ // // const full_url = 'https://stablehorde.net/api/v2/generate/sync'
469
+ // console.log(full_url)
470
+
471
+ // let request = await fetch(full_url, {
472
+ // method: 'POST',
473
+ // headers: {
474
+ // Accept: 'application/json',
475
+ // 'Content-Type': 'application/json',
476
+ // apikey: '0000000000',
477
+ // // 'Client-Agent': '4c79ab19-8e6c-4054-83b3-773b7ce71ece',
478
+ // 'Client-Agent': 'unknown:0:unknown',
479
+ // },
480
+ // body: JSON.stringify(payload),
481
+ // })
482
+
483
+ // let json = await request.json()
484
+ // console.log('requestHorde json:', json)
485
+
486
+ // return json
487
+ // } catch (e) {
488
+ // console.warn(e)
489
+ // return {}
490
+ // }
491
+ // }
492
+ // async function requestHordeCheck(id) {
493
+ // try {
494
+ // console.log('requestHordeCheck():')
495
+ // const base_url = 'https://stablehorde.net/api/v2/generate/check'
496
+
497
+ // const full_url = `${base_url}/${id}`
498
+ // // const full_url = 'https://stablehorde.net/api/v2/generate/sync'
499
+ // console.log(full_url)
500
+ // const payload = {}
501
+ // let request = await fetch(full_url, {
502
+ // method: 'GET',
503
+ // headers: {
504
+ // Accept: 'application/json',
505
+ // 'Content-Type': 'application/json',
506
+ // // 'Client-Agent': '4c79ab19-8e6c-4054-83b3-773b7ce71ece',
507
+ // 'Client-Agent': 'unknown:0:unknown',
508
+ // },
509
+ // })
510
+
511
+ // let json = await request.json()
512
+ // console.log('requestHordeCheck json:', json)
513
+
514
+ // return json
515
+ // } catch (e) {
516
+ // console.warn(e)
517
+ // return {}
518
+ // }
519
+ // }
520
+
521
+ // async function requestHordeStatus(id) {
522
+ // try {
523
+ // console.log('requestHordeStatus():')
524
+ // const base_url = 'https://stablehorde.net/api/v2/generate/status'
525
+
526
+ // const full_url = `${base_url}/${id}`
527
+ // // const full_url = 'https://stablehorde.net/api/v2/generate/sync'
528
+ // console.log(full_url)
529
+ // const payload = {}
530
+ // let request = await fetch(full_url, {
531
+ // method: 'GET',
532
+ // headers: {
533
+ // Accept: 'application/json',
534
+ // 'Content-Type': 'application/json',
535
+ // // 'Client-Agent': '4c79ab19-8e6c-4054-83b3-773b7ce71ece',
536
+ // 'Client-Agent': 'unknown:0:unknown',
537
+ // },
538
+ // })
539
+
540
+ // let json = await request.json()
541
+ // console.log('requestHordeStatus json:', json)
542
+
543
+ // return json
544
+ // } catch (e) {
545
+ // console.warn(e)
546
+ // return {}
547
+ // }
548
+ // }
549
+
550
+ async function requestExtraSingleImage(payload) {
551
+ console.log('requestExtraSingleImage(): about to send a fetch request')
552
+ try {
553
+ let json = await py_re.extraSingleImageRequest(g_sd_url, payload)
554
+ console.log('requestExtraSingleImage json:')
555
+ console.dir(json)
556
+
557
+ return json
558
+ } catch (e) {
559
+ console.warn(e)
560
+ return {}
561
+ }
562
+ }
563
+
564
+ async function requestGetUpscalers() {
565
+ console.log('requestGetUpscalers: ')
566
+ let json = []
567
+ const full_url = `${g_sd_url}/sdapi/v1/upscalers`
568
+ try {
569
+ let request = await fetch(full_url)
570
+ json = await request.json()
571
+ console.log('upscalers json:')
572
+ console.dir(json)
573
+ } catch (e) {
574
+ console.warn(`issues requesting from ${full_url}`, e)
575
+ }
576
+ return json
577
+ }
578
+
579
+ //REFACTOR: reuse the same code for (requestControlNetTxt2Img,requestControlNetImg2Img)
580
+ async function requestControlNetTxt2Img(plugin_settings) {
581
+ console.log('requestControlNetTxt2Img: ')
582
+
583
+ // const full_url = `${g_sd_url}/controlnet/txt2img`
584
+ const full_url = `${g_sd_url}/sdapi/v1/txt2img`
585
+ // debugger
586
+ const control_net_settings =
587
+ control_net.mapPluginSettingsToControlNet(plugin_settings)
588
+ let control_networks = []
589
+ // let active_control_networks = 0
590
+ for (let index = 0; index < g_controlnet_max_models; index++) {
591
+ if (!control_net.getEnableControlNet(index)) {
592
+ control_networks[index] = false
593
+ continue
594
+ }
595
+ control_networks[index] = true
596
+ // debugger
597
+ if (!control_net_settings['controlnet_units'][index]['input_image']) {
598
+ app.showAlert('you need to add a valid ControlNet input image')
599
+ throw 'you need to add a valid ControlNet input image'
600
+ }
601
+
602
+ if (!control_net_settings['controlnet_units'][index]['module']) {
603
+ app.showAlert('you need to select a valid ControlNet Module')
604
+ throw 'you need to select a valid ControlNet Module'
605
+ }
606
+ if (
607
+ !control_net_settings['controlnet_units'][index]['model'] &&
608
+ !control_net.getModuleDetail()[
609
+ control_net_settings['controlnet_units'][index]['module']
610
+ ].model_free
611
+ ) {
612
+ app.showAlert('you need to select a valid ControlNet Model')
613
+ throw 'you need to select a valid ControlNet Model'
614
+ }
615
+ // active_control_networks++
616
+ }
617
+
618
+ let request = await fetch(full_url, {
619
+ method: 'POST',
620
+ headers: {
621
+ Accept: 'application/json',
622
+ 'Content-Type': 'application/json',
623
+ },
624
+ body: JSON.stringify(control_net_settings),
625
+ })
626
+
627
+ let json = await request.json()
628
+ console.log('json:', json)
629
+
630
+ //update the mask in controlNet tab
631
+ const numOfImages = json['images'].length
632
+ let numberOfAnnotations =
633
+ numOfImages - g_generation_session.last_settings.batch_size
634
+ if (numberOfAnnotations < 0) numberOfAnnotations = 0
635
+
636
+ const base64_mask = json['images'].slice(numOfImages - numberOfAnnotations)
637
+
638
+ let mask_index = 0
639
+
640
+ for (let index = 0; index < control_networks.length; index++) {
641
+ if (
642
+ control_networks[index] == false ||
643
+ mask_index >= numberOfAnnotations
644
+ )
645
+ continue
646
+ html_manip.setControlMaskSrc(
647
+ base64ToBase64Url(base64_mask[mask_index]),
648
+ index
649
+ )
650
+ g_generation_session.controlNetMask[index] = base64_mask[mask_index]
651
+ mask_index++
652
+ }
653
+ // g_generation_session.controlNetMask = base64_mask
654
+
655
+ const standard_response = await py_re.convertToStandardResponse(
656
+ control_net_settings,
657
+ json['images'].slice(0, numOfImages - numberOfAnnotations),
658
+ plugin_settings['uniqueDocumentId']
659
+ )
660
+ console.log('standard_response:', standard_response)
661
+
662
+ return standard_response
663
+ }
664
+
665
+ //REFACTOR: reuse the same code for (requestControlNetTxt2Img,requestControlNetImg2Img)
666
+ async function requestControlNetImg2Img(plugin_settings) {
667
+ console.log('requestControlNetImg2Img: ')
668
+ // const full_url = 'http://127.0.0.1:8000/swapModel'
669
+
670
+ // const full_url = `${g_sd_url}/controlnet/img2img`
671
+ const full_url = `${g_sd_url}/sdapi/v1/img2img`
672
+ const control_net_settings =
673
+ control_net.mapPluginSettingsToControlNet(plugin_settings)
674
+
675
+ // let control_networks = 0
676
+ let control_networks = []
677
+ for (let index = 0; index < g_controlnet_max_models; index++) {
678
+ if (!control_net.getEnableControlNet(index)) {
679
+ control_networks[index] = false
680
+ continue
681
+ }
682
+ control_networks[index] = true
683
+ if (!control_net_settings['controlnet_units'][index]['input_image']) {
684
+ app.showAlert('you need to add a valid ControlNet input image')
685
+ throw 'you need to add a valid ControlNet input image'
686
+ }
687
+
688
+ if (!control_net_settings['controlnet_units'][index]['module']) {
689
+ app.showAlert('you need to select a valid ControlNet Module')
690
+ throw 'you need to select a valid ControlNet Module'
691
+ }
692
+ if (
693
+ !control_net_settings['controlnet_units'][index]['model'] &&
694
+ !control_net.getModuleDetail()[
695
+ control_net_settings['controlnet_units'][index]['module']
696
+ ].model_free
697
+ ) {
698
+ app.showAlert('you need to select a valid ControlNet Model')
699
+ throw 'you need to select a valid ControlNet Model'
700
+ }
701
+ }
702
+
703
+ let request = await fetch(full_url, {
704
+ method: 'POST',
705
+ headers: {
706
+ Accept: 'application/json',
707
+ 'Content-Type': 'application/json',
708
+ },
709
+ body: JSON.stringify(control_net_settings),
710
+ // body: JSON.stringify(payload),
711
+ })
712
+
713
+ let json = await request.json()
714
+ console.log('json:', json)
715
+
716
+ //update the mask in controlNet tab
717
+ const numOfImages = json['images'].length
718
+ let numberOfAnnotations =
719
+ numOfImages - g_generation_session.last_settings.batch_size
720
+ if (numberOfAnnotations < 0) numberOfAnnotations = 0
721
+
722
+ // To fix a bug: when Ultimate SD Upscale is active and running, the detection maps won’t be retrieved.
723
+ // So set its value to 0 to avoid the result images being loaded in the annotation map interface.
724
+ if (
725
+ scripts.script_store.is_active &&
726
+ scripts.script_store.selected_script_name !== 'None' &&
727
+ scripts.script_store.is_selected_script_available
728
+ ) {
729
+ numberOfAnnotations = 0
730
+ }
731
+ const base64_mask = json['images'].slice(numOfImages - numberOfAnnotations)
732
+
733
+ let mask_index = 0
734
+ for (let index = 0; index < control_networks.length; index++) {
735
+ if (
736
+ control_networks[index] == false ||
737
+ mask_index >= numberOfAnnotations
738
+ )
739
+ continue
740
+ html_manip.setControlMaskSrc(
741
+ base64ToBase64Url(base64_mask[mask_index]),
742
+ index
743
+ )
744
+ g_generation_session.controlNetMask[index] = base64_mask[mask_index]
745
+ mask_index++
746
+ }
747
+
748
+ // g_generation_session.controlNetMask = base64_mask
749
+
750
+ const standard_response = await py_re.convertToStandardResponse(
751
+ control_net_settings,
752
+ json['images'].slice(0, numOfImages - numberOfAnnotations),
753
+ plugin_settings['uniqueDocumentId']
754
+ )
755
+ console.log('standard_response:', standard_response)
756
+
757
+ // //get all images except last because it's the mask
758
+ // for (const image of json['images'].slice(0, -1)) {
759
+ // await io.IO.base64ToLayer(image)
760
+ // }
761
+
762
+ return standard_response
763
+ }
764
+
765
+ async function isWebuiRunning() {
766
+ console.log('isWebuiRunning: ')
767
+ let json = []
768
+ const full_url = `${g_sd_url}/user`
769
+ try {
770
+ let request = await fetch(full_url)
771
+ json = await request.json()
772
+ console.log('json:')
773
+ console.dir(json)
774
+ } catch (e) {
775
+ console.warn(`issues requesting from ${full_url}`, e)
776
+ return false
777
+ }
778
+ return true
779
+ }
780
+ async function requestLoraModels() {
781
+ const extension_url = py_re.getExtensionUrl()
782
+ const full_url = `${extension_url}/lora/list`
783
+ const lora_models = await api.requestGet(full_url)
784
+ return lora_models
785
+ }
786
+ module.exports = {
787
+ requestTxt2Img,
788
+ requestImg2Img,
789
+ getInitImage,
790
+ requestProgress,
791
+ requestGetModels,
792
+ requestSwapModel,
793
+ requestInterrupt,
794
+ requestGetSamplers,
795
+ getVersionRequest,
796
+ changeSdUrl,
797
+ loadPromptShortcut,
798
+ savePromptShortcut,
799
+ loadHistory,
800
+ setInpaintMaskWeight,
801
+ requestGetConfig,
802
+ requestGetOptions,
803
+ imageSearch,
804
+ requestSavePng,
805
+ // requestHorde,
806
+ // requestHordeCheck,
807
+ // requestHordeStatus,
808
+ requestExtraSingleImage,
809
+ requestGetUpscalers,
810
+ requestControlNetTxt2Img,
811
+ requestControlNetImg2Img,
812
+ isWebuiRunning,
813
+ requestLoraModels,
814
+ }
Auto-Photoshop-StableDiffusion-Plugin/selection.js ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const psapi = require('./psapi')
2
+ const html_manip = require('./utility/html_manip')
3
+ function finalWidthHeight(
4
+ selectionWidth,
5
+ selectionHeight,
6
+ minWidth,
7
+ minHeight
8
+ ) {
9
+ // const minWidth = 512
10
+ // const minHeight = 512
11
+
12
+ // const selectionWidth = 256
13
+ // const selectionHeight = 1000
14
+
15
+ let finalWidth = 0
16
+ let finalHeight = 0
17
+
18
+ if (selectionWidth <= selectionHeight) {
19
+ //do operation on the smaller dimension
20
+ const scaleRatio = selectionWidth / minWidth
21
+
22
+ finalWidth = minWidth
23
+ finalHeight = selectionHeight / scaleRatio
24
+ } else {
25
+ const scaleRatio = selectionHeight / minHeight
26
+
27
+ finalHeight = minHeight
28
+ finalWidth = selectionWidth / scaleRatio
29
+ }
30
+ return [finalWidth, finalHeight]
31
+ }
32
+
33
+ async function selectionToFinalWidthHeight() {
34
+ // const { getSelectionInfoExe } = require('./psapi')
35
+ try {
36
+ const selectionInfo = await psapi.getSelectionInfoExe()
37
+ const [finalWidth, finalHeight] = finalWidthHeight(
38
+ selectionInfo.width,
39
+ selectionInfo.height,
40
+ 512,
41
+ 512
42
+ )
43
+
44
+ return [
45
+ parseInt(finalWidth),
46
+ parseInt(finalHeight),
47
+ selectionInfo.width,
48
+ selectionInfo.height,
49
+ ]
50
+ } catch (e) {
51
+ console.warn('you need a rectangular selection', e)
52
+ }
53
+ }
54
+
55
+ async function selectBoundingBox() {
56
+ let l = await app.activeDocument.activeLayers[0]
57
+ let bounds = await l.boundsNoEffects
58
+ let selectionInfo = convertSelectionObjectToSelectionInfo(bounds)
59
+ await psapi.reSelectMarqueeExe(selectionInfo)
60
+ return selectionInfo
61
+ }
62
+ function convertSelectionObjectToSelectionInfo(selection_obj) {
63
+ let selection_info = {
64
+ left: selection_obj._left,
65
+ right: selection_obj._right,
66
+ bottom: selection_obj._bottom,
67
+ top: selection_obj._top,
68
+ height: selection_obj._bottom - selection_obj._top,
69
+ width: selection_obj._right - selection_obj._left,
70
+ }
71
+ return selection_info
72
+ }
73
+
74
+ const SelectionInfoDesc = () => ({
75
+ _obj: 'get',
76
+ _target: [
77
+ {
78
+ _property: 'selection',
79
+ },
80
+ {
81
+ _ref: 'document',
82
+ _id: app.activeDocument._id,
83
+ },
84
+ ],
85
+ _options: {
86
+ dialogOptions: 'dontDisplay',
87
+ },
88
+ })
89
+ class Selection {
90
+ static async getSelectionInfoExe() {
91
+ //return a selectionInfo object or undefined
92
+ try {
93
+ const selection = await executeAsModal(async () => {
94
+ const result = await batchPlay([SelectionInfoDesc()], {
95
+ synchronousExecution: true,
96
+ modalBehavior: 'execute',
97
+ })
98
+
99
+ return result[0]?.selection
100
+ })
101
+
102
+ if (this.isSelectionValid(selection)) {
103
+ let selection_info = {
104
+ left: selection.left._value,
105
+ right: selection.right._value,
106
+ bottom: selection.bottom._value,
107
+ top: selection.top._value,
108
+ height: selection.bottom._value - selection.top._value,
109
+ width: selection.right._value - selection.left._value,
110
+ }
111
+ // console.dir({selection_info})
112
+ return selection_info
113
+ }
114
+ } catch (e) {
115
+ console.warn('selection info error', e)
116
+ }
117
+ }
118
+
119
+ static isSelectionValid(selection) {
120
+ console.warn(
121
+ 'isSelectionValid is deprecated use selection.isSelectionValid instead'
122
+ )
123
+ if (
124
+ selection && // check if the selection is defined
125
+ selection.hasOwnProperty('left') &&
126
+ selection.hasOwnProperty('right') &&
127
+ selection.hasOwnProperty('top') &&
128
+ selection.hasOwnProperty('bottom')
129
+ ) {
130
+ return true
131
+ }
132
+
133
+ return false
134
+ }
135
+ static reselectArea(selection_info) {}
136
+ static isSameSelection(selection_info_1, selection_info_2) {}
137
+ static async getImageToSelectionDifference() {
138
+ const selectionInfo = await psapi.getSelectionInfoExe()
139
+
140
+ const width = html_manip.getWidth()
141
+ const height = html_manip.getHeight()
142
+ const scale_info_str = `${parseInt(width)}x${parseInt(
143
+ height
144
+ )} => ${parseInt(selectionInfo.width)}x${parseInt(
145
+ selectionInfo.height
146
+ )} `
147
+ let ratio =
148
+ (width * height) / (selectionInfo.width * selectionInfo.height)
149
+
150
+ // const arrow = percentage >= 1 ? '↑' : '↓'
151
+ // percentage = percentage >= 1 ? percentage : 1 / percentage
152
+
153
+ // const percentage_str = `${arrow}X${percentage.toFixed(2)}`
154
+
155
+ // console.log('scale_info_str: ', scale_info_str)
156
+ // console.log('percentage_str: ', percentage_str)
157
+ return ratio
158
+ }
159
+ static {}
160
+ }
161
+ module.exports = {
162
+ finalWidthHeight,
163
+ selectionToFinalWidthHeight,
164
+ selectBoundingBox,
165
+ convertSelectionObjectToSelectionInfo,
166
+ Selection,
167
+ }
Auto-Photoshop-StableDiffusion-Plugin/server/python_server/__pycache__/img2imgapi.cpython-310.pyc ADDED
Binary file (4.1 kB). View file
 
Auto-Photoshop-StableDiffusion-Plugin/server/python_server/__pycache__/metadata_to_json.cpython-310.pyc ADDED
Binary file (1.93 kB). View file
 
Auto-Photoshop-StableDiffusion-Plugin/server/python_server/__pycache__/prompt_shortcut.cpython-310.pyc ADDED
Binary file (2.02 kB). View file
 
Auto-Photoshop-StableDiffusion-Plugin/server/python_server/__pycache__/search.cpython-310.pyc ADDED
Binary file (1.03 kB). View file
 
Auto-Photoshop-StableDiffusion-Plugin/server/python_server/__pycache__/serverHelper.cpython-310.pyc ADDED
Binary file (1.82 kB). View file
 
Auto-Photoshop-StableDiffusion-Plugin/server/python_server/__pycache__/serverMain.cpython-310.pyc ADDED
Binary file (10 kB). View file
 
Auto-Photoshop-StableDiffusion-Plugin/server/python_server/control_net.py ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ # controlnet original + txt2img
3
+ import requests
4
+ import cv2
5
+ import numpy as np
6
+ from base64 import b64encode , b64decode
7
+ from PIL import Image
8
+ import io
9
+
10
+ def readImage(path):
11
+ img = cv2.imread(path)
12
+ retval, buffer = cv2.imencode('.jpg', img)
13
+ b64img = b64encode(buffer).decode("utf-8")
14
+ return b64img
15
+
16
+ def readb64(uri):
17
+ nparr = np.fromstring(b64decode(uri), np.uint8)
18
+ img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
19
+ return img
20
+
21
+ b64img = readImage("output_image.png")
22
+
23
+ class controlnetRequest():
24
+ def __init__(self, prompt):
25
+ self.url = "http://127.0.0.1:7860/controlnet/txt2img" #openpose
26
+ self.body = {
27
+ "prompt": prompt,
28
+ "negative_prompt": "",
29
+ "seed": -1,
30
+ "subseed": -1,
31
+ "subseed_strength": 0,
32
+ "batch_size": 1,
33
+ "n_iter": 1,
34
+ "steps": 30,
35
+ "cfg_scale": 14,
36
+ "width": 512,
37
+ "height": 512,
38
+ "restore_faces": True,
39
+ "eta": 0,
40
+ "sampler_index": "DDIM",
41
+ "controlnet_model": "Test_ziva",
42
+ "controlnet_input_image": [b64img],
43
+ "controlnet_module": 'depth',
44
+ "ControlNet Weight": 1,
45
+ "controlnet_model": 'control_sd15_depth [fef5e48e]',
46
+ "controlnet_guidance": 1
47
+ }
48
+
49
+ def sendRequest(self):
50
+ # print(self.simple_txt2img)
51
+ r = requests.post(self.url, json=self.body)
52
+ print(r)
53
+ return r.json()
54
+
55
+ js = controlnetRequest("clothed busty bird").sendRequest()
56
+
57
+
58
+ for x,i in enumerate(js['images']):
59
+ image = Image.open(io.BytesIO(b64decode(i.split(",",1)[0])))
60
+ image.save(str(x)+'output.png')
61
+
62
+
63
+
64
+ len(js['images'])
65
+ print(js)
Auto-Photoshop-StableDiffusion-Plugin/server/python_server/img2imgapi.py ADDED
@@ -0,0 +1,163 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import requests
3
+ import io
4
+ import base64
5
+ from PIL import Image, PngImagePlugin
6
+ # from serverMain import sd_url
7
+ import asyncio
8
+ import httpx
9
+
10
+
11
+ from io import BytesIO
12
+ import prompt_shortcut
13
+
14
+ # Convert Image to Base64
15
+ def img_2_b64(image):
16
+ buff = BytesIO()
17
+ image.save(buff, format="PNG")
18
+ img_byte = base64.b64encode(buff.getvalue())
19
+ img_str = img_byte.decode("utf-8")
20
+ return img_str
21
+
22
+ import time
23
+ import serverHelper
24
+ import metadata_to_json
25
+
26
+ def b64_2_img(base64_image):
27
+ image = Image.open(io.BytesIO(base64.b64decode(base64_image.split(",",1)[0])))
28
+ return image
29
+
30
+ def reserveBorderPixels(img,dilation_img):
31
+ pixels = img.load() # this is not a list, nor is it list()'able
32
+ width, height = img.size
33
+ dilation_pixels = dilation_img.load()
34
+ all_pixels = []
35
+ depth = 20 # five pixel depth
36
+ for x in range(width):
37
+ for d in range(depth):
38
+ dilation_pixels[x,d] = pixels[x, d]
39
+ dilation_pixels[x,height-(d+1)] = pixels[x, height-(d+1)]
40
+ # all_pixels.append(cpixel)
41
+ for y in range(height):
42
+ for d in range(depth):
43
+ dilation_pixels[d,y] = pixels[d,y] # d = 0
44
+ dilation_pixels[width-(d+1),y] = pixels[width-(d+1), y]
45
+ return dilation_img
46
+
47
+ def maskExpansion(mask_img,mask_expansion):
48
+ #only if image exist then try to open it
49
+
50
+
51
+ # init_img_mask = Image.open(f"{init_img_dir}/{init_img_mask_name}")
52
+
53
+ # if(payload['use_sharp_mask'] == False):# use blurry mask
54
+ iteration = mask_expansion
55
+ dilated_img = applyDilation(mask_img,iteration)
56
+ mask_with_border = reserveBorderPixels(mask_img,dilated_img)
57
+ mask_with_border = mask_with_border.filter(ImageFilter.GaussianBlur(radius = 10))
58
+ return mask_with_border
59
+
60
+ async def base64ToPng(base64_image,image_path):
61
+ base64_img_bytes = base64_image.encode('utf-8')
62
+ with open(image_path, 'wb') as file_to_save:
63
+ decoded_image_data = base64.decodebytes(base64_img_bytes)
64
+ file_to_save.write(decoded_image_data)
65
+
66
+
67
+
68
+
69
+ from PIL import Image, ImageFilter
70
+ def applyDilation(img,iteration=20,max_filter=3):
71
+ # img = Image.open("test_image_2.png")
72
+ dilation_img = img.copy()
73
+ # for i in range(20):
74
+ # dilation_img = dilation_img.filter(ImageFilter.MaxFilter(3))
75
+ for i in range(iteration):
76
+ dilation_img = dilation_img.filter(ImageFilter.MaxFilter(max_filter))
77
+ return dilation_img
78
+
79
+
80
+
81
+ async def img2ImgRequest(sd_url,payload):
82
+ # init_img = Image.open(r"C:/Users/abdul/Desktop/photoshop_plugins/my_plugin_1/server/python_server/output- 1670544300.95411.png")
83
+ print("payload debug:",payload)
84
+
85
+ if(payload['use_prompt_shortcut']): # use edit prompt
86
+ #edit prompt, replaceShortcut(prompt)
87
+ prompt_shortcut_dict = prompt_shortcut.load()
88
+ prompt_shortcut_dict.update(payload["prompt_shortcut_ui_dict"])
89
+ payload['prompt'] = prompt_shortcut.replaceShortcut(payload['prompt'],prompt_shortcut_dict)
90
+ # edit negative prompt, replaceShortcut(negative_prompt)
91
+ payload['negative_prompt'] = prompt_shortcut.replaceShortcut(payload['negative_prompt'],prompt_shortcut_dict)
92
+
93
+ init_img_dir = "./init_images"
94
+ init_img_name = payload['init_image_name']
95
+ init_img = Image.open(f"{init_img_dir}/{init_img_name}")
96
+ init_img_str = img_2_b64(init_img)
97
+ payload['init_images'] = [init_img_str]
98
+
99
+ # mask
100
+
101
+ init_img_mask_name = payload.get('init_image_mask_name',"")
102
+
103
+
104
+ #only if image exist then try to open it
105
+ if(len(init_img_mask_name) > 0):
106
+ init_img_mask = Image.open(f"{init_img_dir}/{init_img_mask_name}")
107
+
108
+ if(payload['use_sharp_mask'] == False):# use blurry mask
109
+ iteration = payload['mask_expansion']
110
+ init_img_mask = applyDilation(init_img_mask,iteration)
111
+
112
+ init_img_mask_str = img_2_b64(init_img_mask)
113
+ payload['mask'] = init_img_mask_str #there is only one mask, unlike 'init_images' which is of type array
114
+
115
+
116
+ # payload = {
117
+ # "prompt": "cute dog",
118
+ # "steps": 10,
119
+ # "init_images":[init_img_str],
120
+ # "n_iter":3
121
+ # }
122
+ # print("payload:",payload)
123
+ print(type(init_img_str))
124
+ #request the images to be generated
125
+ async with httpx.AsyncClient() as client:
126
+ response = await client.post(url=f'{sd_url}/sdapi/v1/img2img', json=payload, timeout=None)
127
+
128
+ r = response.json()
129
+
130
+ #create a directory to store the images at
131
+ # dirName = f'{time.time()}'
132
+ # dir_fullpath,dirName = serverHelper.makeDirPathName()
133
+ uniqueDocumentId = payload['uniqueDocumentId']
134
+ dir_fullpath,dirName = serverHelper.getUniqueDocumentDirPathName(uniqueDocumentId)
135
+ serverHelper.createFolder(dir_fullpath)
136
+ image_paths = []
137
+ metadata = []
138
+ images_info = []
139
+ #for each image store the prompt and settings in the meta data
140
+ for i in r['images']:
141
+ image = Image.open(io.BytesIO(base64.b64decode(i.split(",",1)[0])))
142
+
143
+ png_payload = {
144
+ "image": "data:image/png;base64," + i
145
+ }
146
+ response2 = await client.post(url=f'{sd_url}/sdapi/v1/png-info', json=png_payload, timeout=None)
147
+ pnginfo = PngImagePlugin.PngInfo()
148
+ pnginfo.add_text("parameters", response2.json().get("info"))
149
+ image_name = f'output- {time.time()}.png'
150
+ image_path = f'output/{dirName}/{image_name}'
151
+ image_paths.append(image_path)
152
+ image.save(f'./{image_path}', pnginfo=pnginfo)
153
+
154
+ metadata_info = response2.json().get("info")
155
+ metadata_json = metadata_to_json.convertMetadataToJson(metadata_info)
156
+ metadata.append(metadata_json)
157
+ images_info.append({"base64":i,"path":image_path})
158
+ print("metadata_json: ", metadata_json)
159
+
160
+ return dirName,images_info,metadata
161
+
162
+ if __name__=="__main__":
163
+ img2ImgRequest()
Auto-Photoshop-StableDiffusion-Plugin/server/python_server/init_images/.gitignore ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ # Ignore everything in this directory
2
+ *
3
+ # Except this file
4
+ !.gitignore
Auto-Photoshop-StableDiffusion-Plugin/server/python_server/metadata_to_json.py ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from pathlib import Path
3
+ from PIL import Image
4
+ import json
5
+
6
+ import serverHelper
7
+ # metadata_str = 'cute cat\nSteps: 20, Sampler: Euler a, CFG scale: 7.0, Seed: 2253354038, Size: 512x512, Model hash: 3e16efc8, Seed resize from: -1x-1, Denoising strength: 0, Conditional mask weight: 1.0'
8
+ def convertMetadataToJson(metadata_str):
9
+ print(metadata_str)
10
+ last_new_line_index = metadata_str.rindex('\n')
11
+ prompt = metadata_str[:last_new_line_index]
12
+ other_settings = metadata_str[last_new_line_index+1:]
13
+
14
+ print("prompt:", prompt)
15
+ print("other_settings:", other_settings)
16
+ sub_settings = other_settings.split(",")
17
+ print("sub_settings: ",sub_settings)
18
+
19
+ settings_dict = {}
20
+ settings_dict['prompt'] = prompt
21
+
22
+ for setting in sub_settings:
23
+ [key,value]= setting.split(":")
24
+ key = key.lstrip(' ')
25
+ value = value.lstrip(' ')
26
+ settings_dict[key] = value
27
+ import json
28
+ settings_json = json.dumps(settings_dict)
29
+ print("settings_dict: ",settings_dict)
30
+ print("settings_json ",settings_json)
31
+ return settings_json
32
+
33
+
34
+
35
+
36
+ def getMetadataFromPng(image_path):
37
+ # image_path = "./output/5c42fd2a-6708-45e2-b282-2e9f3894368e/output- 1672476035.4888158.png"
38
+ # image_path = "C:/Users/abdul/Desktop/auto-photoshop/Auto-Photoshop-StableDiffusion-Plugin/server/python_server/output/5c42fd2a-6708-45e2-b282-2e9f3894368e/output- 1672476035.4888158.png"
39
+ im = Image.open(image_path)
40
+ # im.load() # Needed only for .png EXIF data (see citation above)
41
+ # print(im.info['parameters'])
42
+ metadata_string = im.info['parameters']
43
+ metadata_json_string = convertMetadataToJson(metadata_string)
44
+ metadata_dict = json.loads(metadata_json_string)
45
+ print("metadata_dict: ", metadata_dict)
46
+ # print(im.info['meta_to_read'])
47
+ return metadata_dict
48
+
49
+
50
+ def createMetadataJsonFileIfNotExist(image_path):
51
+
52
+ # image_name = os.path.splitext(image_path)
53
+ image_name = Path(image_path).stem
54
+ # parent_dir_path = Path(image_path)
55
+ # parent_dir_path = image_path.split(image_name)[0]
56
+ # os.path.join()
57
+ head = os.path.split(image_path)[0]
58
+ json_file_tail = f'{image_name}.json'
59
+ json_full_path = os.path.join(head,json_file_tail)
60
+ print("image_name: ",image_name)
61
+ print("json_full_path: ",json_full_path)
62
+ isExist = os.path.exists(json_full_path)
63
+ if(isExist):
64
+ #read metadata from json
65
+ metadata_dict = serverHelper.readJson(json_full_path)
66
+
67
+ else:
68
+ #read metadata from image
69
+ #save the metadata to a json file
70
+ metadata_dict = getMetadataFromPng(image_path)
71
+ serverHelper.writeJson(json_full_path,metadata_dict)
72
+ return metadata_dict
73
+
74
+
75
+ if __name__ == "__main__":
76
+ image_path = "C:/Users/abdul/Desktop/auto-photoshop/Auto-Photoshop-StableDiffusion-Plugin/server/python_server/output/5c42fd2a-6708-45e2-b282-2e9f3894368e/output- 1672476035.4888158.png"
77
+ # getMetadataFromPng(image_path)
78
+ createMetadataJsonFileIfNotExist(image_path)
Auto-Photoshop-StableDiffusion-Plugin/server/python_server/output/.gitignore ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ # Ignore everything in this directory
2
+ *
3
+ # Except this file
4
+ !.gitignore
Auto-Photoshop-StableDiffusion-Plugin/server/python_server/prompt_shortcut - Copy.json ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "painterly_style_1": "A full portrait of a beautiful post apocalyptic offworld arctic explorer, intricate, elegant, highly detailed, digital painting, artstation, concept art, smooth, sharp focus, illustration",
3
+ "ugly": " ((((ugly)))), (((duplicate))), ((morbid)), ((mutilated)), out of frame, extra fingers, mutated hands, ((poorly drawn hands)), ((poorly drawn face)), (((mutation))), (((deformed))), ((ugly)), blurry, ((bad anatomy)), (((bad proportions))), ((extra limbs)), cloned face, (((disfigured))), out of frame, ugly, extra limbs, (bad anatomy), gross proportions, (malformed limbs), ((missing arms)), ((missing legs)), (((extra arms))), (((extra legs))), mutated hands, (fused fingers), (too many fingers), (((long neck)))",
4
+ "art_style": "(SPACE1999:1.0),(dreamlikeart style:1.0), ( redshift style:1.0), (analog style:1.2), (studio_ghibli_anime_style style:0.7), (copeseethemald style:0.8)",
5
+ "woman_style": "woman, 1girls, solo, detailed face, lips, realistic pupils, closeup, centered, standing, centered, skin pores, subsurface scattering, detailed skin",
6
+ "environment_style": "detailed background, items, realistic proportions, blushing, masterpiece, best quality, realistic, hyperrealistic, sharp focus, absurdres, good anatomy",
7
+ "uniform_style": "space uniform, red, smooth, black belt, black boots",
8
+ "man_style": "man, solo, detailed face, lips, realistic pupils, closeup, centered, standing, centered, skin pores, subsurface scattering, detailed skin",
9
+ "neg_person": "(glossy:1.0), freckles, nipples, small waist, lowres, large head, long neck, blurry, bad anatomy, bad hands, extra limbs, extra hands, mutated hands, mutated fingers, missing hand, missing finger, text, error, missing fingers, extra digit, fewer digits,",
10
+ "neg_general": "cropped, worst quality, low quality, normal quality, jpeg artifacts, text, signature, watermark, artist name, logo,",
11
+ "nova_green": "[Julianne Hough:Jaime King:0.5]"
12
+ }
Auto-Photoshop-StableDiffusion-Plugin/server/python_server/prompt_shortcut.py ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+ import json
3
+ prompt_shortcut_dict ={}
4
+
5
+
6
+ def readToJson():
7
+ return load()
8
+
9
+ def writeToJson(file_name,data_dict):
10
+ with open(file_name, "w") as outfile:
11
+ json.dump(data_dict, outfile,indent=4)
12
+
13
+
14
+ def load():
15
+ global prompt_shortcut_dict
16
+ try:
17
+ with open('prompt_shortcut.json') as f_obj:
18
+ data = json.load(f_obj)
19
+ prompt_shortcut_dict = data
20
+ print(data)
21
+ except IOError:
22
+ print("prompt_shortcut.json is not found")
23
+ return prompt_shortcut_dict
24
+ def find_words_inside_braces(string):
25
+ result = ""
26
+ pattern ="\{(.*?)\}"
27
+ keywords = []
28
+ for match in re.findall(pattern, string):
29
+ keywords.append(match)
30
+ result += match
31
+ return keywords
32
+
33
+ # text = "a beautiful girl holding a cute cat {style_1} on sunny day"
34
+ # text = "a beautiful girl holding a cute cat { style_1 } on sunny day"
35
+ text = "a beautiful girl{ }, {char1}, {painterly_style} holding a cute cat { style_1 } on sunny day"
36
+ # text = "a beautiful girl {char1 } holding a cute cat on sunny day"
37
+
38
+
39
+
40
+ def replaceShortcut(text,prompt_shortcut_dict):
41
+ raw_keywords = find_words_inside_braces(text)
42
+ strip_keywords = list(map(lambda s: s.strip(),raw_keywords))
43
+
44
+ original_substrings = list(map(lambda s: '{'+s+'}',raw_keywords))
45
+
46
+ print("raw_keywords: ", raw_keywords)
47
+ print("strip_keywords: ", strip_keywords)
48
+ print("original_substrings: ",original_substrings)
49
+ # print ("text:",text)
50
+
51
+ for i, word in enumerate(strip_keywords):
52
+ # word = word.strip()
53
+ print("word: ",word)
54
+ if len(word) > 0 and word in prompt_shortcut_dict:
55
+ prompt = prompt_shortcut_dict[word]
56
+ print("prompt: ",prompt)
57
+ text = text.replace(original_substrings[i],prompt)
58
+ # else:
59
+ # text = text.replace(word,word.strip())
60
+ print ("final text: ",text)
61
+ return text
Auto-Photoshop-StableDiffusion-Plugin/server/python_server/search.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from itertools import islice
2
+
3
+ try:
4
+ from duckduckgo_search import DDGS
5
+ except ImportError:
6
+ raise ImportError(
7
+ "duckduckgo_search is required to image search. Please install it with `pip install --upgrade duckduckgo_search`."
8
+ )
9
+
10
+
11
+ async def imageSearch(keywords="cute cats"):
12
+ with DDGS() as ddgs:
13
+ return [x for x in islice(ddgs.images(keywords), 30)]
14
+
15
+
16
+ if __name__ == "__main__":
17
+
18
+ async def main():
19
+ result = await imageSearch()
20
+ print(result)
21
+
22
+ import asyncio
23
+
24
+ asyncio.run(main())
Auto-Photoshop-StableDiffusion-Plugin/server/python_server/serverHelper.py ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import time
2
+ import os
3
+ import datetime
4
+ import uuid
5
+ import json
6
+
7
+ # this function should be used whenever we need to write to json file
8
+ def writeJson(file_name,data_dict):
9
+ with open(file_name, 'w', encoding='utf-8') as outfile:
10
+ json.dump(data_dict, outfile, ensure_ascii=False, indent=4)
11
+
12
+
13
+
14
+
15
+ # this function should be used whenever we need to read from json file
16
+ def readJson(file_name):
17
+ data_dict = {}
18
+ try:
19
+ with open(file_name) as f_obj:
20
+ data_dict = json.load(f_obj)
21
+
22
+ print("readJson: data_dict: ", data_dict)
23
+ except IOError:
24
+ print(f"{file_name} is not found")
25
+ return data_dict
26
+
27
+ def createFolder(fullpath):
28
+ print("fullpath:",fullpath)
29
+
30
+ if not os.path.exists(fullpath):
31
+ os.mkdir(fullpath)
32
+ #create string dir path name based on the current time
33
+ def makeDirPathName():
34
+ # dirName = f'{time.time()}'
35
+ currentDirPath = os.getcwd()
36
+ now = datetime.datetime.now()
37
+ daily_folder = now.strftime("%Y-%m-%d")
38
+ output_path = os.path.join(currentDirPath,"output")
39
+ fullpath = os.path.join(output_path,daily_folder)
40
+ # fullpath = os.path.join(currentDirPath,dirName)
41
+ return fullpath,daily_folder
42
+
43
+ #create string dir path name based on the uniqueDocumentId
44
+ def getUniqueDocumentDirPathName(uniqueDocumentId):
45
+
46
+ currentDirPath = os.getcwd()
47
+ output_path = os.path.join(currentDirPath,"output")
48
+ fullpath = os.path.join(output_path,uniqueDocumentId)
49
+
50
+ return fullpath,uniqueDocumentId
51
+
52
+ def makeUniqueID():
53
+ myuuid = uuid.uuid4()
54
+ print('Your UUID is: ' + str(myuuid))
55
+ return myuuid
56
+
57
+
58
+ if __name__ == "__main__":
59
+ # currentDirPath = os.getcwd()
60
+ # dirName = f'{time.time()}'
61
+ # fullpath = os.path.join(currentDirPath,dirName)
62
+ # createFolder(fullpath)
63
+ id = makeUniqueID()
64
+ print("id: ",id)
Auto-Photoshop-StableDiffusion-Plugin/server/python_server/serverMain.py ADDED
@@ -0,0 +1,495 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import json
3
+ import requests
4
+ import io
5
+ import base64
6
+ from PIL import Image, PngImagePlugin
7
+ import asyncio
8
+ import httpx
9
+
10
+
11
+ import os
12
+ import time
13
+ import serverHelper
14
+ import prompt_shortcut
15
+ import metadata_to_json
16
+ import search
17
+ sd_url = os.environ.get('SD_URL', 'http://127.0.0.1:7860')
18
+
19
+
20
+
21
+
22
+ async def txt2ImgRequest(payload):
23
+ # payload = {
24
+ # "prompt": "cute cat, kitten",
25
+ # "steps": 10
26
+ # }
27
+ print("payload: ",payload)
28
+
29
+ if(payload['use_prompt_shortcut']): # use edit prompt
30
+ #edit prompt, replaceShortcut(prompt)
31
+ prompt_shortcut_dict = prompt_shortcut.load()
32
+ prompt_shortcut_dict.update(payload["prompt_shortcut_ui_dict"])
33
+ payload['prompt'] = prompt_shortcut.replaceShortcut(payload['prompt'],prompt_shortcut_dict)
34
+ # edit negative prompt, replaceShortcut(negative_prompt)
35
+ payload['negative_prompt'] = prompt_shortcut.replaceShortcut(payload['negative_prompt'],prompt_shortcut_dict)
36
+
37
+
38
+ #request the images to be generated
39
+ request_path = "/sdapi/v1/txt2img"
40
+
41
+ async with httpx.AsyncClient() as client:
42
+ response = await client.post(url=f'{sd_url}/sdapi/v1/txt2img', json=payload, timeout=None)
43
+ r = response.json()
44
+
45
+ #create a directory to store the images at
46
+ # dirName = f'{time.time()}'
47
+ # dir_fullpath,dirName = serverHelper.makeDirPathName()
48
+ uniqueDocumentId = payload['uniqueDocumentId']
49
+ dir_fullpath,dirName = serverHelper.getUniqueDocumentDirPathName(uniqueDocumentId)
50
+ serverHelper.createFolder(dir_fullpath)
51
+ image_paths = []
52
+ #for each image store the prompt and settings in the meta data
53
+ metadata = []
54
+ images_info = []
55
+ for i in r['images']:
56
+ image = Image.open(io.BytesIO(base64.b64decode(i.split(",",1)[0])))
57
+
58
+ png_payload = {
59
+ "image": "data:image/png;base64," + i
60
+ }
61
+ response2 = await client.post(url=f'{sd_url}/sdapi/v1/png-info', json=png_payload)
62
+ pnginfo = PngImagePlugin.PngInfo()
63
+ pnginfo.add_text("parameters", response2.json().get("info"))
64
+ image_name = f'output- {time.time()}.png'
65
+
66
+ image_path = f'output/{dirName}/{image_name}'
67
+ image_paths.append(image_path)
68
+ image.save(f'./{image_path}', pnginfo=pnginfo)
69
+
70
+ metadata_info = response2.json().get("info")
71
+ metadata_json = metadata_to_json.convertMetadataToJson(metadata_info)
72
+ metadata.append(metadata_json)
73
+ images_info.append({"base64":i,"path":image_path})
74
+ print("metadata_json: ", metadata_json)
75
+
76
+
77
+ return dirName,images_info,metadata
78
+
79
+ import base64
80
+ from io import BytesIO
81
+
82
+
83
+ def img_2_b64(image):
84
+ buff = BytesIO()
85
+ image.save(buff, format="PNG")
86
+ img_byte = base64.b64encode(buff.getvalue())
87
+ img_str = img_byte.decode("utf-8")
88
+ return img_str
89
+
90
+
91
+ from typing import Union
92
+
93
+ from fastapi import FastAPI
94
+ from fastapi import APIRouter, Request
95
+
96
+
97
+
98
+ router = APIRouter()
99
+
100
+
101
+ @router.get("/")
102
+ def read_root():
103
+ return {"Hello": "World"}
104
+
105
+
106
+ @router.get("/version")
107
+ def getVersion():
108
+ manifest_dir = "..\..\manifest.json"
109
+
110
+ manifest = {'version': '0.0.0'}
111
+ version = "0.0.0"
112
+ try:
113
+
114
+ with open(manifest_dir, 'r') as f:
115
+ manifest = json.load(f)
116
+ version = manifest['version']
117
+ except:
118
+ print("couldn't read the manifest.json")
119
+ return {"version": f"v{version}"}
120
+
121
+
122
+
123
+
124
+
125
+
126
+ # @router.post("/txt2img/")
127
+ # async def txt2ImgHandle(payload:Payload):
128
+ # print("txt2ImgHandle: \n")
129
+ # txt2ImgRequest(payload)
130
+ # return {"prompt":payload.prompt,"images": ""}
131
+
132
+
133
+ from fastapi import Request, Response
134
+ import img2imgapi
135
+
136
+
137
+
138
+
139
+
140
+
141
+ @router.post("/sd_url/")
142
+ async def changeSdUrl(request:Request):
143
+ global sd_url
144
+ try:
145
+
146
+ payload = await request.json()
147
+ print("changeSdUrl: payload:",payload)
148
+ print(f"change sd url from {sd_url} to {payload['sd_url']} \n")
149
+ sd_url = payload['sd_url']
150
+ except:
151
+ print("error occurred in changeSdUrl()")
152
+ # response.body = resp.content
153
+ # return {}
154
+ return {"sd_url":sd_url}
155
+
156
+
157
+
158
+
159
+
160
+
161
+
162
+
163
+
164
+ @router.post("/txt2img/")
165
+ async def txt2ImgHandle(request:Request):
166
+ print("txt2ImgHandle: \n")
167
+ payload = await request.json()
168
+ dir_name,images_info,metadata, = await txt2ImgRequest(payload)
169
+ # return {"prompt":payload.prompt,"images": ""}
170
+ return {"payload": payload,"dir_name": dir_name,"images_info":images_info,"metadata":metadata}
171
+
172
+ @router.post("/img2img/")
173
+ async def img2ImgHandle(request:Request):
174
+ print("img2ImgHandle: \n")
175
+ payload = await request.json()
176
+ dir_name,images_info,metadata = await img2imgapi.img2ImgRequest(sd_url,payload)
177
+ # return {"prompt":payload.prompt,"images": ""}
178
+ return {"payload": payload,"dir_name": dir_name,"images_info":images_info,"metadata":metadata}
179
+
180
+
181
+
182
+
183
+
184
+
185
+ @router.post("/getInitImage/")
186
+ async def getInitImageHandle(request:Request):
187
+ print("getInitImageHandle: \n")
188
+ payload = await request.json()
189
+ print("payload:",payload)
190
+ init_img_dir = "./init_images"
191
+ init_img_name = payload["init_image_name"]# change this to "image_name"
192
+
193
+ numOfAttempts = 3
194
+ init_img_str = ""
195
+ for i in range(numOfAttempts):
196
+ try:
197
+ image_path = f"{init_img_dir}/{init_img_name}"
198
+ init_img = Image.open(image_path)
199
+ init_img_str = img_2_b64(init_img)
200
+
201
+
202
+ # # If file exists, delete it.
203
+ # if os.path.isfile(image_path):
204
+ # os.remove(image_path)
205
+ except:
206
+ print(f"exception:fail to read an image file {image_path}, will try again {i} of {numOfAttempts}")
207
+ #sleep for one second every time you try to read an image and fail
208
+ time.sleep(1)
209
+ continue;
210
+
211
+
212
+
213
+ return {"payload": payload,"init_image_str":init_img_str}
214
+
215
+ @router.get('/config')
216
+ async def sdapi(request: Request, response: Response):
217
+ try:
218
+
219
+ resp = requests.get(url=f'{sd_url}/config', params=request.query_params)
220
+ response.status_code = resp.status_code
221
+ response.body = resp.content
222
+ except:
223
+ print(f'exception: fail to send request to {sd_url}/config')
224
+ print(f'{request}')
225
+ return response
226
+
227
+ @router.get('/sdapi/v1/{path:path}')
228
+ async def sdapi(path: str, request: Request, response: Response):
229
+ try:
230
+
231
+ resp = requests.get(url=f'{sd_url}/sdapi/v1/{path}', params=request.query_params)
232
+ response.status_code = resp.status_code
233
+ response.body = resp.content
234
+ except:
235
+ print(f'exception: fail to send request to {sd_url}/sdapi/v1/{path}')
236
+ print(f'{request}')
237
+ return response
238
+
239
+ @router.post('/sdapi/v1/{path:path}')
240
+ async def sdapi(path: str, request: Request, response: Response):
241
+ try:
242
+ json = await request.json()
243
+ except:
244
+ json = {}
245
+
246
+ try:
247
+ # if(path =="interrupt"):
248
+ # resp = requests.post(url=f'{sd_url}/sdapi/v1/{path}', params=request.query_params)
249
+
250
+ # else:
251
+ # resp = requests.post(url=f'{sd_url}/sdapi/v1/{path}', params=request.query_params, json=await request.json())
252
+ resp = requests.post(url=f'{sd_url}/sdapi/v1/{path}', params=request.query_params, json=json)
253
+
254
+ response.status_code = resp.status_code
255
+ response.body = resp.content
256
+ except:
257
+ print(f'exception: fail to send request to {sd_url}/sdapi/v1/{path}')
258
+ print(f'{request}')
259
+ return response
260
+
261
+
262
+
263
+ # async def base64ToPng(base64_image,image_path):
264
+ # base64_img_bytes = base64_image.encode('utf-8')
265
+ # with open(image_path, 'wb') as file_to_save:
266
+ # decoded_image_data = base64.decodebytes(base64_img_bytes)
267
+ # file_to_save.write(decoded_image_data)
268
+
269
+
270
+ @router.post('/save/png/')
271
+ async def savePng(request:Request):
272
+ print("savePng()")
273
+ try:
274
+ json = await request.json()
275
+
276
+ except:
277
+ json = {}
278
+
279
+ print("json:",json)
280
+ try:
281
+ folder = './init_images'
282
+ image_path = f"{folder}/{json['image_name']}"
283
+ await img2imgapi.base64ToPng(json['base64'],image_path)
284
+
285
+
286
+
287
+
288
+ return {"status":f"{json['image_name']} has been saved"}
289
+ except:
290
+ print(f'{request}')
291
+ return {"error": "error message: could not save the image file"}
292
+
293
+
294
+ @router.post('/search/image/')
295
+ async def searchImage(request:Request):
296
+ try:
297
+ json = await request.json()
298
+ except:
299
+ json = {}
300
+
301
+
302
+ try:
303
+ keywords = json.get('keywords','cute dogs')
304
+ images = await search.imageSearch(keywords)
305
+ print(images)
306
+
307
+
308
+ return {"images":images}
309
+ except:
310
+ print("keywords",keywords)
311
+ # print(f'{request}')
312
+ return {"error": "error message: can't preform an image search"}
313
+
314
+ @router.post('/mask/expansion/')
315
+ async def maskExpansionHandler(request:Request):
316
+ try:
317
+ json = await request.json()
318
+ except:
319
+ json = {}
320
+
321
+
322
+ try:
323
+ # keywords = json.get('keywords','cute dogs')
324
+ base64_mask_image = json['mask']
325
+ mask_expansion = json['mask_expansion']
326
+ #convert base64 to img
327
+
328
+ await img2imgapi.base64ToPng(base64_mask_image,"original_mask.png")#save a copy of the mask for debugging
329
+
330
+ mask_image = img2imgapi.b64_2_img(base64_mask_image)
331
+
332
+ expanded_mask_img = img2imgapi.maskExpansion(mask_image,mask_expansion)
333
+ base64_expanded_mask_image = img2imgapi.img_2_b64(expanded_mask_img)
334
+ await img2imgapi.base64ToPng(base64_expanded_mask_image,"expanded_mask.png")#save a copy of the mask of the expanded_mask for debugging
335
+
336
+ print("successful mask expansion operation")
337
+ return {"mask":base64_expanded_mask_image}
338
+
339
+ except:
340
+ print("request",request)
341
+ raise Exception(f"couldn't preform mask expansion")
342
+ # return response
343
+ return {"error": "error message: can't preform an mask expansion"}
344
+
345
+
346
+ @router.post('/history/load')
347
+ async def loadHistory(request: Request):
348
+ # {'image_paths','metadata_setting'}
349
+ history = {}
350
+ try:
351
+ json = await request.json()
352
+ except:
353
+ json = {}
354
+
355
+ try:
356
+
357
+ uniqueDocumentId = json['uniqueDocumentId']
358
+
359
+ import glob
360
+
361
+ image_paths = glob.glob(f'./output/{uniqueDocumentId}/*.png')
362
+ settings_paths = glob.glob(f'./output/{uniqueDocumentId}/*.json')#note: why is we are not using settings_paths?
363
+ print("loadHistory: image_paths:", image_paths)
364
+
365
+
366
+ history['image_paths'] = image_paths
367
+ history['metadata_jsons'] = []
368
+ history['base64_images'] = []
369
+ for image_path in image_paths:
370
+ print("image_path: ", image_path)
371
+ metadata_dict = metadata_to_json.createMetadataJsonFileIfNotExist(image_path)
372
+ history['metadata_jsons'].routerend(metadata_dict)
373
+
374
+
375
+ img = Image.open(image_path)
376
+ base64_image = img_2_b64(img)
377
+ history['base64_images'].routerend(base64_image)
378
+
379
+ except:
380
+
381
+ print(f'{request}')
382
+
383
+ #reverse the order so that newer generated images path will be shown first
384
+
385
+
386
+ history['image_paths'].reverse()
387
+ history['metadata_jsons'].reverse()
388
+ history['base64_images'].reverse()
389
+ return {"image_paths":history['image_paths'], "metadata_jsons":history['metadata_jsons'],"base64_images": history['base64_images']}
390
+
391
+
392
+ @router.post('/prompt_shortcut/load')
393
+ async def loadPromptShortcut(request: Request):
394
+ prompt_shortcut_json = {}
395
+ try:
396
+ json = await request.json()
397
+ except:
398
+ json = {}
399
+
400
+ try:
401
+
402
+ prompt_shortcut_json = prompt_shortcut.load()
403
+ # response.body = {"prompt_shortcut":prompt_shortcut}
404
+ # response.status_code = 200
405
+ except:
406
+ # print(f'exception: fail to send request to {sd_url}/sdapi/v1/{path}')
407
+ print(f'{request}')
408
+
409
+ # return response
410
+ return {"prompt_shortcut":prompt_shortcut_json}
411
+ @router.post('/prompt_shortcut/save')
412
+ async def loadPromptShortcut(request: Request):
413
+ prompt_shortcut_json = {}
414
+ try:
415
+ json = await request.json()
416
+ except:
417
+ json = {}
418
+
419
+ try:
420
+ print("json: ",json)
421
+ print("json['prompt_shortcut']: ",json['prompt_shortcut'])
422
+ # save the prompt shortcut to the prompt_shortcut.json
423
+ prompt_shortcut_json = json['prompt_shortcut']
424
+ # response.body = {"prompt_shortcut":prompt_shortcut}
425
+ # response.body = {"prompt_shortcut":prompt_shortcut}
426
+ prompt_shortcut.writeToJson("prompt_shortcut.json",prompt_shortcut_json)
427
+ except:
428
+ # print(f'exception: fail to send request to {sd_url}/sdapi/v1/{path}')
429
+ print(f'error occurred durning reading the request {request}')
430
+ # return response
431
+ return {"prompt_shortcut":prompt_shortcut_json}
432
+
433
+ @router.post("/swapModel")
434
+ async def swapModel(request:Request):
435
+ print("swapModel: \n")
436
+ payload = await request.json()
437
+ print("payload:",payload)
438
+ model_title = payload.title
439
+ option_payload = {
440
+ # "sd_model_checkpoint": "Anything-V3.0-pruned.ckpt [2700c435]"
441
+ "sd_model_checkpoint": model_title
442
+
443
+ }
444
+ response = requests.post(url=f'{sd_url}/sdapi/v1/options', json=option_payload)
445
+
446
+
447
+ import webbrowser
448
+ @router.post("/open/url/")
449
+ async def openUrl(request:Request):
450
+ try:
451
+ json = await request.json()
452
+ except:
453
+ json = {}
454
+
455
+ url = ""
456
+ print("json: ",json)
457
+ try:
458
+ url = json['url']
459
+ webbrowser.open(url) # Go to example.com
460
+ except:
461
+ # print(f'exception: fail to send request to {sd_url}/sdapi/v1/{path}')
462
+ print(f'an error has occurred durning processing the request {request}')
463
+ # return response
464
+ return {"url":url}
465
+
466
+
467
+ @router.get('/lora/list')
468
+ async def list_available_loras():
469
+ lora_dict = {}
470
+ try:
471
+ from modules import shared
472
+ import glob
473
+
474
+ os.makedirs(shared.cmd_opts.lora_dir, exist_ok=True)
475
+
476
+ candidates = \
477
+ glob.glob(os.path.join(shared.cmd_opts.lora_dir, '**/*.pt'), recursive=True) + \
478
+ glob.glob(os.path.join(shared.cmd_opts.lora_dir, '**/*.safetensors'), recursive=True) + \
479
+ glob.glob(os.path.join(shared.cmd_opts.lora_dir, '**/*.ckpt'), recursive=True)
480
+
481
+ for filename in sorted(candidates, key=str.lower):
482
+ if os.path.isdir(filename):
483
+ continue
484
+
485
+ name = os.path.splitext(os.path.basename(filename))[0]
486
+ print("lora name: ",name)
487
+ # available_loras[name] = LoraOnDisk(name, filename)
488
+ lora_dict[name] = name
489
+
490
+ except Exception as e:
491
+ print("list_available_loras() error ",repr(e),e)
492
+ return lora_dict
493
+
494
+ app = FastAPI()
495
+ app.include_router(router)
Auto-Photoshop-StableDiffusion-Plugin/start_server.bat ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @REM @echo off
2
+ git pull
3
+
4
+ set SD_URL=http://127.0.0.1:7860
5
+
6
+ echo does server_env\ exist
7
+ if exist server_env\ (
8
+ echo Yes
9
+ goto :activate_server_env
10
+ ) else (
11
+ echo No
12
+ goto :create_server_env
13
+ )
14
+
15
+ :create_server_env
16
+ python -m venv server_env
17
+
18
+
19
+
20
+
21
+ @REM pause
22
+
23
+
24
+ :activate_server_env
25
+
26
+ ::run a server
27
+ echo my_path: %~dp0
28
+ @REM set current_dir=
29
+ set VENV_DIR=%~dp0server_env
30
+ @REM cd ./server_env/Scripts/
31
+ set PYTHON="%VENV_DIR%\Scripts\Python.exe"
32
+ %PYTHON% -m pip install -r requirements.txt
33
+
34
+ cd ./server/python_server
35
+ echo python path: %PYTHON%
36
+ dir
37
+ echo %PYTHON% uvicorn serverMain:app --reload
38
+ %PYTHON% -m uvicorn serverMain:app --reload
39
+ pause
40
+ @REM exit /b
41
+ @REM %PYTHON% uvicorn serverMain:app --reload
42
+ pause
43
+
44
+ @REM %PYTHON% img2imgapi.py
45
+ @REM activate
46
+ @REM echo server_env %PYTHON%
47
+ @REM cd ./server/python_server
48
+ @REM %PYTHON% img2imgapi.py
49
+ @REM uvicorn serverMain:app --reload
50
+ @REM dir .
51
+ @REM call webui.bat
Auto-Photoshop-StableDiffusion-Plugin/start_server.sh ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ git pull
3
+ # Set the desired remote host where the "<>" is
4
+ export SD_URL=http://127.0.0.1:7860
5
+
6
+ # Check python was installed
7
+ if ! hash python; then
8
+ echo "Python is not installed"
9
+ exit 1
10
+ fi
11
+
12
+ # Check the default python version
13
+ orig_ver=$(python -V 2>&1)
14
+ major_version=$(echo "$orig_ver" | sed 's/[^0-9]*\([0-9]*\)\..*/\1/')
15
+ minor_subversion=$(echo "$orig_ver" | sed -E 's/^[^.]*\.([^.]*).*$/\1/')
16
+ if [[ "$major_version" -ge "3" ]] && [[ "$minor_subversion" -ge "7" ]] # Because of uvicorn==0.20.0 in requirements
17
+ then
18
+ echo "You have valid version of $orig_ver"
19
+ else
20
+ echo "Your version $orig_ver not valid, should be >=3.7"
21
+ exit 1
22
+ fi
23
+
24
+
25
+ # Check if the desired environment exists
26
+ if [ ! -d "server_env" ]; then
27
+ # Create the environment if it doesn't exist
28
+ python -m venv server_env
29
+ source ./server_env/bin/activate
30
+ python -m pip install -r requirements.txt
31
+ else
32
+ source ./server_env/bin/activate
33
+ fi
34
+
35
+ cd ./server/python_server
36
+ python -m uvicorn serverMain:app --reload
Auto-Photoshop-StableDiffusion-Plugin/start_server_MacOS.sh ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ git pull
3
+ # Set the desired remote host where the "<>" is
4
+ export SD_URL=http://127.0.0.1:7860
5
+
6
+ # Check if the desired environment exists
7
+ if [ ! -d "server_env" ]; then
8
+ # Create the environment if it doesn't exist
9
+ python3 -m venv server_env
10
+ source ./server_env/bin/activate
11
+ python3 -m pip install -r requirements.txt
12
+ else
13
+ source ./server_env/bin/activate
14
+ fi
15
+
16
+ cd ./server/python_server
17
+ python3 -m uvicorn serverMain:app --reload