função de corte de projeto java
O projeto precisa de uma função de upload de assinaturas de texto e remoção da imagem de fundo. Quando ouvi esse requisito pela primeira vez, fiquei de queixo caído. Nunca pensei que essa função pudesse ser realizada em java. Mas já que o cliente precisa, vamos fazer.
Após a realização desta função, também fortaleci minha ideia. Não importa o quão estranha seja a demanda, primeiro devo encontrar uma maneira. Não recuse de forma decisiva. Acredite, pode haver algo que não possa ser resolvido pelo nº Java天下第一
. 1 no mundo? (Na verdade, eu já estou python
ansioso para aprender em meu coração, hehe~~~)
1. Renderização
Após algumas pesquisas e modificações, fiz o seguinte efeito com meus amigos front-end. (O todo é igual ao PS e imediatamente parece mais alto)
A função é relativamente simples, faça upload de imagens para o back-end e o back-end retorna o caminho da imagem recortada.
A imagem original é a seguinte:
Depois de carregar esta imagem, primeiro quadro selecione o intervalo e gire a direção. Observe que a seleção do quadro e gire a imagem são operações de front-end, e essas operações de front-end têm métodos, conforme mostrado no figura abaixo: Após a configuração,
clique 抠图
para ver o efeito da imagem abaixo, ela ficou transparente. Nesta etapa, o recorte chama a interface de recorte fornecida por java.
2. Interface de botão
A seguir está a interface de recorte de imagem. Nesta interface, o front-end transmite a imagem cortada para o back-end. Nesta interface, o back-end passará a imagem passada pelo front-end para o método. Neste método, o PictureUtils.transApla(restore,169)
recorte será executado. E salve-o novamente. Depois de salvar, retorne o caminho da imagem processada para o front-end, e o front-end pode exibi-lo diretamente. As etapas detalhadas são as seguintes:
- O front-end carrega as imagens para o painel. Neste momento, a interface do back-end não é chamada, sendo carregada apenas pelo front-end.
- Como o tamanho e a direção das imagens enviadas pelos usuários não são fixos, algumas funções de rotação e corte também devem ser consideradas. Portanto, também adicionamos essas funções comuns aqui e, após a rotação e o corte, o intervalo foi determinado. Observe que tudo isso é feito pelo próprio front-end.
- Após o processamento, chame a interface de alfaiataria, que está escrita no código abaixo, o foco é apenas no
PictureUtils.transApla(restore,169)
método.
A seguir está a interface de recorte:
/**
* 签名图扣掉背景色
* @param request
* @return
*/
@RequestMapping(value = "/signHandle",method = RequestMethod.POST)
public Object getPsPictureSign(HttpServletRequest request){
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
String fileName = null;
String msg = null;
String result = "";
try {
//获取文件
Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
if(fileMap == null || fileMap.isEmpty()){
return addResultMapMsg(false,"未上传签名图片");
}
MultipartFile multipartFile = null;//获取文件名
for (Map.Entry<String, MultipartFile> set : fileMap.entrySet()) {
multipartFile = set.getValue();// 文件名
String uploadfileName = multipartFile.getOriginalFilename();
String suffix = uploadfileName.substring(uploadfileName.lastIndexOf(".")+1).toLowerCase();
if(!uploadSuffix.contains(suffix)){
return addResultMapMsg(false,"只能上传 png、jpg 图片格式");
}
}
//先将文件保存到服务器中,然后操作文件
String fileOriginalName = multipartFile.getOriginalFilename();
String resultStr = File.separator + "pictureTmp" + File.separator + File.separator + fileOriginalName.substring(0,fileOriginalName.lastIndexOf(".")+1) +".png";
fileName = realPath + resultStr;
File restore = new File(fileName);
if(!restore.getParentFile().exists()){
restore.getParentFile().mkdirs();
}
//System.out.println(3+"=="+fileName);
multipartFile.transferTo(restore);
// 抠图工具类
PictureUtils.transApla(restore,169); // 169为灰色的rcb色值
result = resultStr;
} catch (Exception e) {
e.printStackTrace();
msg = "处理失败";
}
if(!StringUtils.isEmpty(msg)){
//说明上传有错
return addResultMapMsg(false,msg);
}else {
return addResultMapMsg(true,result.replace("\\","/"));
}
}
A seguir estão as classes de ferramentas empacotadas, que podem ser usadas diretamente. Além disso, como o método usado está disponível diretamente em java, não há necessidade de fazer referência a pacotes jar adicionais.
O seguinte é o método de classe de ferramenta:
package znxd.lxynzl.controller.photoshop;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.regex.Pattern;
/**
* Created by lingsf on 2020/6/16.
*/
public class PictureUtils {
public static int color_range = 210;
public static Pattern pattern = Pattern.compile("[0-9]*");
public static boolean isNo(String str) {
return pattern.matcher(str).matches();
}
/**
*
* @param file 保存后要处理的png文件
* @param rcb 要扣掉的rcb色值
*/
public static void transApla(File file,int rcb){
InputStream is=null;
try {
is = new FileInputStream(file);
// 如果是MultipartFile类型,那么自身也有转换成流的方法:is = file.getInputStream();
BufferedImage bi = ImageIO.read(is);
Image image = (Image) bi;
ImageIcon imageIcon = new ImageIcon(image);
BufferedImage bufferedImage = new BufferedImage(imageIcon.getIconWidth(), imageIcon.getIconHeight(),
BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D g2D = (Graphics2D) bufferedImage.getGraphics();
g2D.drawImage(imageIcon.getImage(), 0, 0, imageIcon.getImageObserver());
int alpha = 0;
color_range = 255 - rcb; // 0
for (int j1 = bufferedImage.getMinY(); j1 < bufferedImage
.getHeight(); j1++) {
for (int j2 = bufferedImage.getMinX(); j2 < bufferedImage
.getWidth(); j2++) {
int rgb = bufferedImage.getRGB(j2, j1);
if (colorInRange(rgb)) {
alpha = 0;
} else {
alpha = 255;
}
rgb = (alpha << 24) | (rgb & 0x00ffffff);
bufferedImage.setRGB(j2, j1, rgb);
}
}
g2D.drawImage(bufferedImage, 0, 0, imageIcon.getImageObserver());
ImageIO.write(bufferedImage, "png", file);// 直接输出文件
} catch (Exception e) {
e.printStackTrace();
} finally {
if(is!=null){
try{
is.close();
}catch (Exception e){
}
}
}
}
public static boolean colorInRange(int color) {
int red = (color & 0xff0000) >> 16;
int green = (color & 0x00ff00) >> 8;
int blue = (color & 0x0000ff);
if (red >= color_range && green >= color_range && blue >= color_range) {
return true;
}
return false;
}
}
3. Resumo
A função geral é relativamente simples. O back-end fornece apenas uma interface. A principal solução swing
é substituir o pigmento usado. 固定的色值替换为透明色素
Portanto, o diagrama de funções solicita que o usuário 白底黑字
faça o upload com a assinatura o máximo possível.
Claro, você também viu que a foto da assinatura que escrevi acima não foi removida 白底黑字
e a foto ainda pode ser cortada com sucesso.
Endereço de download front-end vue: Disco de rede Baidu Código de extração:nvt2