1285 lines
43 KiB
JavaScript
1285 lines
43 KiB
JavaScript
const psapi = require('../psapi')
|
|
|
|
const layer_util = require('../utility/layer')
|
|
const general = require('./general')
|
|
|
|
const { executeAsModal } = require('photoshop').core
|
|
const batchPlay = require('photoshop').action.batchPlay
|
|
const formats = require('uxp').storage.formats
|
|
const storage = require('uxp').storage
|
|
const fs = storage.localFileSystem
|
|
|
|
async function isBlackAndWhiteImage(base64EncodedImage) {
|
|
try {
|
|
// Load your base64 encoded image
|
|
const image = await Jimp.read(Buffer.from(base64EncodedImage, 'base64'))
|
|
console.log(
|
|
'isBlackAndWhiteImage(): image.bitmap.width, image.bitmap.height: ',
|
|
image.bitmap.width,
|
|
image.bitmap.height
|
|
)
|
|
// Check if your image only has one channel
|
|
return (
|
|
image.bitmap.width === image.bitmap.height &&
|
|
image.bitmap.width === 1
|
|
)
|
|
} catch (e) {
|
|
console.warn(e)
|
|
}
|
|
}
|
|
|
|
async function convertBlackAndWhiteImageToRGBChannels(base64EncodedImage) {
|
|
// Load your base64 encoded image
|
|
const image = await Jimp.read(Buffer.from(base64EncodedImage, 'base64'))
|
|
|
|
// Convert your black and white image to RGB channels
|
|
image.color([
|
|
{ apply: 'red', params: [255] },
|
|
{ apply: 'green', params: [255] },
|
|
{ apply: 'blue', params: [255] },
|
|
])
|
|
|
|
// Get your base64 encoded black and white image with RGB channels
|
|
const base64EncodedImageWithRGBChannels = await image.getBase64Async(
|
|
Jimp.MIME_JPEG
|
|
)
|
|
|
|
return base64EncodedImageWithRGBChannels
|
|
}
|
|
async function convertBlackAndWhiteImageToRGBChannels2(base64EncodedImage) {
|
|
try {
|
|
// Load your base64 encoded image
|
|
const image = await Jimp.read(Buffer.from(base64EncodedImage, 'base64'))
|
|
|
|
// Convert your black and white image to RGB channels
|
|
image.color([{ apply: 'mix', params: ['#ffffff', 100] }])
|
|
|
|
// Get your base64 encoded black and white image with RGB channels
|
|
const base64EncodedImageWithRGBChannels = await image.getBase64Async(
|
|
Jimp.MIME_JPEG
|
|
)
|
|
|
|
return base64EncodedImageWithRGBChannels
|
|
} catch (e) {
|
|
console.warn(e)
|
|
}
|
|
}
|
|
async function convertBlackAndWhiteImageToRGBChannels3(base64EncodedImage) {
|
|
try {
|
|
// Load your base64 encoded image
|
|
const image = await Jimp.read(Buffer.from(base64EncodedImage, 'base64'))
|
|
|
|
// Convert your black and white image to RGB channels
|
|
// image.color([{ apply: 'mix', params: ['#ffffff', 100] }])
|
|
|
|
// Get your base64 encoded black and white image with RGB channels
|
|
const base64EncodedImageWithRGBChannels = await image.getBase64Async(
|
|
Jimp.MIME_PNG
|
|
)
|
|
|
|
return base64EncodedImageWithRGBChannels
|
|
} catch (e) {
|
|
console.warn(e)
|
|
}
|
|
}
|
|
|
|
async function snapShotLayer() {
|
|
//snapshot layer with no mask
|
|
let command = [
|
|
// Select All Layers current layer
|
|
{
|
|
_obj: 'selectAllLayers',
|
|
_target: [
|
|
{ _enum: 'ordinal', _ref: 'layer', _value: 'targetEnum' },
|
|
],
|
|
},
|
|
// Duplicate current layer
|
|
// {"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},
|
|
{
|
|
// ID: ids,
|
|
_obj: 'duplicate',
|
|
_target: [
|
|
{ _enum: 'ordinal', _ref: 'layer', _value: 'targetEnum' },
|
|
],
|
|
// version: 5
|
|
},
|
|
|
|
// Merge Layers
|
|
{ _obj: 'mergeLayersNew' },
|
|
// Make
|
|
{
|
|
_obj: 'make',
|
|
at: { _enum: 'channel', _ref: 'channel', _value: 'mask' },
|
|
new: { _class: 'channel' },
|
|
using: { _enum: 'userMaskEnabled', _value: 'revealSelection' },
|
|
},
|
|
// Set Selection
|
|
{
|
|
_obj: 'set',
|
|
_target: [{ _property: 'selection', _ref: 'channel' }],
|
|
to: { _enum: 'ordinal', _ref: 'channel', _value: 'targetEnum' },
|
|
},
|
|
//make a group
|
|
{
|
|
_obj: 'make',
|
|
_target: [
|
|
{
|
|
_ref: 'layerSection',
|
|
},
|
|
],
|
|
from: {
|
|
_ref: 'layer',
|
|
_enum: 'ordinal',
|
|
_value: 'targetEnum',
|
|
},
|
|
layerSectionStart: 512,
|
|
layerSectionEnd: 513,
|
|
name: 'Group 2',
|
|
_options: {
|
|
dialogOptions: 'dontDisplay',
|
|
},
|
|
},
|
|
{
|
|
_obj: 'mergeLayersNew',
|
|
_options: {
|
|
dialogOptions: 'dontDisplay',
|
|
},
|
|
},
|
|
]
|
|
|
|
const result = await batchPlay(command, {
|
|
synchronousExecution: true,
|
|
modalBehavior: 'execute',
|
|
})
|
|
|
|
return result
|
|
}
|
|
|
|
async function snapShotLayerExe() {
|
|
await executeAsModal(async () => {
|
|
//create a fill layer above the background layer, so that it's present in the snapshot
|
|
try {
|
|
const selectionInfo = await psapi.getSelectionInfoExe()
|
|
|
|
// const backgroundLayer = await app.activeDocument.backgroundLayer
|
|
|
|
await psapi.createSolidLayer(255, 255, 255)
|
|
const solid_layer = await app.activeDocument.activeLayers[0]
|
|
// await psapi.unSelectMarqueeExe()//unselect the
|
|
|
|
// await solid_layer.moveAbove(backgroundLayer)
|
|
// await snapShotLayer() //create a layer with only the opaque pixels
|
|
// await psapi.reSelectMarqueeExe(selectionInfo)
|
|
// await solid_layer.delete()
|
|
} catch (e) {
|
|
console.warn(e)
|
|
}
|
|
})
|
|
await executeAsModal(async () => {
|
|
//create a fill layer above the background layer, so that it's present in the snapshot
|
|
try {
|
|
const solid_layer = await app.activeDocument.activeLayers[0]
|
|
const backgroundLayer = await app.activeDocument.backgroundLayer
|
|
await solid_layer.moveAbove(backgroundLayer)
|
|
await psapi.unselectActiveLayersExe()
|
|
await snapShotLayer() //create a layer with only the opaque pixels
|
|
// await psapi.reSelectMarqueeExe(selectionInfo)
|
|
// await psapi.unSelectMarqueeExe()//unselect the
|
|
await solid_layer.delete()
|
|
} catch (e) {
|
|
console.warn(e)
|
|
}
|
|
})
|
|
}
|
|
|
|
class IO {
|
|
// constructor() {}
|
|
static async exportWebp(layer, export_width, export_height) {
|
|
await executeAsModal(async () => {
|
|
//we assume we have a valid layer rectangular image/layer, no transparency
|
|
const doc_entry = await getCurrentDocFolder() //get the main document folder before we switch doc
|
|
const layer_info = await layer_util.Layer.getLayerInfo(layer)
|
|
//*) create a new document
|
|
const new_doc = await IOHelper.createDocumentExe(
|
|
export_width,
|
|
export_height
|
|
)
|
|
const new_layer = await layer_util.Layer.duplicateToDoc(
|
|
layer,
|
|
new_doc
|
|
)
|
|
//*) resize the layer to the same dimension as the document
|
|
|
|
await layer_util.Layer.scaleTo(
|
|
new_layer,
|
|
new_doc.width,
|
|
new_doc.height
|
|
) //
|
|
|
|
await layer_util.Layer.moveTo(new_layer, 0, 0) //move to the top left corner
|
|
//
|
|
await IOHelper.saveAsWebpExe(doc_entry) //save current document as .webp file, save it into doc_entry folder
|
|
await new_doc.closeWithoutSaving()
|
|
})
|
|
}
|
|
static async exportPng() {}
|
|
static async exportDoc() {}
|
|
static async exportLayer() {}
|
|
|
|
static async base64PngToPngFile(
|
|
base64_png,
|
|
folder,
|
|
image_name = 'temp_base64Png.png'
|
|
) {
|
|
const arrayBuffer = _base64ToArrayBuffer(base64_png)
|
|
|
|
// const folder = await storage.localFileSystem.getTemporaryFolder()
|
|
|
|
const file = await folder.createFile(image_name, { overwrite: true })
|
|
|
|
await file.write(arrayBuffer, { format: storage.formats.binary })
|
|
return file
|
|
}
|
|
static async openImageFileAsDocument(file_entry) {
|
|
const new_doc = await app.open(file_entry)
|
|
return new_doc
|
|
}
|
|
static async base64PngToBase64Webp(base64_png) {
|
|
let base64_webp
|
|
try {
|
|
await executeAsModal(async () => {
|
|
try {
|
|
const main_doc_entry = await getCurrentDocFolder()
|
|
//save the base64_png to .png file
|
|
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
|
|
const new_doc = await this.openImageFileAsDocument(png_file)
|
|
//save document as .webp
|
|
const [_, webp_file] = await IOHelper.saveAsWebpExe(
|
|
main_doc_entry
|
|
) //save current document as .webp file, save it into doc_entry folder
|
|
await new_doc.closeWithoutSaving()
|
|
//load/read the .webp file as an arraybuffer
|
|
const ArrayBufferWebp = await webp_file.read({
|
|
format: formats.binary,
|
|
})
|
|
|
|
//convert the arraybuffer to base64Webp string
|
|
|
|
base64_webp = _arrayBufferToBase64(ArrayBufferWebp)
|
|
} catch (e) {
|
|
console.warn(e)
|
|
}
|
|
})
|
|
return base64_webp
|
|
} catch (e) {
|
|
console.warn(e)
|
|
}
|
|
}
|
|
static async base64WebpFromFile(file_entry) {
|
|
//file_entry most be .webp
|
|
let webp_base64
|
|
try {
|
|
await executeAsModal(async () => {
|
|
const arrayBuffer = await file_entry.read({
|
|
format: formats.binary,
|
|
})
|
|
console.log('webp arrayBuffer:', arrayBuffer)
|
|
|
|
const base64_image = _arrayBufferToBase64(arrayBuffer) //convert the buffer to base64
|
|
console.log('base64_image:', base64_image)
|
|
webp_base64 = base64_image
|
|
})
|
|
return [webp_base64, webp_arrayBuffer]
|
|
} catch (e) {
|
|
console.warn(e)
|
|
}
|
|
}
|
|
|
|
static async base64ToLayer(
|
|
base64_png,
|
|
image_name = 'base64_to_layer.png',
|
|
to_x = 0,
|
|
to_y = 0,
|
|
width = 512,
|
|
height = 512,
|
|
format = 'png'
|
|
) {
|
|
let layer
|
|
if (format === 'png') {
|
|
layer = await IOBase64ToLayer.base64PngToLayer(
|
|
base64_png,
|
|
image_name
|
|
)
|
|
|
|
psapi.setVisibleExe(layer, true)
|
|
await layer_util.Layer.scaleTo(layer, width, height) //
|
|
await layer_util.Layer.moveTo(layer, to_x, to_y) //move to the top left corner
|
|
psapi.setVisibleExe(layer, true)
|
|
}
|
|
return layer
|
|
}
|
|
|
|
static async getSelectionFromCanvasAsBase64Silent(
|
|
selectionInfo,
|
|
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)
|
|
}
|
|
}
|
|
static async getSelectionFromCanvasAsBase64NonSilent(
|
|
layer,
|
|
image_name,
|
|
width,
|
|
height
|
|
) {
|
|
try {
|
|
const image_buffer = await psapi.newExportPng(
|
|
layer,
|
|
image_name,
|
|
width,
|
|
height
|
|
)
|
|
|
|
const base64_image = _arrayBufferToBase64(image_buffer) //convert the buffer to base64
|
|
//send the base64 to the server to save the file in the desired directory
|
|
// await sdapi.requestSavePng(base64_image, image_name)
|
|
// await saveFileInSubFolder(base64_image, document_name, image_name)
|
|
|
|
const { requestSavePng } = require('../sdapi_py_re')
|
|
await requestSavePng(base64_image, image_name)
|
|
return base64_image
|
|
} catch (e) {
|
|
console.warn(e)
|
|
}
|
|
}
|
|
static async getSelectionFromCanvasAsBase64Interface(
|
|
width,
|
|
height,
|
|
layer,
|
|
selectionInfo,
|
|
resize = true,
|
|
use_silent_mode = true,
|
|
image_name = 'temp.png'
|
|
) {
|
|
let base64_image
|
|
if (use_silent_mode) {
|
|
base64_image = await this.getSelectionFromCanvasAsBase64Silent(
|
|
selectionInfo,
|
|
resize,
|
|
width,
|
|
height
|
|
)
|
|
} else {
|
|
base64_image = await this.getSelectionFromCanvasAsBase64NonSilent(
|
|
layer,
|
|
image_name,
|
|
width,
|
|
height
|
|
)
|
|
}
|
|
return base64_image
|
|
}
|
|
static async getSelectionFromCanvasAsBase64Interface_New(
|
|
width,
|
|
height,
|
|
selectionInfo,
|
|
resize = true,
|
|
image_name = 'temp.png'
|
|
) {
|
|
//use this version, it has less parameters
|
|
const use_silent_mode = html_manip.getUseSilentMode()
|
|
let layer = null
|
|
if (!use_silent_mode) {
|
|
await psapi.snapshot_layerExe()
|
|
const snapshotLayer = await app.activeDocument.activeLayers[0]
|
|
layer = snapshotLayer
|
|
}
|
|
let base64_image
|
|
if (use_silent_mode) {
|
|
base64_image = await this.getSelectionFromCanvasAsBase64Silent(
|
|
selectionInfo,
|
|
resize,
|
|
width,
|
|
height
|
|
)
|
|
} else {
|
|
base64_image = await this.getSelectionFromCanvasAsBase64NonSilent(
|
|
layer,
|
|
image_name,
|
|
width,
|
|
height
|
|
)
|
|
}
|
|
await layer_util.deleteLayers([layer]) //delete the snapshot layer if it exists
|
|
return base64_image
|
|
}
|
|
|
|
static async urlToLayer(image_url, image_file_name = 'image_from_url.png') {
|
|
try {
|
|
await psapi.unselectActiveLayersExe()
|
|
const temp_entry = await fs.getTemporaryFolder()
|
|
await downloadItExe(image_url, temp_entry, image_file_name)
|
|
} catch (e) {
|
|
console.warn('urlToLayer()', image_url, image_file_name, e)
|
|
}
|
|
}
|
|
}
|
|
|
|
class IOHelper {
|
|
static async saveAsWebp(doc_entry) {
|
|
//doc_entry must be in dataFolder or tempFolder
|
|
//save document as webp
|
|
const document_id = app.activeDocument.id
|
|
|
|
// doc_entry = await getCurrentDocFolder()
|
|
const file_entry = await doc_entry.createFile('temp.webp', {
|
|
overwrite: true,
|
|
})
|
|
|
|
const token = await fs.createSessionToken(file_entry)
|
|
const result = await batchPlay(
|
|
[
|
|
{
|
|
_obj: 'save',
|
|
as: {
|
|
_obj: 'WebPFormat',
|
|
compression: {
|
|
_enum: 'WebPCompression',
|
|
_value: 'compressionLossless',
|
|
},
|
|
includeXMPData: false,
|
|
includeEXIFData: false,
|
|
includePsExtras: false,
|
|
},
|
|
in: {
|
|
_path: token,
|
|
_kind: 'local',
|
|
},
|
|
documentID: 59,
|
|
copy: true,
|
|
lowerCase: true,
|
|
saveStage: {
|
|
_enum: 'saveStageType',
|
|
_value: 'saveBegin',
|
|
},
|
|
_options: {
|
|
dialogOptions: 'dontDisplay',
|
|
},
|
|
},
|
|
],
|
|
{
|
|
synchronousExecution: true,
|
|
modalBehavior: 'execute',
|
|
}
|
|
)
|
|
|
|
return [result, file_entry]
|
|
}
|
|
|
|
static async saveAsWebpExe(doc_entry) {
|
|
let result
|
|
let file_entry
|
|
await executeAsModal(async () => {
|
|
;[result, file_entry] = await this.saveAsWebp(doc_entry)
|
|
})
|
|
return [result, file_entry]
|
|
}
|
|
static async createDocumentExe(width, height) {
|
|
let new_doc
|
|
try {
|
|
await executeAsModal(async () => {
|
|
new_doc = await app.documents.add({
|
|
width: width,
|
|
height: height,
|
|
resolution: await app.activeDocument.resolution,
|
|
mode: 'RGBColorMode',
|
|
fill: 'transparent',
|
|
})
|
|
})
|
|
} catch (e) {
|
|
console.warn(e)
|
|
}
|
|
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
|
|
// crop_w - 1,
|
|
// crop_h - 1
|
|
)
|
|
|
|
let resized_img
|
|
if (b_resize) {
|
|
resized_img = await cropped_img.resize(
|
|
resize_width,
|
|
resize_height,
|
|
// Jimp.RESIZE_BILINEAR
|
|
// Jimp.RESIZE_NEAREST_NEIGHBOR
|
|
settings_tab_ts.store.data.scale_interpolation_method
|
|
.jimp
|
|
)
|
|
} 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 {
|
|
static {}
|
|
static async base64PngToLayer(base64_png, image_name) {
|
|
//unselect all layers so that the imported layer get place at the top of the document
|
|
await psapi.unselectActiveLayersExe()
|
|
|
|
const imported_layer = await base64ToFile(base64_png, image_name) //silent import into the document
|
|
|
|
return imported_layer
|
|
}
|
|
}
|
|
class IOFolder {
|
|
static {}
|
|
static async createSettingsFolder() {
|
|
//create a folder named "Settings" in the DataFolder
|
|
let settings_entry
|
|
await executeAsModal(async () => {
|
|
settings_entry = await this.createFolderSafe('Settings')
|
|
})
|
|
return settings_entry
|
|
}
|
|
static async findOrCreateFolderExe(folder_name) {
|
|
//create a folder named "Settings" in the DataFolder
|
|
let folder_entry
|
|
await executeAsModal(async () => {
|
|
folder_entry = await this.createFolderSafe(folder_name)
|
|
})
|
|
return folder_entry
|
|
}
|
|
|
|
static async doesFolderExist(folder_name) {
|
|
//check if folder exist. return true if it does. false if it doesn't.
|
|
const data_folder = await fs.getDataFolder()
|
|
let b_exist = false
|
|
let folder
|
|
try {
|
|
folder = await data_folder.getEntry(folder_name)
|
|
b_exist = true
|
|
} catch (e) {
|
|
// console.warn(e)
|
|
b_exist = false
|
|
}
|
|
return b_exist
|
|
}
|
|
|
|
static async createFolderSafe(folder_name) {
|
|
//will always return a folder. it will create the folder if it doesn't exist.
|
|
try {
|
|
// const uuid = await getUniqueDocumentId()
|
|
const data_folder = await fs.getDataFolder()
|
|
|
|
let folder_entry
|
|
try {
|
|
folder_entry = await data_folder.getEntry(folder_name)
|
|
} catch (e) {
|
|
console.warn(e)
|
|
//create document folder
|
|
folder_entry = await data_folder.createFolder(folder_name)
|
|
}
|
|
|
|
return folder_entry
|
|
} catch (e) {
|
|
console.warn(e)
|
|
}
|
|
}
|
|
|
|
static async getDocumentFolderNativePath() {
|
|
try {
|
|
const uuid = await getUniqueDocumentId()
|
|
|
|
let doc_folder = await this.getDocFolder(uuid)
|
|
const path = general.fixNativePath(doc_folder.nativePath)
|
|
return path
|
|
} catch (e) {
|
|
console.warn(e)
|
|
}
|
|
return ''
|
|
}
|
|
|
|
static async getDocFolder(doc_uuid) {
|
|
//will create folder if does not exist. always return a folder entry
|
|
const doc_entry = await getDocFolder(doc_uuid)
|
|
return doc_entry
|
|
}
|
|
static async getSettingsFolder() {
|
|
//will create folder if does not exist. always return a folder entry
|
|
const settings_entry = await this.createSettingsFolder()
|
|
return settings_entry
|
|
}
|
|
static async getPresetFolder() {
|
|
//will create folder if does not exist. always return a folder entry
|
|
const preset_entry = await this.findOrCreateFolderExe('Preset')
|
|
return preset_entry
|
|
}
|
|
static async getCustomPresetFolder(
|
|
custom_preset_folder_name = 'custom_preset'
|
|
) {
|
|
//will create folder if does not exist. always return a folder entry
|
|
const preset_entry = await this.findOrCreateFolderExe(
|
|
custom_preset_folder_name
|
|
)
|
|
return preset_entry
|
|
}
|
|
static async createFolderIfDoesNotExist(folder_name) {
|
|
try {
|
|
await executeAsModal(async () => {
|
|
try {
|
|
const folder = await fs.getDataFolder()
|
|
const sub_folder = await folder.createFolder(folder_name)
|
|
} catch (e) {
|
|
console.warn(e)
|
|
}
|
|
})
|
|
} catch (e) {
|
|
console.warn(e)
|
|
}
|
|
}
|
|
}
|
|
|
|
class IOLog {
|
|
static {}
|
|
static async saveLogToFile(json, file_name) {
|
|
try {
|
|
const plugin_folder = await fs.getDataFolder()
|
|
const file = await plugin_folder.createFile(file_name, {
|
|
type: storage.types.file,
|
|
overwrite: true,
|
|
})
|
|
|
|
const JSONInPrettyFormat = JSON.stringify(json, undefined, 4)
|
|
await file.write(JSONInPrettyFormat, {
|
|
format: storage.formats.utf8,
|
|
append: true,
|
|
})
|
|
} catch (e) {
|
|
console.warn(e)
|
|
}
|
|
}
|
|
}
|
|
class IOJson {
|
|
static {}
|
|
static async saveJsonToFile(json, folder_entry, file_name) {
|
|
try {
|
|
const file = await folder_entry.createFile(file_name, {
|
|
type: storage.types.file,
|
|
overwrite: true,
|
|
})
|
|
|
|
const JSONInPrettyFormat = JSON.stringify(json, undefined, 4)
|
|
await file.write(JSONInPrettyFormat, {
|
|
format: storage.formats.utf8,
|
|
append: false,
|
|
})
|
|
} catch (e) {
|
|
console.warn(e)
|
|
}
|
|
}
|
|
|
|
static async saveJsonToFileExe(json, folder_entry, file_name) {
|
|
await executeAsModal(async () => {
|
|
await this.saveJsonToFile(json, folder_entry, file_name)
|
|
})
|
|
}
|
|
static async loadJsonFromFile(folder_entry, file_name) {
|
|
const json_file_name = file_name
|
|
|
|
try {
|
|
const json_entry = await folder_entry.getEntry(json_file_name)
|
|
if (json_entry) {
|
|
const json = JSON.parse(
|
|
await json_entry.read({
|
|
format: storage.formats.utf8,
|
|
})
|
|
)
|
|
return json
|
|
}
|
|
} catch (e) {
|
|
console.warn(e)
|
|
}
|
|
}
|
|
|
|
static async saveSettingsToFile(settings_json, settings_file_name) {
|
|
await executeAsModal(async () => {
|
|
const folder_entry = await IOFolder.getSettingsFolder('Settings')
|
|
await this.saveJsonToFile(
|
|
settings_json,
|
|
folder_entry,
|
|
settings_file_name
|
|
)
|
|
})
|
|
}
|
|
static async loadSettingsFromFile(settings_file_name) {
|
|
const folder_entry = await IOFolder.getSettingsFolder('Settings')
|
|
const settings_json = await this.loadJsonFromFile(
|
|
folder_entry,
|
|
settings_file_name
|
|
)
|
|
return settings_json
|
|
}
|
|
static async saveHordeSettingsToFile(settings_json) {
|
|
const settings_file_name = 'horde_settings.json'
|
|
await this.saveSettingsToFile(settings_json, settings_file_name)
|
|
}
|
|
static async loadHordeSettingsFromFile() {
|
|
const settings_file_name = 'horde_settings.json'
|
|
const settings_json = await this.loadSettingsFromFile(
|
|
settings_file_name
|
|
)
|
|
return settings_json
|
|
}
|
|
|
|
static async getJsonEntries(doc_entry) {
|
|
let entries = await doc_entry.getEntries()
|
|
const json_entries = entries.filter(
|
|
(e) => e.isFile && e.name.toLowerCase().includes('.json') // must be a file and has the of the type .json
|
|
)
|
|
console.log('json_entries: ', json_entries)
|
|
// .forEach((e) => console.log(e.name))
|
|
return json_entries
|
|
}
|
|
static async deleteFile(doc_entry, file_name) {
|
|
try {
|
|
const file_entry = await doc_entry.getEntry(file_name)
|
|
file_entry.delete()
|
|
} catch (e) {}
|
|
}
|
|
}
|
|
|
|
async function createThumbnail(base64Image, width = 100) {
|
|
const image = await Jimp.read(Buffer.from(base64Image, 'base64'))
|
|
image.resize(
|
|
width,
|
|
Jimp.AUTO,
|
|
settings_tab_ts.store.data.scale_interpolation_method.jimp
|
|
)
|
|
const thumbnail = await image.getBase64Async(Jimp.MIME_PNG)
|
|
return thumbnail
|
|
}
|
|
|
|
async function getImageFromCanvas() {
|
|
const width = html_manip.getWidth()
|
|
const height = html_manip.getHeight()
|
|
const selectionInfo = await psapi.getSelectionInfoExe()
|
|
const base64 = await io.IO.getSelectionFromCanvasAsBase64Interface_New(
|
|
width,
|
|
height,
|
|
selectionInfo,
|
|
true
|
|
)
|
|
return base64
|
|
}
|
|
async function getBase64FromJimp(jimp_image) {
|
|
const dataURL = await jimp_image.getBase64Async(Jimp.MIME_PNG)
|
|
const base64 = dataURL.replace(/^data:image\/png;base64,/, '')
|
|
return base64
|
|
}
|
|
|
|
function transparentToMask(x, y, idx) {
|
|
const alpha = this.bitmap.data[idx + 3]
|
|
let color
|
|
if (alpha === 0) {
|
|
color = 0xffffffff
|
|
} else if (alpha === 255) {
|
|
color = 0x000000ff
|
|
} else {
|
|
color = Jimp.rgbaToInt(alpha, alpha, alpha, 255)
|
|
}
|
|
this.setPixelColor(color, x, y)
|
|
}
|
|
function inpaintTransparentToMask(x, y, idx) {
|
|
const alpha = this.bitmap.data[idx + 3]
|
|
let color
|
|
// if (alpha === 0) {
|
|
// color = 0x000000ff
|
|
// } else if (alpha === 255) {
|
|
// color = 0xffffffff
|
|
// } else {
|
|
// color = Jimp.rgbaToInt(alpha, alpha, alpha, 255)
|
|
// }
|
|
|
|
if (alpha === 0) {
|
|
color = 0x000000ff
|
|
} else {
|
|
color = 0xffffffff
|
|
}
|
|
this.setPixelColor(color, x, y)
|
|
}
|
|
function transparentToWhiteBackground(x, y, idx) {
|
|
const alpha = this.bitmap.data[idx + 3]
|
|
let color
|
|
if (alpha === 0) {
|
|
color = 0xffffffff
|
|
} else {
|
|
color = Jimp.rgbaToInt(
|
|
this.bitmap.data[idx],
|
|
this.bitmap.data[idx + 1],
|
|
this.bitmap.data[idx + 2],
|
|
255
|
|
) // remove transparency but keep the color, This is bad. used as workaround Auto1111 not able to handle alpha channels
|
|
}
|
|
this.setPixelColor(color, x, y)
|
|
}
|
|
async function getMask() {
|
|
try {
|
|
let b = app.activeDocument.backgroundLayer
|
|
await executeAsModal(() => (b.visible = false))
|
|
const base64 = await getImageFromCanvas()
|
|
await executeAsModal(() => (b.visible = true))
|
|
const jimp_image = await Jimp.read(Buffer.from(base64, 'base64'))
|
|
|
|
const jimp_mask = await jimp_image.scan(
|
|
0,
|
|
0,
|
|
jimp_image.bitmap.width,
|
|
jimp_image.bitmap.height,
|
|
transparentToMask
|
|
)
|
|
html_manip.setInitImageSrc(
|
|
await jimp_mask.getBase64Async(Jimp.MIME_PNG)
|
|
)
|
|
const mask = await getBase64FromJimp(jimp_mask)
|
|
return mask
|
|
} catch (e) {
|
|
console.warn(e)
|
|
}
|
|
}
|
|
|
|
async function getImg2ImgInitImage() {
|
|
//the init image will has transparent pixel in it
|
|
//the mask will be a grayscale image/white and black
|
|
try {
|
|
let b = app.activeDocument.backgroundLayer
|
|
await executeAsModal(() => (b.visible = false))
|
|
const base64 = await getImageFromCanvas()
|
|
await executeAsModal(() => (b.visible = true))
|
|
const init_image = base64
|
|
|
|
html_manip.setInitImageSrc(general.base64ToBase64Url(init_image)) // convert jimp_image to img.src data
|
|
|
|
// console.log('mask: ', mask)
|
|
return init_image
|
|
} catch (e) {
|
|
console.warn(e)
|
|
}
|
|
}
|
|
async function getOutpaintInitImageAndMask() {
|
|
//the init image will has transparent pixel in it
|
|
//the mask will be a grayscale image/white and black
|
|
try {
|
|
let b = app.activeDocument.backgroundLayer
|
|
await executeAsModal(() => (b.visible = false))
|
|
const base64 = await getImageFromCanvas()
|
|
await executeAsModal(() => (b.visible = true))
|
|
const init_image = base64
|
|
let jimp_init = await Jimp.read(Buffer.from(base64, 'base64'))
|
|
|
|
let jimp_mask = await jimp_init
|
|
.clone()
|
|
.scan(
|
|
0,
|
|
0,
|
|
jimp_init.bitmap.width,
|
|
jimp_init.bitmap.height,
|
|
transparentToMask
|
|
)
|
|
// jimp_init = await jimp_init.scan(
|
|
// 0,
|
|
// 0,
|
|
// jimp_init.bitmap.width,
|
|
// jimp_init.bitmap.height,
|
|
// transparentToWhiteBackground
|
|
// // transparentToMask
|
|
// )
|
|
html_manip.setInitImageMaskSrc(
|
|
await jimp_mask.getBase64Async(Jimp.MIME_PNG)
|
|
) // convert jimp_image to img.src data
|
|
html_manip.setInitImageSrc(
|
|
await jimp_init.getBase64Async(Jimp.MIME_PNG)
|
|
) // convert jimp_image to img.src data
|
|
|
|
const mask = await getBase64FromJimp(jimp_mask)
|
|
// console.log('mask: ', mask)
|
|
return {
|
|
init_image,
|
|
mask,
|
|
}
|
|
} catch (e) {
|
|
console.warn(e)
|
|
}
|
|
}
|
|
|
|
async function getInpaintInitImageAndMask() {
|
|
try {
|
|
await executeAsModal(async () => await layer_util.toggleActiveLayer()) //only white mark layer should be visible
|
|
const mask_base64 = await getImageFromCanvas()
|
|
await executeAsModal(async () => {
|
|
await layer_util.toggleActiveLayer() // undo the toggling operation, active layer will be visible
|
|
app.activeDocument.activeLayers[0].visible = false //hide the white mark
|
|
})
|
|
const init_base64 = await getImageFromCanvas()
|
|
|
|
let jimp_mask = await Jimp.read(Buffer.from(mask_base64, 'base64')) //make jimp object
|
|
let jimp_init = await Jimp.read(Buffer.from(init_base64, 'base64')) //make jimp object, jimp_init will have transparent pixels, should we convert to white??
|
|
|
|
jimp_mask = await jimp_mask.scan(
|
|
0,
|
|
0,
|
|
jimp_mask.bitmap.width,
|
|
jimp_mask.bitmap.height,
|
|
inpaintTransparentToMask
|
|
) //convert transparent image to black and white image
|
|
|
|
html_manip.setInitImageMaskSrc(
|
|
await jimp_mask.getBase64Async(Jimp.MIME_PNG)
|
|
)
|
|
html_manip.setInitImageSrc(
|
|
await jimp_init.getBase64Async(Jimp.MIME_PNG)
|
|
)
|
|
|
|
const mask = await getBase64FromJimp(jimp_mask)
|
|
const init_image = await getBase64FromJimp(jimp_init)
|
|
return { init_image, mask }
|
|
} catch (e) {
|
|
console.warn(e)
|
|
}
|
|
}
|
|
|
|
async function saveFileInSubFolder(b64Image, sub_folder_name, file_name) {
|
|
// const b64Image =
|
|
// 'iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAIAAADTED8xAAADMElEQVR4nOzVwQnAIBQFQYXff81RUkQCOyDj1YOPnbXWPmeTRef+/3O/OyBjzh3CD95BfqICMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMO0TAAD//2Anhf4QtqobAAAAAElFTkSuQmCC'
|
|
|
|
const img = _base64ToArrayBuffer(b64Image)
|
|
|
|
// const img_name = 'temp_output_image.png'
|
|
const img_name = file_name
|
|
const folder = await storage.localFileSystem.getDataFolder()
|
|
const documentFolderName = sub_folder_name
|
|
let documentFolder
|
|
try {
|
|
documentFolder = await folder.getEntry(documentFolderName)
|
|
} catch (e) {
|
|
console.warn(e)
|
|
//create document folder
|
|
documentFolder = await folder.createFolder(documentFolderName)
|
|
}
|
|
|
|
console.log('documentFolder.nativePath: ', documentFolder.nativePath)
|
|
const file = await documentFolder.createFile(img_name, { overwrite: true })
|
|
|
|
await file.write(img, { format: storage.formats.binary })
|
|
|
|
const token = await storage.localFileSystem.createSessionToken(file) // batchPlay requires a token on _path
|
|
}
|
|
//REFACTOR: move to document.js
|
|
async function saveJsonFileInSubFolder(json, sub_folder_name, file_name) {
|
|
// const b64Image =
|
|
// 'iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAIAAADTED8xAAADMElEQVR4nOzVwQnAIBQFQYXff81RUkQCOyDj1YOPnbXWPmeTRef+/3O/OyBjzh3CD95BfqICMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMO0TAAD//2Anhf4QtqobAAAAAElFTkSuQmCC'
|
|
|
|
// const img_name = 'temp_output_image.png'
|
|
|
|
const json_file_name = file_name
|
|
|
|
const folder = await storage.localFileSystem.getDataFolder()
|
|
const documentFolderName = sub_folder_name
|
|
let documentFolder
|
|
try {
|
|
documentFolder = await folder.getEntry(documentFolderName)
|
|
} catch (e) {
|
|
console.warn(e)
|
|
//create document folder
|
|
documentFolder = await folder.createFolder(documentFolderName)
|
|
}
|
|
|
|
console.log('documentFolder.nativePath: ', documentFolder.nativePath)
|
|
const file = await documentFolder.createFile(json_file_name, {
|
|
type: storage.types.file,
|
|
overwrite: true,
|
|
})
|
|
|
|
const JSONInPrettyFormat = JSON.stringify(json, undefined, 4)
|
|
await file.write(JSONInPrettyFormat, {
|
|
format: storage.formats.utf8,
|
|
append: false,
|
|
})
|
|
|
|
const token = await storage.localFileSystem.createSessionToken(file) // batchPlay requires a token on _path
|
|
}
|
|
async function fixTransparentEdges(base64) {
|
|
function transparentToOpaque(x, y, idx) {
|
|
const alpha = this.bitmap.data[idx + 3]
|
|
if (alpha > 0 && alpha < 255) {
|
|
this.bitmap.data[idx + 3] = 0 //make semi transparent pixels completely transparent
|
|
}
|
|
}
|
|
|
|
try {
|
|
let jimp_img = await Jimp.read(Buffer.from(base64, 'base64'))
|
|
|
|
jimp_img = await jimp_img.scan(
|
|
0,
|
|
0,
|
|
jimp_img.bitmap.width,
|
|
jimp_img.bitmap.height,
|
|
transparentToOpaque
|
|
)
|
|
const opaque_base64 = await getBase64FromJimp(jimp_img)
|
|
return opaque_base64
|
|
} catch (e) {
|
|
console.warn(e)
|
|
}
|
|
}
|
|
|
|
async function maskFromInitImage(base64) {
|
|
function setTransparentToBlack(x, y, idx) {
|
|
let alpha = this.bitmap.data[idx + 3]
|
|
if (alpha !== 0) {
|
|
this.bitmap.data[idx] = 0
|
|
this.bitmap.data[idx + 1] = 0
|
|
this.bitmap.data[idx + 2] = 0
|
|
this.bitmap.data[idx + 3] = 255
|
|
} else {
|
|
//alpha === 0
|
|
|
|
this.bitmap.data[idx] = 255
|
|
this.bitmap.data[idx + 1] = 255
|
|
this.bitmap.data[idx + 2] = 255
|
|
this.bitmap.data[idx + 3] = 255
|
|
}
|
|
}
|
|
|
|
try {
|
|
let jimp_img = await Jimp.read(Buffer.from(base64, 'base64'))
|
|
|
|
jimp_img = await jimp_img.scan(
|
|
0,
|
|
0,
|
|
jimp_img.bitmap.width,
|
|
jimp_img.bitmap.height,
|
|
setTransparentToBlack
|
|
)
|
|
const mask_base64 = await getBase64FromJimp(jimp_img)
|
|
return mask_base64
|
|
} catch (e) {
|
|
console.warn(e)
|
|
}
|
|
}
|
|
async function fixMaskEdges(base64) {
|
|
function grayScaleToBlack(x, y, idx) {
|
|
if (
|
|
this.bitmap.data[idx] !== 255 ||
|
|
this.bitmap.data[idx + 1] !== 255 ||
|
|
this.bitmap.data[idx + 2] !== 255
|
|
) {
|
|
this.bitmap.data[idx] = 0
|
|
this.bitmap.data[idx + 1] = 0
|
|
this.bitmap.data[idx + 2] = 0
|
|
}
|
|
}
|
|
|
|
try {
|
|
let jimp_img = await Jimp.read(Buffer.from(base64, 'base64'))
|
|
|
|
jimp_img = await jimp_img.scan(
|
|
0,
|
|
0,
|
|
jimp_img.bitmap.width,
|
|
jimp_img.bitmap.height,
|
|
grayScaleToBlack
|
|
)
|
|
const opaque_base64 = await getBase64FromJimp(jimp_img)
|
|
return opaque_base64
|
|
} catch (e) {
|
|
console.warn(e)
|
|
}
|
|
}
|
|
|
|
async function getUniqueDocumentId() {
|
|
try {
|
|
let uniqueDocumentId = await psapi.readUniqueDocumentIdExe()
|
|
|
|
console.log(
|
|
'getUniqueDocumentId(): uniqueDocumentId: ',
|
|
uniqueDocumentId
|
|
)
|
|
|
|
// Regular expression to check if string is a valid UUID
|
|
const regexExp =
|
|
/^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/gi
|
|
|
|
// String with valid UUID separated by dash
|
|
// const str = 'a24a6ea4-ce75-4665-a070-57453082c256'
|
|
|
|
const isValidId = regexExp.test(uniqueDocumentId) // true
|
|
console.log('isValidId: ', isValidId)
|
|
if (isValidId == false) {
|
|
let uuid = self.crypto.randomUUID()
|
|
console.log(uuid) // for example "36b8f84d-df4e-4d49-b662-bcde71a8764f"
|
|
await psapi.saveUniqueDocumentIdExe(uuid)
|
|
uniqueDocumentId = uuid
|
|
}
|
|
return uniqueDocumentId
|
|
} catch (e) {
|
|
console.warn('warning Document Id may not be valid', e)
|
|
}
|
|
}
|
|
async function getImageSize(base64) {
|
|
const image = await Jimp.read(Buffer.from(base64, 'base64'))
|
|
const width = image.bitmap.width
|
|
const height = image.bitmap.height
|
|
return { width, height }
|
|
}
|
|
async function convertGrayscaleToMonochrome(base64) {
|
|
function grayToMonoPixel(x, y, idx) {
|
|
// convert any grayscale value to white, resulting in black and white image
|
|
|
|
// if (this.bitmap.data[idx] > 0) {
|
|
// this.bitmap.data[idx] = 255
|
|
// }
|
|
// if (this.bitmap.data[idx + 1] > 0) {
|
|
// this.bitmap.data[idx + 1] = 255
|
|
// }
|
|
// if (this.bitmap.data[idx + 2] > 0) {
|
|
// this.bitmap.data[idx + 2] = 255
|
|
// }
|
|
let color
|
|
if (
|
|
this.bitmap.data[idx] !== 0 &&
|
|
this.bitmap.data[idx + 1] !== 0 &&
|
|
this.bitmap.data[idx + 2] !== 0
|
|
) {
|
|
color = 0xffffffff
|
|
} else {
|
|
color = 0x000000ff
|
|
}
|
|
this.setPixelColor(color, x, y)
|
|
}
|
|
try {
|
|
const jimp_image = await Jimp.read(Buffer.from(base64, 'base64'))
|
|
|
|
const jimp_mask = await jimp_image.scan(
|
|
0,
|
|
0,
|
|
jimp_image.bitmap.width,
|
|
jimp_image.bitmap.height,
|
|
grayToMonoPixel
|
|
)
|
|
const base64_monochrome_mask = await getBase64FromJimp(jimp_mask)
|
|
return base64_monochrome_mask
|
|
} catch (e) {
|
|
console.warn(e)
|
|
}
|
|
}
|
|
module.exports = {
|
|
IO,
|
|
snapShotLayerExe,
|
|
IOHelper,
|
|
IOJson,
|
|
IOFolder,
|
|
IOLog,
|
|
convertBlackAndWhiteImageToRGBChannels,
|
|
convertBlackAndWhiteImageToRGBChannels2,
|
|
convertBlackAndWhiteImageToRGBChannels3,
|
|
isBlackAndWhiteImage,
|
|
createThumbnail,
|
|
getMask,
|
|
getOutpaintInitImageAndMask,
|
|
getInpaintInitImageAndMask,
|
|
getImg2ImgInitImage,
|
|
saveFileInSubFolder,
|
|
saveJsonFileInSubFolder,
|
|
fixTransparentEdges,
|
|
fixMaskEdges,
|
|
maskFromInitImage,
|
|
getImageFromCanvas,
|
|
getUniqueDocumentId,
|
|
getImageSize,
|
|
convertGrayscaleToMonochrome,
|
|
}
|