生成 mask

图片加载

/**
 * 加载图片
 */
export const imageLoad = (url: string): Promise<HTMLImageElement> => {
    return new Promise((resolve, reject) => {
        const img = new Image();
        img.onload = (): void => {
            resolve(img);
        };
        img.onerror = (err): void => {
            reject(err);
        };
        img.src = url;
    });
};

/**
 * 图片url转成base64格式
 */
export const convertImageToBase64 = (imgUrl: string, background?: string): Promise<string> => {
    const proxyURL = getProxyImageURL(imgUrl);
    return new Promise<string>((resolve, reject) => {
        const image = new Image();
        image.crossOrigin = 'anonymous';
        image.src = proxyURL;
        image.onload = (): void => {
            const canvas = document.createElement('canvas');
            const ctx = canvas.getContext('2d');
            if (!ctx) return;
            canvas.height = image.naturalHeight;
            canvas.width = image.naturalWidth;
            if (!isEmpty(background)) {
                ctx.fillStyle = background;
                ctx.fillRect(0, 0, canvas.width, canvas.height);
            }
            ctx?.drawImage(image, 0, 0);
            const base64data = canvas.toDataURL('image/png');
            resolve(base64data);
        };
        image.onerror = (error): void => {
            reject(`图片转base64失败${JSON.stringify(error)}`);
        };
    });
};

/**
 * file转换为base64
 * @param {*} data
 * @param {*} filename
 * @returns
 */
export const fileToBase64 = (file) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    return new Promise((resolve) => {
        reader.addEventListener('load', (e) => {
            const base64 = e.target.result;
            resolve(base64);
        });
    });
};

/**
 * 图片调整大小
 * @param image
 * @param width
 * @param height
 */
export function imageResize (image: File, width: number, height: number) {
    return new Promise((resolve) => {
        const reader = new FileReader();
        reader.onload = (e) => {
            const img = new Image();
            img.src = e.target?.result as string;
            img.onload = () => {
                const canvas = document.createElement('canvas');
                const ctx = canvas.getContext('2d');
                canvas.width = width;
                canvas.height = height;
                ctx?.drawImage(img, 0, 0, width, height);
                // base64
                const base64 = canvas.toDataURL('image/png');
                resolve(base64);
            };
        };
        reader.readAsDataURL(image);
    });
}

1:1图片转 3:4


/**
 * 1:1 图片转换 3:4
 */
export const imageToThreeFour = (imageStr: string): Promise<string> => {
    return new Promise((resolve) => {
        const image = new Image();
        image.onload = () => {
            const canvas = document.createElement('canvas');
            const ctx = canvas.getContext('2d');
            if (!ctx) return;
            const width = image.width;
            const height = image.height;
            console.log('change 11 34',width,height)

            if(width != height) {
                resolve(imageStr);
                return;
            }
            const newWidth = width / 4 * 3;
            const newHeight = height;
            canvas.width = newWidth;
            canvas.height = newHeight;
            // 缩小的宽度去掉两边
            const x = (width - newWidth) / 2;
            // 裁剪
            ctx.drawImage(image, x, 0, newWidth, height, 0, 0, newWidth, newHeight);
            const base64 = canvas.toDataURL('image/png');
            console.log('change 11 34',base64);
            resolve(base64);
        };

        image.crossOrigin = 'Anonymous';
        image.src = imageStr;
    });
}

寻找最小图片边缘

// 裁剪图片至其最小尺寸的函数
export const cropImageToMinSize = (imageUrl: string): Promise<string> => {
    return new Promise((resolve) => {
        // 创建一个Image对象用于加载图片
        const img = new Image();

        // 设置图片加载完成后的回调函数
        img.onload = function () {
            // 创建一个Canvas元素
            const canvas = document.createElement('canvas');
            const ctx = canvas.getContext('2d');

            if (!ctx) {
                // 如果无法获取绘图上下文,则返回
                return;
            }

            // 设置Canvas尺寸与图片尺寸相同
            canvas.width = img.width;
            canvas.height = img.height;

            // 在Canvas上绘制图片
            ctx.drawImage(img, 0, 0);

            // 获取图片像素数据
            const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
            const data = imageData.data;

            // 寻找图片内容的上下左右边界
            let top = findEdge(data, canvas.width, canvas.height, true);
            let bottom = findEdge(data, canvas.width, canvas.height, false);
            let left = findEdge(data, canvas.height, img.width, true);
            let right = findEdge(data, canvas.height, img.width, false);

            // 定义寻找边缘的函数
            function findEdge(data, length, width, isVertical) {
                let edge;
                for (edge = 0; edge < length; edge++) {
                    for (let i = 0; i < width; i++) {
                        const alpha = data[(isVertical ? edge : i) * width + (isVertical ? i : edge)] * 4 + 3;
                        if (alpha > 0) break;
                    }
                    if (i < width) break;
                }
                return edge;
            }

            // 计算裁剪后的图片尺寸
            const croppedWidth = right - left + 1;
            const croppedHeight = bottom - top + 1;

            // 创建新的Canvas用于裁剪
            const croppedCanvas = document.createElement('canvas');
            const croppedCtx = croppedCanvas.getContext('2d');

            // 设置新Canvas的尺寸与裁剪后的图片尺寸相同
            croppedCanvas.width = croppedWidth;
            croppedCanvas.height = croppedHeight;

            // 在新Canvas上绘制裁剪后的图片
            croppedCtx.drawImage(
                img,
                left,
                top,
                croppedWidth,
                croppedHeight,
                0,
                0,
                croppedWidth,
                croppedHeight
            );

            // 将裁剪后的图片转换为base64格式
            const croppedBase64 = croppedCanvas.toDataURL();

            // 执行回调函数,返回结果
            resolve(croppedBase64);
        };

        // 设置图片的跨域属性
        img.crossOrigin = 'Anonymous';

        // 加载图片
        img.src = imageUrl;
    });
};

自定义上传样式


    /**
     * 上传图片 点击
     */
    const uploadImagesClick = (): void => {
        const uploadCustomImage = document.getElementById('uploadCustomImage');
        uploadCustomImage.click();
    };

    const prepareUploadFile: React.ChangeEventHandler<HTMLInputElement> = async (event) => {
        const inputElement = event.target as HTMLInputElement;
        // 获取单个文件
        const file = inputElement.files?.[0];
        if (isEmpty(file)) return;
        // 仅支持 1 比 1 图片,不满足条件提示返回 获取图片宽高
        const img = await imageLoad(await fileToBase64(file));
        if (img.width !== img.height) {
            message.error('图片宽高比例不符合要求,请重新选择');
            return;
        }
        // TODO 调整图片大小为 1024 * 1024
        customScenceImageBase64Ref.current = file;
        setInpaintVisible(true);
    };
    
    
     <div className="item-option-wrap" onClick={uploadImagesClick}>
                                                <input className="upload-input" type="file" id="uploadCustomImage" style={{ display: 'none' }}
                                                    accept=".png, .jpg, .jpeg" onChange={prepareUploadFile}/>
                                                <PlusOutlined/>
                                                <span className="local-upload-text">上传图片</span>
                                            </div>

isEmpty

export const isEmpty = (key: any): boolean => {
    if (key === undefined || key === '' || key === null) {
        return true;
    }
    if (typeof (key) === 'string') {
        key = key.replace(trimReg, '');
        if (key == '' || key == null || key == 'null' || key == undefined || key == 'undefined') {
            return true;
        }
        return false;
    } else if (typeof (key) === 'undefined') {
        return true;
    } else if (typeof (key) === 'object') {
        for (const i in key) {
            return false;
        }
        return true;
    } else if (typeof (key) === 'boolean') {
        return false;
    } else if (typeof (key) === 'number') {
        return isNaN(key);
    }
};
/**
 * 不等于空
 * @param key
 */
export const isNotEmpty = (key: any): boolean => {
    return !isEmpty(key);
};

getAnyImage

export const getImageBodyAny = async (anyObj: any) => {
    try {
        if (isEmpty(anyObj)) {
            return null;
        }
        // 如果是import('@fastify/multipart').MultipartFile  直接返回
        if (anyObj[0]?.data) {
            return anyObj[0].data;
        }
        if (typeof anyObj === 'string') {
            // 判断是否为网络 url
            if (anyObj.startsWith('http://') || anyObj.startsWith('https://')) {
                const response: any = await got(anyObj, { responseType: 'buffer' });
                return response.body;
            } else if (checkStrIsBase64(anyObj)) {
                // 将拿到的img由base64转换为byte[]
                return base64ToFileObject(anyObj, 'test.jpg').buffer;
            }
            // 转buffer
            return Buffer.from(anyObj);
        } else if (anyObj instanceof Buffer) {
            return anyObj;
        }
        return anyObj;
    } catch (err) {
        return null;
    }
};

uploadOss


    async uploadFile (fileDirType, buffer, fileNameSuffix) {
        const { userId } = this.baseService.getUserInfo() || {};
        const params = {
            file: buffer,
            uploadDir: generateOssFilePath(fileDirType, fileNameSuffix, userId),

        };
        // 上传文件到oss
        const res = await this.ossService.uploadFile(params);
        if (res.res.status !== 200) {
            this.logger.error(`【volcengine_tss】上传文件到oss失败:${JSON.stringify(res)}`);
            throw new CustomException({
                code: 500,
                message: `【volcengine_tss】上传文件到oss失败:${JSON.stringify(res)}`,
            });
        }
        return res.url;
    }

    async formatImageAsURL (imageData: any, fileDirType:keyof typeof OssFileDir, fileNameSuffix: string): Promise<string> {
        const buffer = await getImageBodyAny(imageData);
        // 上传oss
        return this.uploadFile(fileDirType, buffer, fileNameSuffix);
    }