chore: image edit invert painting area
This commit is contained in:
@@ -50,6 +50,10 @@
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.m-0 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.m-r-10 {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,19 @@
|
||||
border-radius: var(--border-radius-base);
|
||||
overflow: hidden;
|
||||
|
||||
.label {
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
left: 4px;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
border-radius: 12px;
|
||||
padding: 0 8px;
|
||||
background-color: var(--ant-geekblue-1);
|
||||
z-index: 10;
|
||||
transform: scale(0.9);
|
||||
}
|
||||
|
||||
.progress-wrapper {
|
||||
position: absolute;
|
||||
bottom: 20px;
|
||||
|
||||
@@ -14,6 +14,7 @@ interface SingleImageProps {
|
||||
maxHeight?: number;
|
||||
maxWidth?: number;
|
||||
dataUrl: string;
|
||||
label?: React.ReactNode;
|
||||
uid: number;
|
||||
preview?: boolean;
|
||||
autoSize?: boolean;
|
||||
@@ -42,6 +43,7 @@ const SingleImage: React.FC<SingleImageProps> = (props) => {
|
||||
maxHeight,
|
||||
maxWidth,
|
||||
dataUrl = '',
|
||||
label,
|
||||
style,
|
||||
autoBgColor,
|
||||
preview = true,
|
||||
@@ -119,6 +121,7 @@ const SingleImage: React.FC<SingleImageProps> = (props) => {
|
||||
ref={imgWrapper}
|
||||
>
|
||||
<>
|
||||
{label && <div className="label">{label}</div>}
|
||||
{loading ? (
|
||||
<span
|
||||
className="progress-wrap"
|
||||
|
||||
@@ -10,7 +10,13 @@ import { useIntl } from '@umijs/max';
|
||||
import { Button, Checkbox, Slider, Tooltip } from 'antd';
|
||||
import dayjs from 'dayjs';
|
||||
import _ from 'lodash';
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import React, {
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState
|
||||
} from 'react';
|
||||
import IconFont from '../icon-font';
|
||||
import './index.less';
|
||||
|
||||
@@ -38,7 +44,7 @@ const COLOR = 'rgba(0, 0, 255, 0.3)';
|
||||
|
||||
const CanvasImageEditor: React.FC<CanvasImageEditorProps> = ({
|
||||
imageSrc,
|
||||
disabled,
|
||||
disabled: isDisabled,
|
||||
imageStatus,
|
||||
clearUploadMask,
|
||||
onSave,
|
||||
@@ -68,8 +74,13 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = ({
|
||||
const preImguid = useRef<string | number>('');
|
||||
const [activeScale, setActiveScale] = useState<number>(1);
|
||||
const negativeMaskRef = useRef<boolean>(false);
|
||||
const [invertMask, setInvertMask] = useState<boolean>(false);
|
||||
const mouseDownState = useRef<boolean>(false);
|
||||
|
||||
const disabled = useMemo(() => {
|
||||
return isDisabled || invertMask;
|
||||
}, [isDisabled, invertMask]);
|
||||
|
||||
const getTransformedPoint = useCallback(
|
||||
(offsetX: number, offsetY: number) => {
|
||||
const { current: scale } = autoScale;
|
||||
@@ -225,11 +236,7 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = ({
|
||||
);
|
||||
const data = imageData.data;
|
||||
|
||||
if (negativeMaskRef.current) {
|
||||
inpaintBackground(data);
|
||||
} else {
|
||||
inpaintArea(data);
|
||||
}
|
||||
inpaintArea(data);
|
||||
|
||||
maskCtx.putImageData(imageData, 0, 0);
|
||||
|
||||
@@ -605,6 +612,39 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = ({
|
||||
overlayCtx!.resetTransform();
|
||||
}, []);
|
||||
|
||||
const invertPainting = (isChecked: boolean) => {
|
||||
const ctx = overlayCanvasRef.current!.getContext('2d');
|
||||
|
||||
if (!ctx) return;
|
||||
|
||||
if (isChecked) {
|
||||
const canvasWidth = overlayCanvasRef.current!.width;
|
||||
const canvasHeight = overlayCanvasRef.current!.height;
|
||||
|
||||
clearOverlayCanvas();
|
||||
|
||||
ctx.fillStyle = COLOR;
|
||||
ctx.fillRect(0, 0, canvasWidth, canvasHeight);
|
||||
|
||||
setTransform();
|
||||
ctx.globalCompositeOperation = 'destination-out';
|
||||
|
||||
strokesRef.current.forEach((stroke) => {
|
||||
stroke.forEach((point: Point) => {
|
||||
const { x, y } = getTransformedPoint(point.x, point.y);
|
||||
const lineWidth = getTransformLineWidth(point.lineWidth);
|
||||
ctx.fillStyle = 'rgba(0,0,0,1)';
|
||||
ctx.beginPath();
|
||||
ctx.arc(x, y, lineWidth / 2, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
});
|
||||
});
|
||||
ctx.globalCompositeOperation = 'source-out';
|
||||
} else {
|
||||
redrawStrokes(strokesRef.current);
|
||||
}
|
||||
};
|
||||
|
||||
const updateCursorSize = () => {
|
||||
cursorRef.current!.style.width = `${lineWidth * autoScale.current}px`;
|
||||
cursorRef.current!.style.height = `${lineWidth * autoScale.current}px`;
|
||||
@@ -630,11 +670,7 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = ({
|
||||
resetCanvas();
|
||||
}
|
||||
preImguid.current = imguid;
|
||||
console.log(
|
||||
'Image initialized:',
|
||||
strokesRef.current.length,
|
||||
imageStatus.isOriginal
|
||||
);
|
||||
|
||||
if (strokesRef.current.length && imageStatus.isOriginal) {
|
||||
redrawStrokes(strokesRef.current);
|
||||
saveImage();
|
||||
@@ -710,6 +746,8 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = ({
|
||||
|
||||
const handleOnChangeMask = (e: any) => {
|
||||
negativeMaskRef.current = e.target.checked;
|
||||
invertPainting(e.target.checked);
|
||||
setInvertMask(e.target.checked);
|
||||
saveImage();
|
||||
};
|
||||
|
||||
@@ -746,14 +784,6 @@ const CanvasImageEditor: React.FC<CanvasImageEditorProps> = ({
|
||||
};
|
||||
}, []);
|
||||
|
||||
// useEffect(() => {
|
||||
// if (disabled) {
|
||||
// overlayCanvasRef.current!.style.pointerEvents = 'none';
|
||||
// } else {
|
||||
// overlayCanvasRef.current!.style.pointerEvents = 'auto';
|
||||
// }
|
||||
// }, [disabled]);
|
||||
|
||||
return (
|
||||
<div className="editor-wrapper">
|
||||
<div className="flex-between">
|
||||
|
||||
@@ -29,7 +29,3 @@ To add a new language configuration, follow these steps:
|
||||
|
||||
- Review and ensure all translations are complete.
|
||||
- Your new language configuration is now ready for use!
|
||||
|
||||
5. **Check the Dir and File**
|
||||
|
||||
- `npm run check:locales`
|
||||
|
||||
@@ -141,5 +141,7 @@ export default {
|
||||
'playground.image.fitview': 'Fit View',
|
||||
'playground.chat.aithought': 'CoT',
|
||||
'playground.image.mask.uploaded': 'Mask Uploaded',
|
||||
'playground.image.mask.upload': 'Upload Mask'
|
||||
'playground.image.mask.upload': 'Upload Mask',
|
||||
'playground.params.frequency_penalty.tips': `Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.`,
|
||||
'playground.params.presence_penalty.tips': `Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics.`
|
||||
};
|
||||
|
||||
@@ -136,5 +136,7 @@ export default {
|
||||
'playground.image.fitview': '适应视图',
|
||||
'playground.chat.aithought': '思考过程',
|
||||
'playground.image.mask.uploaded': '遮罩已上传',
|
||||
'playground.image.mask.upload': '上传遮罩'
|
||||
'playground.image.mask.upload': '上传遮罩',
|
||||
'playground.params.frequency_penalty.tips': `数值介于 -2.0 和 2.0 之间。正值会根据新词在文本中已出现的频率对其进行惩罚,从而降低模型逐字重复相同内容的可能性。`,
|
||||
'playground.params.presence_penalty.tips': `数值介于 -2.0 和 2.0 之间。正值会根据新词是否已在文本中出现过对其进行惩罚,从而增加模型谈论新话题的可能性。`
|
||||
};
|
||||
|
||||
@@ -3,6 +3,8 @@ import { initialPasswordAtom, userAtom } from '@/atoms/user';
|
||||
import LangSelect from '@/components/lang-select';
|
||||
import SealInput from '@/components/seal-form/seal-input';
|
||||
import {
|
||||
CRYPT_TEXT,
|
||||
REMEMBER_ME_KEY,
|
||||
getRememberMe,
|
||||
rememberMe,
|
||||
removeRememberMe
|
||||
@@ -12,14 +14,11 @@ import { useIntl, useModel } from '@umijs/max';
|
||||
import { Button, Checkbox, Form } from 'antd';
|
||||
import CryptoJS from 'crypto-js';
|
||||
import { useAtom } from 'jotai';
|
||||
import { memo, useEffect, useMemo } from 'react';
|
||||
import { useEffect, useMemo } from 'react';
|
||||
import { flushSync } from 'react-dom';
|
||||
import { login } from '../apis';
|
||||
import { checkDefaultPage } from '../utils';
|
||||
|
||||
const REMEMBER_ME_KEY = 'r_m';
|
||||
const CRYPT_TEXT = 'seal';
|
||||
|
||||
const LoginForm = () => {
|
||||
const [userInfo, setUserInfo] = useAtom(userAtom);
|
||||
const [initialPassword, setInitialPassword] = useAtom(initialPasswordAtom);
|
||||
@@ -27,7 +26,6 @@ const LoginForm = () => {
|
||||
const intl = useIntl();
|
||||
const [form] = Form.useForm();
|
||||
|
||||
console.log('initialState+++++++=login', userInfo, initialState);
|
||||
const renderWelCome = useMemo(() => {
|
||||
return (
|
||||
<div
|
||||
@@ -206,4 +204,4 @@ const LoginForm = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(LoginForm);
|
||||
export default LoginForm;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { initialPasswordAtom, userAtom } from '@/atoms/user';
|
||||
import SealInput from '@/components/seal-form/seal-input';
|
||||
import { PasswordReg } from '@/config';
|
||||
import { CRYPT_TEXT } from '@/utils/localstore/index';
|
||||
import { GlobalOutlined, LockOutlined } from '@ant-design/icons';
|
||||
import { SelectLang, useIntl } from '@umijs/max';
|
||||
import { Button, Form, message } from 'antd';
|
||||
@@ -9,8 +10,6 @@ import { useAtom } from 'jotai';
|
||||
import { updatePassword } from '../apis';
|
||||
import { checkDefaultPage } from '../utils';
|
||||
|
||||
const CRYPT_TEXT = 'seal';
|
||||
|
||||
const PasswordForm: React.FC = () => {
|
||||
const intl = useIntl();
|
||||
const [form] = Form.useForm();
|
||||
@@ -28,7 +27,6 @@ const PasswordForm: React.FC = () => {
|
||||
};
|
||||
|
||||
const handleSubmit = async (values: any) => {
|
||||
console.log('values', values, form);
|
||||
try {
|
||||
await updatePassword({
|
||||
new_password: values.new_password,
|
||||
|
||||
@@ -132,6 +132,7 @@ const ParamsSettings: React.FC<ParamsSettingsProps> = forwardRef(
|
||||
onValuesChange={handleValuesChange}
|
||||
onFinish={handleOnFinish}
|
||||
onFinishFailed={handleOnFinishFailed}
|
||||
initialValues={initialValues}
|
||||
>
|
||||
<div>
|
||||
{
|
||||
|
||||
@@ -157,11 +157,6 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
|
||||
}, [finalParameters, currentPrompt, parameters.size]);
|
||||
|
||||
const handleClear = () => {
|
||||
// setImageList([]);
|
||||
// setTokenResult(null);
|
||||
// setMask('');
|
||||
// setImage('');
|
||||
// setUploadList([]);
|
||||
setCurrentPrompt('');
|
||||
};
|
||||
|
||||
@@ -393,11 +388,33 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
|
||||
editable={false}
|
||||
autoBgColor={false}
|
||||
onClick={() => handleOnImgClick(uploadList[0], true)}
|
||||
label={<span>Origin</span>}
|
||||
></SingleImage>
|
||||
</>
|
||||
);
|
||||
}, [uploadList, handleOnImgClick]);
|
||||
|
||||
const renderMaskImage = useMemo(() => {
|
||||
if (!maskUpload.length) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<SingleImage
|
||||
{...maskUpload[0]}
|
||||
height={125}
|
||||
maxHeight={125}
|
||||
preview={false}
|
||||
loading={false}
|
||||
autoSize={false}
|
||||
editable={false}
|
||||
autoBgColor={false}
|
||||
label={<span>Mask</span>}
|
||||
></SingleImage>
|
||||
</>
|
||||
);
|
||||
}, [maskUpload]);
|
||||
|
||||
return (
|
||||
<div className="ground-left-wrapper">
|
||||
<div className="ground-left">
|
||||
@@ -428,6 +445,7 @@ const GroundImages: React.FC<MessageProps> = forwardRef((props, ref) => {
|
||||
alignItems: 'center'
|
||||
}}
|
||||
>
|
||||
<div className="m-r-10">{renderMaskImage}</div>
|
||||
{renderOriginImage}
|
||||
{imageList.length > 0 && (
|
||||
<>
|
||||
|
||||
@@ -553,7 +553,7 @@ export const ChatParamsConfig: ParamsSchema[] = [
|
||||
},
|
||||
attrs: {
|
||||
max: 2,
|
||||
step: 0.1,
|
||||
step: 0.01,
|
||||
inputnumber: true
|
||||
},
|
||||
rules: [
|
||||
@@ -599,7 +599,55 @@ export const ChatParamsConfig: ParamsSchema[] = [
|
||||
},
|
||||
attrs: {
|
||||
max: 1,
|
||||
step: 0.1,
|
||||
step: 0.01,
|
||||
inputnumber: true
|
||||
},
|
||||
rules: [
|
||||
{
|
||||
required: false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
type: 'Slider',
|
||||
name: 'frequency_penalty',
|
||||
label: {
|
||||
text: 'Frequency Penalty',
|
||||
isLocalized: false
|
||||
},
|
||||
description: {
|
||||
text: 'playground.params.frequency_penalty.tips',
|
||||
html: false,
|
||||
isLocalized: true
|
||||
},
|
||||
attrs: {
|
||||
max: 2,
|
||||
min: -2,
|
||||
step: 0.01,
|
||||
inputnumber: true
|
||||
},
|
||||
rules: [
|
||||
{
|
||||
required: false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
type: 'Slider',
|
||||
name: 'presence_penalty',
|
||||
label: {
|
||||
text: 'Presence Penalty',
|
||||
isLocalized: false
|
||||
},
|
||||
description: {
|
||||
text: 'playground.params.presence_penalty.tips',
|
||||
html: false,
|
||||
isLocalized: true
|
||||
},
|
||||
attrs: {
|
||||
max: 2,
|
||||
min: -2,
|
||||
step: 0.01,
|
||||
inputnumber: true
|
||||
},
|
||||
rules: [
|
||||
|
||||
@@ -5,7 +5,9 @@ export const LLM_METAKEYS: Record<string, any> = {
|
||||
top_p: 'top_p',
|
||||
n_ctx: 'n_ctx',
|
||||
n_slot: 'n_slot',
|
||||
max_model_len: 'max_model_len'
|
||||
max_model_len: 'max_model_len',
|
||||
frequency_penalty: 'frequency_penalty',
|
||||
presence_penalty: 'presence_penalty'
|
||||
};
|
||||
|
||||
export const IMG_METAKEYS = [
|
||||
@@ -23,7 +25,9 @@ export const llmInitialValues = {
|
||||
stop: null,
|
||||
temperature: 1,
|
||||
top_p: 1,
|
||||
max_tokens: null
|
||||
max_tokens: null,
|
||||
frequency_penalty: null,
|
||||
presence_penalty: null
|
||||
};
|
||||
|
||||
export const advancedFieldsDefaultValus = {
|
||||
|
||||
@@ -433,7 +433,11 @@ const Workers: React.FC = () => {
|
||||
</span>
|
||||
<span>
|
||||
{intl.formatMessage({ id: 'resources.table.used' })}:{' '}
|
||||
{convertFileSize(record?.status?.memory?.used, 0)}
|
||||
{convertFileSize(
|
||||
record?.status?.memory?.used ||
|
||||
record?.status.memory?.allocated,
|
||||
0
|
||||
)}
|
||||
</span>
|
||||
</span>
|
||||
}
|
||||
|
||||
@@ -2,6 +2,9 @@ import localStore from './store';
|
||||
|
||||
const IS_FIRST_LOGIN = 'is_first_login';
|
||||
|
||||
const REMEMBER_ME_KEY = 'r_m';
|
||||
const CRYPT_TEXT = 'seal';
|
||||
|
||||
const store = localStore.createInstance({ name: '_xWXJKJ_S1Sna_' });
|
||||
|
||||
const rememberMe = (key: string, data: any) => {
|
||||
@@ -35,7 +38,9 @@ const writeState = (key: string, data: any) => {
|
||||
};
|
||||
|
||||
export {
|
||||
CRYPT_TEXT,
|
||||
IS_FIRST_LOGIN,
|
||||
REMEMBER_ME_KEY,
|
||||
getRememberMe,
|
||||
readState,
|
||||
rememberMe,
|
||||
|
||||
Reference in New Issue
Block a user