add thumbnail functionality to CtrlNet annotated image
parent
95fa58cb6a
commit
b3f94ab4f0
|
|
@ -0,0 +1,36 @@
|
|||
|
||||
<svg
|
||||
version="1.0"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="18.000000pt"
|
||||
height="18.000000pt"
|
||||
viewBox="0 0 127.000000 127.000000"
|
||||
preserveAspectRatio="xMidYMid meet"
|
||||
style="
|
||||
width: 32px;
|
||||
height: 27px;
|
||||
position: absolute;
|
||||
top: 3px;
|
||||
left: -1px;
|
||||
"
|
||||
>
|
||||
<g
|
||||
transform="translate(0.000000,115.000000) scale(0.100000,-0.100000)"
|
||||
fill="#000000"
|
||||
stroke="none"
|
||||
>
|
||||
<path
|
||||
d="M577 1172 c-10 -11 -17 -36 -17 -60 l0 -42 -133 0 c-117 0 -136 -2
|
||||
-150 -18 -15 -16 -17 -49 -17 -254 l0 -236 -24 -6 c-53 -13 -74 -67 -38 -99
|
||||
15 -13 39 -17 115 -17 53 0 97 -4 97 -9 0 -5 -13 -69 -30 -143 -35 -155 -36
|
||||
-169 -12 -191 45 -41 84 -11 104 78 l13 60 150 0 150 0 13 -60 c15 -67 35 -95
|
||||
67 -95 27 0 55 29 55 56 0 11 -13 78 -30 150 -16 71 -30 135 -30 142 0 9 26
|
||||
12 98 12 83 0 102 3 115 18 33 36 14 85 -39 98 l-24 6 0 238 c0 217 -2 238
|
||||
-18 253 -15 14 -42 17 -150 17 l-132 0 0 43 c0 30 -6 49 -18 60 -26 23 -94 22
|
||||
-115 -1z m393 -377 l0 -235 -335 0 -335 0 0 235 0 235 335 0 335 0 0 -235z
|
||||
m77 -291 c3 -9 0 -20 -8 -25 -18 -11 -790 -11 -808 0 -8 5 -11 16 -8 25 6 14
|
||||
49 16 412 16 363 0 406 -2 412 -16z m-293 -133 c9 -39 16 -75 16 -80 0 -7 -47
|
||||
-11 -135 -11 -88 0 -135 4 -135 11 0 5 7 41 16 80 l16 69 103 0 103 0 16 -69z"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
<svg
|
||||
viewBox="0 0 36 36"
|
||||
style="width: 18px; height: 18px"
|
||||
>
|
||||
<path
|
||||
d="M33.567 8.2L27.8 2.432a1.215 1.215 0 0 0-.866-.353H26.9a1.371 1.371 0 0 0-.927.406L5.084 23.372a.99.99 0 0 0-.251.422L2.055 33.1c-.114.377.459.851.783.851a.251.251 0 0 0 .062-.007c.276-.063 7.866-2.344 9.311-2.778a.972.972 0 0 0 .414-.249l20.888-20.889a1.372 1.372 0 0 0 .4-.883 1.221 1.221 0 0 0-.346-.945zM11.4 29.316c-2.161.649-4.862 1.465-6.729 2.022l2.009-6.73z"
|
||||
/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 729 B |
|
|
@ -0,0 +1,56 @@
|
|||
<svg
|
||||
version="1.0"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="512.000000pt"
|
||||
height="512.000000pt"
|
||||
viewBox="0 0 512.000000 512.000000"
|
||||
preserveAspectRatio="xMidYMid meet"
|
||||
style="
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: -1px;
|
||||
"
|
||||
>
|
||||
<g
|
||||
transform="translate(0.000000,512.000000) scale(0.100000,-0.100000)"
|
||||
fill="#000000"
|
||||
stroke="none"
|
||||
>
|
||||
<path
|
||||
d="M920 4311 c-118 -36 -212 -129 -259 -254 -18 -50 -21 -79 -21 -217
|
||||
l0 -160 80 0 80 0 0 128 c0 147 14 208 60 264 51 62 99 78 231 78 63 0 131 3
|
||||
152 6 l37 7 0 78 0 79 -167 -1 c-93 0 -179 -4 -193 -8z"
|
||||
/>
|
||||
<path
|
||||
d="M3840 4242 l0 -79 38 -7 c20 -3 88 -6 151 -6 132 0 180 -16 231 -78
|
||||
46 -56 60 -117 60 -264 l0 -128 80 0 80 0 0 158 c0 131 -3 169 -19 215 -36
|
||||
104 -104 182 -204 234 -50 27 -58 28 -234 31 l-183 4 0 -80z"
|
||||
/>
|
||||
<path
|
||||
d="M2450 3404 c-252 -30 -471 -107 -694 -243 -199 -122 -420 -320 -578
|
||||
-519 -32 -40 -58 -79 -58 -85 0 -20 105 -146 213 -256 296 -302 597 -483 937
|
||||
-562 122 -29 364 -37 495 -16 318 51 613 200 903 457 102 90 249 249 310 334
|
||||
l32 44 -47 62 c-67 90 -253 281 -358 368 -248 208 -538 351 -802 397 -90 16
|
||||
-290 27 -353 19z m279 -317 c189 -54 340 -214 386 -409 79 -338 -192 -670
|
||||
-549 -669 -158 0 -278 47 -390 151 -123 116 -177 238 -178 400 0 161 54 284
|
||||
178 400 153 143 345 187 553 127z"
|
||||
/>
|
||||
<path
|
||||
d="M2485 2841 c-59 -17 -86 -31 -129 -71 -153 -141 -103 -397 92 -471
|
||||
116 -43 262 -7 333 82 46 59 62 106 63 184 0 52 -6 82 -23 117 -27 55 -94 121
|
||||
-148 143 -45 19 -146 28 -188 16z"
|
||||
/>
|
||||
<path
|
||||
d="M640 1280 c0 -138 3 -167 21 -217 40 -107 103 -178 202 -230 50 -27
|
||||
58 -28 235 -31 l182 -4 0 80 0 79 -37 7 c-21 3 -89 6 -152 6 -132 0 -180 16
|
||||
-231 78 -46 56 -60 117 -60 264 l0 128 -80 0 -80 0 0 -160z"
|
||||
/>
|
||||
<path
|
||||
d="M4320 1312 c0 -147 -14 -208 -60 -264 -51 -62 -99 -78 -231 -78 -63
|
||||
0 -131 -3 -151 -6 l-38 -7 0 -79 0 -80 183 4 c176 3 184 4 234 31 99 52 162
|
||||
123 202 230 18 50 21 79 21 217 l0 160 -80 0 -80 0 0 -128z"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.3 KiB |
|
|
@ -1,13 +1,15 @@
|
|||
import { observer } from 'mobx-react';
|
||||
import React from 'react';
|
||||
import { SpCheckBox, SpMenu, SpSlider } from '../util/elements';
|
||||
import { MoveToCanvasSvg,ActionButtonSVG, SpCheckBox, SpMenu, SpSlider, Thumbnail, PenSvg, PreviewSvg } from '../util/elements';
|
||||
import ControlNetStore from './store';
|
||||
import { mapRange, versionCompare } from './util';
|
||||
import { note, selection } from '../util/oldSystem';
|
||||
import { note, selection, html_manip, psapi,api, general } from '../util/oldSystem';
|
||||
|
||||
|
||||
declare const g_generation_session: any;
|
||||
declare const io: any;
|
||||
declare const app: any;
|
||||
declare let g_sd_url: string;
|
||||
|
||||
|
||||
@observer
|
||||
|
|
@ -116,6 +118,159 @@ export default class ControlNetUnit extends React.Component<{ index: number, app
|
|||
}
|
||||
}
|
||||
|
||||
async requestControlNetDetectMap(
|
||||
controlnet_init_image:string,
|
||||
_module:string,
|
||||
processor_res:number,
|
||||
threshold_a:number,
|
||||
threshold_b:number
|
||||
) {
|
||||
try {
|
||||
const payload = {
|
||||
controlnet_module: _module,
|
||||
controlnet_input_images: [controlnet_init_image],
|
||||
controlnet_processor_res: processor_res,
|
||||
controlnet_threshold_a: threshold_a,
|
||||
controlnet_threshold_b: threshold_b,
|
||||
}
|
||||
const full_url = `${g_sd_url}/controlnet/detect`
|
||||
|
||||
const response_data = await api.requestPost(full_url, payload)
|
||||
|
||||
// update the mask preview with the new detectMap
|
||||
if (response_data['images'].length === 0) {
|
||||
app.showAlert(response_data['info'])
|
||||
}
|
||||
return response_data['images'][0]
|
||||
} catch (e) {
|
||||
console.warn('requestControlNetDetectMap(): ', _module, e)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async previewAnnotator() {
|
||||
const index = this.props.index
|
||||
try {
|
||||
const storeData = this.props.appState.controlNetUnitData[index];
|
||||
|
||||
const controlnet_init_image = storeData.input_image
|
||||
|
||||
const _module = storeData.module || 'none';
|
||||
const processor_res = storeData.processor_res
|
||||
const threshold_a = storeData.threshold_a
|
||||
const threshold_b = storeData.threshold_b
|
||||
|
||||
if (!controlnet_init_image) {
|
||||
const error = 'ControlNet initial image is empty'
|
||||
app.showAlert(error)
|
||||
throw error
|
||||
}
|
||||
if (!_module || _module === 'none') {
|
||||
const error = 'select a valid controlnet module (preprocessor)'
|
||||
app.showAlert(error)
|
||||
throw error
|
||||
}
|
||||
|
||||
const detect_map = await this.requestControlNetDetectMap(
|
||||
controlnet_init_image,
|
||||
_module,
|
||||
processor_res,
|
||||
threshold_a,
|
||||
threshold_b
|
||||
)
|
||||
|
||||
const rgb_detect_map_url =
|
||||
await io.convertBlackAndWhiteImageToRGBChannels3(detect_map)
|
||||
const rgb_detect_map = general.base64UrlToBase64(rgb_detect_map_url)
|
||||
g_generation_session.controlNetMask[index] = rgb_detect_map
|
||||
|
||||
storeData.mask = rgb_detect_map
|
||||
|
||||
} catch (e) {
|
||||
console.warn('PreviewAnnotator click(): index: ', index, e)
|
||||
}
|
||||
}
|
||||
async toCanvas() {
|
||||
if (
|
||||
g_generation_session.control_net_preview_selection_info &&
|
||||
g_generation_session.controlNetMask[this.props.index]
|
||||
) {
|
||||
const selection_info =
|
||||
g_generation_session.control_net_preview_selection_info
|
||||
const layer = await io.IO.base64ToLayer(
|
||||
g_generation_session.controlNetMask[this.props.index],
|
||||
'ControlNet Mask.png',
|
||||
selection_info.left,
|
||||
selection_info.top,
|
||||
selection_info.width,
|
||||
selection_info.height
|
||||
)
|
||||
} else {
|
||||
// await note.Notification.inactiveSelectionArea()
|
||||
app.showAlert('Mask Image is not available')
|
||||
}
|
||||
}
|
||||
async toControlNetInitImage() {
|
||||
const preview_result_base64 = g_generation_session.controlNetMask[this.props.index]
|
||||
g_generation_session.controlNetImage[this.props.index] = preview_result_base64
|
||||
g_generation_session.control_net_selection_info =
|
||||
g_generation_session.control_net_preview_selection_info
|
||||
|
||||
const rgb_detect_map_url =
|
||||
await io.convertBlackAndWhiteImageToRGBChannels3(
|
||||
preview_result_base64
|
||||
)
|
||||
|
||||
// g_generation_session.controlNetMask[index] = rgb_detect_map
|
||||
|
||||
// html_manip.setControlImageSrc(rgb_detect_map_url, this.props.index)
|
||||
const storeData = this.props.appState.controlNetUnitData[this.props.index];
|
||||
|
||||
storeData.input_image = storeData.mask
|
||||
}
|
||||
async previewAnnotatorFromCanvas() {
|
||||
try {
|
||||
const storeData = this.props.appState.controlNetUnitData[this.props.index];
|
||||
const _module = storeData.module || 'none';
|
||||
|
||||
const width = html_manip.getWidth()
|
||||
const height = html_manip.getHeight()
|
||||
const selectionInfo = await psapi.getSelectionInfoExe()
|
||||
g_generation_session.control_net_preview_selection_info = selectionInfo
|
||||
const base64 = await io.IO.getSelectionFromCanvasAsBase64Interface_New(
|
||||
width,
|
||||
height,
|
||||
selectionInfo,
|
||||
true
|
||||
)
|
||||
|
||||
if (!_module || _module === 'none') {
|
||||
const error = 'select a valid controlnet module (preprocessor)'
|
||||
app.showAlert(error)
|
||||
throw error
|
||||
}
|
||||
|
||||
const processor_res = storeData.processor_res
|
||||
const threshold_a = storeData.threshold_a
|
||||
const threshold_b = storeData.threshold_b
|
||||
|
||||
const detect_map = await this.requestControlNetDetectMap(
|
||||
base64,
|
||||
_module,
|
||||
processor_res,
|
||||
threshold_a,
|
||||
threshold_b
|
||||
)
|
||||
|
||||
const rgb_detect_map_url =
|
||||
await io.convertBlackAndWhiteImageToRGBChannels3(detect_map)
|
||||
g_generation_session.controlNetMask[this.props.index] = detect_map
|
||||
|
||||
storeData.mask = general.base64UrlToBase64(rgb_detect_map_url)
|
||||
} catch (e) {
|
||||
console.warn('PreviewAnnotator click(): index: ', this.props.index, e)
|
||||
}
|
||||
}
|
||||
render() {
|
||||
const storeData = this.props.appState.controlNetUnitData[this.props.index];
|
||||
const pd = this.props.appState.preprocessorDetail[storeData.module] || {};
|
||||
|
|
@ -158,19 +313,26 @@ export default class ControlNetUnit extends React.Component<{ index: number, app
|
|||
className="imgContainer controlNetImaageContainer"
|
||||
>
|
||||
<div>
|
||||
<img
|
||||
<Thumbnail>
|
||||
<img
|
||||
id={`control_net_mask_${this.props.index}`}
|
||||
className="column-item-image"
|
||||
src={storeData.mask ? 'data:image/png;base64,' + storeData.mask : "https://source.unsplash.com/random"}
|
||||
width="300px"
|
||||
height="100px"
|
||||
/>
|
||||
/>
|
||||
<ActionButtonSVG onClick={this.toControlNetInitImage.bind(this)} ><PenSvg/></ActionButtonSVG>
|
||||
<ActionButtonSVG onClick={this.toCanvas.bind(this)} ><MoveToCanvasSvg/></ActionButtonSVG>
|
||||
<ActionButtonSVG onClick={this.previewAnnotatorFromCanvas.bind(this)} ><PreviewSvg/></ActionButtonSVG>
|
||||
</Thumbnail>
|
||||
|
||||
</div>
|
||||
<div className="imgButton btnClass">
|
||||
<button
|
||||
className="column-item button-style btnSquare"
|
||||
id={`bControlMask_${this.props.index}`}
|
||||
onClick={this.onMaskButtonClick.bind(this)}
|
||||
onClick={this.previewAnnotator.bind(this)}
|
||||
|
||||
title="Preview Annotator"
|
||||
>
|
||||
Preview Annotator
|
||||
|
|
|
|||
|
|
@ -1,7 +1,16 @@
|
|||
import React, { ReactEventHandler, useState } from 'react'
|
||||
import React, { CSSProperties, ReactEventHandler, useState } from 'react'
|
||||
// import ReactDOM from 'react-dom'
|
||||
import ReactDOM from 'react-dom/client'
|
||||
// import { versions } from 'uxp'
|
||||
|
||||
|
||||
|
||||
export { ReactComponent as MoveToCanvasSvg } from '../../icon/move_to_canvas.svg';
|
||||
export { ReactComponent as PenSvg } from '../../icon/pen.svg';
|
||||
export { ReactComponent as PreviewSvg } from '../../icon/preview.svg';
|
||||
|
||||
|
||||
|
||||
declare global {
|
||||
namespace JSX {
|
||||
interface IntrinsicElements {
|
||||
|
|
@ -16,6 +25,7 @@ declare global {
|
|||
'sp-divider': any
|
||||
'sp-detail': any
|
||||
'sp-textarea': any
|
||||
'sp-action-button': any
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -174,7 +184,7 @@ export class SpMenu extends React.Component<{
|
|||
id?: string
|
||||
|
||||
title?: string
|
||||
style?: string
|
||||
style?: CSSProperties
|
||||
items?: string[]
|
||||
disabled?: boolean[]
|
||||
label_item?: string
|
||||
|
|
@ -212,11 +222,11 @@ export class SpMenu extends React.Component<{
|
|||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<div style={this.props.style}>
|
||||
<sp-picker
|
||||
title={this.props.title}
|
||||
size="m"
|
||||
style={{ width: '199px', marginRight: '5px' }}
|
||||
// style={{ width: '199px', marginRight: '5px' }}
|
||||
>
|
||||
<sp-menu id={this.props.id} slot="options">
|
||||
{this.props.label_item && (
|
||||
|
|
@ -314,6 +324,12 @@ export class SpPicker extends PhotoshopElem {
|
|||
return <sp-picker ref={(elem: Element) => this.elem = elem} {...attr}></sp-picker>
|
||||
}
|
||||
}
|
||||
export class SpMenuComponent extends PhotoshopElem {
|
||||
render() {
|
||||
const [attr] = this.splitProps(this.props)
|
||||
return <sp-menu ref={(elem: Element) => this.elem = elem} {...attr}></sp-menu>
|
||||
}
|
||||
}
|
||||
export class SpMenuItem extends PhotoshopElem {
|
||||
render() {
|
||||
const [attr] = this.splitProps(this.props)
|
||||
|
|
@ -357,3 +373,29 @@ export class SpDivider extends PhotoshopElem {
|
|||
return <sp-divider ref={(elem: Element) => this.elem = elem} {...attr}></sp-divider>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class Thumbnail extends React.Component<{children:React.ReactNode}> {
|
||||
|
||||
render() {
|
||||
return <div className='viewer-image-container'>
|
||||
|
||||
{this.props.children}
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
export class ActionButtonSVG extends PhotoshopElem {
|
||||
render() {
|
||||
const [attr] = this.splitProps(this.props)
|
||||
|
||||
return <sp-action-button style={{padding: 0, maxWidth: "32px",maxHeight: "32px" /* display: none; */}} class="thumbnail-image-button" ref={(elem: Element) => this.elem = elem} {...attr}>
|
||||
|
||||
<div slot="icon" style={{fill: 'currentColor'}}>
|
||||
{this.props.children}
|
||||
</div>
|
||||
</sp-action-button>}}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue