from PIL import Image import numpy as np def remove_black_background(img_path, out_path): # Carregar imagem e garantir modo RGBA img = Image.open(img_path).convert("RGBA") data = np.array(img) # Extrair canais r, g, b, a = data[:,:,0], data[:,:,1], data[:,:,2], data[:,:,3] # O alpha original é estimado pelo valor máximo dos canais R, G, B # Isso funciona porque o fundo é preto (0,0,0) # Usamos fmax para obter o valor float e evitar overflow/underflow max_rgb = np.fmax(np.fmax(r, g), b) # Criar nova imagem com o mesmo tamanho new_data = np.zeros_like(data) # O novo alpha é o valor máximo de R, G, B new_alpha = max_rgb.astype(np.uint8) # Onde new_alpha é maior que zero, desmultiplicamos a cor para remover o halo preto mask = new_alpha > 0 # Copiar canais new_data[:,:,0] = r new_data[:,:,1] = g new_data[:,:,2] = b new_data[:,:,3] = new_alpha # Aplicar unmultiplying alpha para clarear os pixels semi-transparentes de borda # R_new = R_old * 255 / alpha alpha_float = new_alpha.astype(float) for i in range(3): channel = data[:,:,i].astype(float) # Onde a máscara for verdadeira, calcula. Onde for falsa, deixa zero. adjusted = np.zeros_like(channel) adjusted[mask] = np.minimum(255, (channel[mask] * 255.0 / alpha_float[mask])) new_data[:,:,i] = adjusted.astype(np.uint8) # Salvar a nova imagem out_img = Image.fromarray(new_data, "RGBA") out_img.save(out_path, "PNG") print(f"Processada: {img_path} -> {out_path}") if __name__ == "__main__": remove_black_background("logotipo_steelXR.png", "public/logotipo_steelXR_transparente.png") remove_black_background("iconeXR.png", "public/iconeXR_transparente.png")