Merge branch 'silent_export' into master

pull/101/head
Abdullah Alfaraj 2023-02-15 14:50:21 +03:00
commit 7957f3e333
13 changed files with 1827 additions and 173 deletions

6
.gitignore vendored
View File

@ -18,3 +18,9 @@ start_server.bat
expanded_mask.png expanded_mask.png
original_mask.png original_mask.png
/config /config
/jimp/*
!/jimp/browser/
/jimp/browser/examples
/jimp/browser/*.md
/jimp/browser/*.editorconfig

View File

@ -9,7 +9,6 @@ const helper = require('./helper')
// const sdapi = require(`./${g_sdapi_path}`) // const sdapi = require(`./${g_sdapi_path}`)
const sdapi = require('./sdapi_py_re') const sdapi = require('./sdapi_py_re')
// const exportHelper = require('./export_png') // const exportHelper = require('./export_png')
const outpaint = require('./outpaint') const outpaint = require('./outpaint')
const psapi = require('./psapi') const psapi = require('./psapi')
@ -35,6 +34,7 @@ const storage = require('uxp').storage
const fs = storage.localFileSystem const fs = storage.localFileSystem
const horde_native = require('./utility/sdapi/horde_native') const horde_native = require('./utility/sdapi/horde_native')
const io = require('./utility/io') const io = require('./utility/io')
const general = require('./utility/general')
let g_horde_generator = new horde_native.hordeGenerator() let g_horde_generator = new horde_native.hordeGenerator()
async function hasSessionSelectionChanged() { async function hasSessionSelectionChanged() {
@ -2481,7 +2481,10 @@ document
.addEventListener('click', async () => { .addEventListener('click', async () => {
//set init image event listener, use when settion is active //set init image event listener, use when settion is active
const layer = await app.activeDocument.activeLayers[0] const layer = await app.activeDocument.activeLayers[0]
const image_info = await psapi.setInitImage(layer, random_session_id) const image_info = await psapi.silentSetInitImage(
layer,
random_session_id
)
const image_name = image_info['name'] const image_name = image_info['name']
const path = `./server/python_server/init_images/${image_name}` const path = `./server/python_server/init_images/${image_name}`
g_viewer_manager.addInitImageLayers(layer, path, false) g_viewer_manager.addInitImageLayers(layer, path, false)
@ -2498,7 +2501,7 @@ document
}) })
const layer = g_viewer_manager.maskGroup const layer = g_viewer_manager.maskGroup
// const layer = await app.activeDocument.activeLayers[0] // const layer = await app.activeDocument.activeLayers[0]
const mask_info = await psapi.setInitImageMask( const mask_info = await psapi.silentSetInitImageMask(
layer, layer,
random_session_id random_session_id
) )
@ -4087,29 +4090,3 @@ async function prmoptForUpdate() {
document.getElementById('btnUpdate').addEventListener('click', async () => { document.getElementById('btnUpdate').addEventListener('click', async () => {
await prmoptForUpdate() await prmoptForUpdate()
}) })
function urlToImg(img_url) {
//TODO: delete this code
var xhr = new XMLHttpRequest()
// Use JSFiddle logo as a sample image to avoid complicating
// this example with cross-domain issues.
// xhr.open('GET', 'http://fiddle.jshell.net/img/logo.png', true)
xhr.open('GET', img_url, true)
// Ask for the result as an ArrayBuffer.
xhr.responseType = 'arraybuffer'
xhr.onload = function (e) {
// Obtain a blob: URL for the image data.
var arrayBufferView = new Uint8Array(this.response)
var blob = new Blob([arrayBufferView], { type: 'image/png' })
var urlCreator = window.URL || window.webkitURL
var imageUrl = urlCreator.createObjectURL(blob)
var img = document.getElementById('webp_container')
img.src = imageUrl
}
xhr.send()
}

18
jimp/browser/lib/jimp.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -186,7 +186,7 @@ async function snapAndFillExe(session_id) {
// g_init_image_related_layers['init_image_layer'] = snapshotLayer // g_init_image_related_layers['init_image_layer'] = snapshotLayer
// g_init_image_related_layers['solid_white'] = whiteSolidLayer // g_init_image_related_layers['solid_white'] = whiteSolidLayer
const image_info = await psapi.setInitImage( const image_info = await psapi.silentSetInitImage(
snapshotGroup, snapshotGroup,
session_id session_id
) )
@ -215,125 +215,6 @@ async function snapAndFillExe(session_id) {
return [] return []
} }
async function outpaintFasterExe(session_id) {
//create a snapshot of canvas
//select opaque pixel and create black fill layer
//create a snapshot of mask
//set initial image
//set mask image
try {
let outpaintLayers = []
await executeAsModal(async () => {
const selectionInfo = await psapi.getSelectionInfoExe()
// await psapi.unSelectMarqueeExe()
//create a snapshot of canvas
// let [snapshotLayer,snapshotGroup] = await createSnapshot()
await psapi.snapshot_layerExe()
const snapshotLayer = await app.activeDocument.activeLayers[0]
snapshotLayer.name = 'Init Image Snapshot -- temporary'
const snapshotGroup = await psapi.createEmptyGroup()
// snapshotGroup.name = `${snapshotGroup.name}_init_image`
snapshotGroup.name = 'Init Image Group -- temporary'
await psapi.createSolidLayer(255, 255, 255)
const whiteSolidLayer = await app.activeDocument.activeLayers[0]
whiteSolidLayer.name = 'Background Color -- temporary'
snapshotLayer.moveAbove(whiteSolidLayer)
console.log('[snapshotLayer,snapshotGroup]:', [
snapshotLayer,
snapshotGroup,
])
//select opaque pixel and create black fill layer
await psapi.selectLayersExe([snapshotLayer])
await psapi.selectLayerChannelCommand()
const snapshotMaskGroup = await psapi.createEmptyGroup()
await psapi.createSolidLayer(0, 0, 0)
let solid_black_layer = app.activeDocument.activeLayers[0]
//create a snapshot of mask
await psapi.reSelectMarqueeExe(selectionInfo)
// let [snapshotMaskLayer,snapshotMaskGroup] = await createSnapshot()
await psapi.snapshot_layerExe()
const snapshotMaskLayer = await app.activeDocument.activeLayers[0]
snapshotMaskLayer.name = 'Mask -- Paint White to Mask -- temporary'
// const snapshotMaskGroup = await psapi.createEmptyGroup()
// snapshotMaskGroup.name = `${snapshotMaskGroup.name}_mask`
snapshotMaskGroup.name = 'Mask Group -- temporary'
snapshotMaskLayer.moveBelow(solid_black_layer)
await snapshotMaskGroup.moveAbove(snapshotGroup)
await solid_black_layer.delete() // should we await for the deletion?
await psapi.selectLayers([snapshotGroup])
await psapi.reSelectMarqueeExe(selectionInfo)
await psapi.createClippingMaskExe()
await psapi.selectLayers([snapshotGroup])
const image_info = await psapi.setInitImage(
snapshotGroup,
session_id
)
const image_name = image_info['name']
const path = `./server/python_server/init_images/${image_name}`
await psapi.reSelectMarqueeExe(selectionInfo)
await psapi.selectLayers([snapshotMaskGroup])
await psapi.reSelectMarqueeExe(selectionInfo)
await psapi.createClippingMaskExe()
await psapi.selectLayers([snapshotMaskGroup])
await psapi.reSelectMarqueeExe(selectionInfo)
await psapi.setInitImageMask(snapshotMaskGroup, session_id)
await psapi.reSelectMarqueeExe(selectionInfo)
//set initial image
//set mask image
outpaintLayers = [
snapshotMaskGroup,
snapshotMaskLayer,
snapshotLayer,
snapshotGroup,
whiteSolidLayer,
]
// g_mask_related_layers['mask_group'] = snapshotMaskGroup
// g_mask_related_layers['white_mark'] = snapshotMaskLayer
// // g_mask_related_layers['solid_black'] = blackSolidLayer
g_viewer_manager.initializeMask(
snapshotMaskGroup,
snapshotMaskLayer,
null,
path
)
// g_init_image_related_layers['init_image_group'] = snapshotGroup
// g_init_image_related_layers['init_image_layer'] = snapshotLayer
// g_init_image_related_layers['solid_white'] = whiteSolidLayer
g_viewer_manager.initializeInitImage(
snapshotGroup,
snapshotLayer,
whiteSolidLayer,
path
) //this will be called once a session and will add the first init image to th viewer manager
for (layer of outpaintLayers) {
layer.visible = false
}
//collapse the folders
const layer_util = require('./utility/layer')
await layer_util.collapseFolderExe(
[snapshotGroup, snapshotMaskGroup],
false
)
})
console.log('outpaintLayers 2: ', outpaintLayers)
return outpaintLayers
} catch (e) {
console.error(`outpaintFasterExe error: ${e}`)
}
return []
}
async function addClippingMaskToLayer(layer, selectionInfo) { async function addClippingMaskToLayer(layer, selectionInfo) {
await psapi.selectLayers([layer]) //select the layer await psapi.selectLayers([layer]) //select the layer
await psapi.reSelectMarqueeExe(selectionInfo) //reselect the selection await psapi.reSelectMarqueeExe(selectionInfo) //reselect the selection
@ -401,10 +282,18 @@ async function outpaintExe(session_id) {
await addClippingMaskToLayer(snapshotGroup, selectionInfo) await addClippingMaskToLayer(snapshotGroup, selectionInfo)
const image_info = await psapi.setInitImage( const mask_info = await psapi.silentSetInitImageMask(
snapshotMaskGroup,
session_id
)
snapshotMaskGroup.visible = false
const image_info = await psapi.silentSetInitImage(
snapshotGroup, snapshotGroup,
session_id session_id
) )
snapshotGroup.visible = false
const init_image_name = image_info['name'] const init_image_name = image_info['name']
const init_path = `./server/python_server/init_images/${init_image_name}` const init_path = `./server/python_server/init_images/${init_image_name}`
@ -414,11 +303,8 @@ async function outpaintExe(session_id) {
await psapi.reSelectMarqueeExe(selectionInfo) await psapi.reSelectMarqueeExe(selectionInfo)
// await psapi.setInitImageMask(snapshotMaskGroup,session_id) // await psapi.silentSetInitImageMask(snapshotMaskGroup,session_id)
const mask_info = await psapi.setInitImageMask(
snapshotMaskGroup,
session_id
)
const mask_name = mask_info['name'] const mask_name = mask_info['name']
const mask_path = `./server/python_server/init_images/${mask_name}` const mask_path = `./server/python_server/init_images/${mask_name}`
await psapi.reSelectMarqueeExe(selectionInfo) await psapi.reSelectMarqueeExe(selectionInfo)
@ -559,18 +445,20 @@ async function inpaintFasterExe(session_id) {
// await psapi.selectLayers([snapshotGroup]) // await psapi.selectLayers([snapshotGroup])
await psapi.selectLayers([maskGroup]) await psapi.selectLayers([maskGroup])
// await psapi.setInitImageMask(maskGroup,session_id) // await psapi.silentSetInitImageMask(maskGroup,session_id)
const mask_info = await psapi.setInitImageMask( const mask_info = await psapi.silentSetInitImageMask(
maskGroup, maskGroup,
session_id session_id
) )
maskGroup.visible = false
//hide the mask so you can take screenshot of the init image
const mask_name = mask_info['name'] const mask_name = mask_info['name']
const mask_path = `./server/python_server/init_images/${mask_name}` const mask_path = `./server/python_server/init_images/${mask_name}`
await psapi.reSelectMarqueeExe(selectionInfo) await psapi.reSelectMarqueeExe(selectionInfo)
await psapi.selectLayers([snapshotGroup]) await psapi.selectLayers([snapshotGroup])
const image_info = await psapi.setInitImage( const image_info = await psapi.silentSetInitImage(
snapshotGroup, snapshotGroup,
session_id session_id
) )

1564
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,9 @@
"author": "Adobe Inc", "author": "Adobe Inc",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"fastify": "^4.10.2" "fastify": "^4.10.2",
"jimp": "^0.16.2",
"md5": "^2.3.0"
}, },
"main": "index.js", "main": "index.js",
"directories": { "directories": {

View File

@ -715,7 +715,89 @@ function layerNameToFileName(layer_name, layer_id, session_id) {
return file_name return file_name
} }
// await runModalFunction(); async function silentSetInitImage(layer, session_id) {
try {
const html_manip = require('./utility/html_manip')
const io = require('./utility/io')
// const layer = await app.activeDocument.activeLayers[0]
const old_name = layer.name
// image_name = await app.activeDocument.activeLayers[0].name
//convert layer name to a file name
let image_name = layerNameToFileName(old_name, layer.id, session_id)
image_name = `${image_name}.png`
//the width and height of the exported image
const width = html_manip.getWidth()
const height = html_manip.getHeight()
//get the selection from the canvas as base64 png, make sure to resize to the width and height slider
const base64_image = await io.IO.getSelectionFromCanvasAsBase64(
true,
width,
height
)
//save base64 as file in the init_images directory
const init_entry = await getInitImagesDir()
await io.IO.base64PngToPngFile(base64_image, init_entry, image_name)
g_init_image_name = image_name
console.log(image_name)
const path = `${g_init_images_dir}/${image_name}`
//store the base64 init image and also set it as the active/latest init image
g_generation_session.base64initImages[path] = base64_image
g_generation_session.activeBase64InitImage = base64_image
const init_src = base64ToSrc(g_generation_session.activeBase64InitImage)
html_manip.setInitImageSrc(init_src)
return (image_info = { name: image_name, base64: base64_image })
} catch (e) {
console.error(`psapi.js silentSetInitImage error:, ${e}`)
}
}
async function silentSetInitImageMask(layer, session_id) {
try {
const html_manip = require('./utility/html_manip')
// const layer = await app.activeDocument.activeLayers[0]
const old_name = layer.name
image_name = layerNameToFileName(old_name, layer.id, session_id)
image_name = `${image_name}.png`
const width = html_manip.getWidth()
const height = html_manip.getHeight()
//get the selection from the canvas as base64 png, make sure to resize to the width and height slider
const base64_image = await io.IO.getSelectionFromCanvasAsBase64(
true,
width,
height
)
//save base64 as file in the init_images directory
const init_entry = await getInitImagesDir()
await io.IO.base64PngToPngFile(base64_image, init_entry, image_name)
g_init_image_mask_name = image_name // this is the name we will send to the server
console.log(image_name)
const path = `${g_init_images_dir}/${image_name}`
g_generation_session.base64maskImage[path] = base64_image
g_generation_session.activeBase64MaskImage = base64_image
const mask_src = base64ToSrc(g_generation_session.activeBase64MaskImage)
html_manip.setInitImageMaskSrc(mask_src)
return (image_info = { name: image_name, base64: base64_image })
} catch (e) {
console.error(`psapi.js setInitImageMask error: `, e)
}
}
async function setInitImage(layer, session_id) { async function setInitImage(layer, session_id) {
try { try {
const html_manip = require('./utility/html_manip') const html_manip = require('./utility/html_manip')
@ -1377,4 +1459,6 @@ module.exports = {
isSelectionValid, isSelectionValid,
snapshot_layer_no_slide_Exe, snapshot_layer_no_slide_Exe,
setVisibleExe, setVisibleExe,
silentSetInitImage,
silentSetInitImageMask,
} }

View File

@ -62,7 +62,7 @@ async function requestSavePng(base64_image, image_name) {
// return json // return json
const uniqueDocumentId = await getUniqueDocumentId() const uniqueDocumentId = await getUniqueDocumentId()
const folder = `${uniqueDocumentId}/init_images` const folder = `${uniqueDocumentId}/init_images`
const init_entery = getInitImagesDir() const init_entry = await getInitImagesDir()
saveFileInSubFolder(base64_image, folder, image_name) saveFileInSubFolder(base64_image, folder, image_name)
console.warn('this function is deprecated') console.warn('this function is deprecated')
} catch (e) { } catch (e) {

View File

@ -6,7 +6,7 @@ function newOutputImageName(format = 'png') {
} }
function makeImagePath(format = 'png') { function makeImagePath(format = 'png') {
const image_name = general.newOutputImageName(format) const image_name = newOutputImageName(format)
const image_path = `${uniqueDocumentId}/${image_name}` const image_path = `${uniqueDocumentId}/${image_name}`
return image_path return image_path
} }
@ -14,8 +14,24 @@ function convertImageNameToPng(image_name) {
const image_png_name = image_name.split('.')[0] + '.png' const image_png_name = image_name.split('.')[0] + '.png'
return image_png_name return image_png_name
} }
function fixNativePath(native_path) {
const fixed_native_path = native_path.replaceAll('\\', '/')
return fixed_native_path
}
function base64ToBase64Url(base64_image) {
return 'data:image/png;base64,' + base64_image
}
function base64UrlToBase64(base64_url) {
const base64_image = base64_url.replace('data:image/png;base64,', '')
return base64_image
}
module.exports = { module.exports = {
newOutputImageName, newOutputImageName,
makeImagePath, makeImagePath,
convertImageNameToPng, convertImageNameToPng,
fixNativePath,
base64ToBase64Url,
base64UrlToBase64,
} }

View File

@ -1,6 +1,8 @@
const batchPlay = require('photoshop').action.batchPlay const batchPlay = require('photoshop').action.batchPlay
const psapi = require('../psapi') const psapi = require('../psapi')
const layer_util = require('../utility/layer') const layer_util = require('../utility/layer')
const general = require('./general')
const Jimp = require('../jimp/browser/lib/jimp.min')
async function snapShotLayer() { async function snapShotLayer() {
//snapshot layer with no mask //snapshot layer with no mask
let command = [ let command = [
@ -143,13 +145,16 @@ class IO {
static async exportDoc() {} static async exportDoc() {}
static async exportLayer() {} static async exportLayer() {}
static async base64PngToPngFile(base64_png) { static async base64PngToPngFile(
base64_png,
folder,
image_name = 'temp_base64Png.png'
) {
const arrayBuffer = _base64ToArrayBuffer(base64_png) const arrayBuffer = _base64ToArrayBuffer(base64_png)
const img_name = 'temp_base64Png.png' // const folder = await storage.localFileSystem.getTemporaryFolder()
const folder = await storage.localFileSystem.getTemporaryFolder() const file = await folder.createFile(image_name, { overwrite: true })
const file = await folder.createFile(img_name, { overwrite: true })
await file.write(arrayBuffer, { format: storage.formats.binary }) await file.write(arrayBuffer, { format: storage.formats.binary })
return file return file
@ -165,7 +170,12 @@ class IO {
try { try {
const main_doc_entry = await getCurrentDocFolder() const main_doc_entry = await getCurrentDocFolder()
//save the base64_png to .png file //save the base64_png to .png file
const png_file = await this.base64PngToPngFile(base64_png) const temp_folder = await fs.getTemporaryFolder()
const png_file = await this.base64PngToPngFile(
base64_png,
temp_folder
)
//load the .png file as a layer in new document //load the .png file as a layer in new document
const new_doc = await this.openImageFileAsDocument(png_file) const new_doc = await this.openImageFileAsDocument(png_file)
//save document as .webp //save document as .webp
@ -233,6 +243,55 @@ class IO {
} }
return layer return layer
} }
static async getSelectionFromCanvasAsBase64(
b_resize = false,
resize_width = 0,
resize_height = 0
) {
//it will save the document then crop it so that only the selection area are left.
//return arrayBuffer or base64Png?
try {
let file
const folder = await fs.getTemporaryFolder()
await executeAsModal(
async () => {
const canvas_image_name = 'canvas_image.png'
file = await folder.createFile(canvas_image_name, {
overwrite: true,
})
const currentDocument = app.activeDocument
await currentDocument.saveAs.png(file, null, true)
//save file end
//read the saved image.png
},
{ commandName: 'readPng' }
)
const arrayBuffer = await file.read({
format: formats.binary,
})
const selectionInfo = g_generation_session.selectionInfo
// const selectionInfo = await psapi.getSelectionInfoExe()
const cropped_base64_url = await IOHelper.cropPng(
arrayBuffer,
selectionInfo,
true,
resize_width,
resize_height
)
const cropped_base64 = general.base64UrlToBase64(cropped_base64_url)
// html_manip.setInitImageSrc(cropped_base64_url)
return cropped_base64
} catch (e) {
console.warn(e)
}
}
} }
class IOHelper { class IOHelper {
@ -311,6 +370,48 @@ class IOHelper {
} }
return new_doc return new_doc
} }
static async cropPng(
arrayBuffer,
selectionInfo,
b_resize = false,
resize_width = 0,
resize_height = 0
) {
//crop png from array buffer
//have the option to resize the after cropping
const crop_x = selectionInfo.left
const crop_y = selectionInfo.top
const crop_w = selectionInfo.width
const crop_h = selectionInfo.height
const base64_url_result = await Jimp.read(arrayBuffer)
.then(async (img) => {
let cropped_img = await img.crop(crop_x, crop_y, crop_w, crop_h)
let resized_img
if (b_resize) {
resized_img = await cropped_img.resize(
resize_width,
resize_height
)
} else {
resized_img = cropped_img
}
const base64_url = await resized_img.getBase64Async(
Jimp.MIME_PNG
)
console.log('jimp: base64_url: ', base64_url)
// document.getElementById("image").setAttribute("src", data);
return base64_url
})
.catch((error) => {
console.error(error)
})
return base64_url_result
}
} }
class IOBase64ToLayer { class IOBase64ToLayer {
@ -327,4 +428,5 @@ class IOBase64ToLayer {
module.exports = { module.exports = {
IO, IO,
snapShotLayerExe, snapShotLayerExe,
IOHelper,
} }

View File

@ -326,7 +326,7 @@ class hordeGenerator {
const image_path = `${uuid}/${image_png_file_name}` //this is the png path const image_path = `${uuid}/${image_png_file_name}` //this is the png path
images_info.push({ images_info.push({
path: image_path, path: image_path,
base64: getDummyBase64(), base64: getDummyBase64(), //TODO:change this to the base64_png
layer: image_layer, layer: image_layer,
}) })
await psapi.layerToSelection( await psapi.layerToSelection(

View File

@ -445,8 +445,7 @@ async function getDocumentFolderNativePath(doc_uuid) {
const uuid = await getUniqueDocumentId() const uuid = await getUniqueDocumentId()
let doc_folder = await getDocFolder(uuid) let doc_folder = await getDocFolder(uuid)
let path = doc_folder.nativePath const path = general.fixNativePath(doc_folder.nativePath)
path = path.replaceAll('\\', '/')
return path return path
} catch (e) { } catch (e) {
console.warn(e) console.warn(e)

View File

@ -161,7 +161,7 @@ class ViewerImage {
//set init image event listener, use when settion is active //set init image event listener, use when settion is active
const layer = await app.activeDocument.activeLayers[0] const layer = await app.activeDocument.activeLayers[0]
const image_info = await psapi.setInitImage( const image_info = await psapi.silentSetInitImage(
layer, layer,
random_session_id random_session_id
) )