Bem-vindos à nossa comunidade!

Junte-se a nós e faça parte hoje mesmo!

Compressão de imagens antes do upload

Bene Júnior

Novo Membro
Cadastro
8/6/21
Postagens
4
Curtidas
0
Pontuação
1
Cidade
Sumaré
Olá, pessoal!

Preciso diminuir o tamanho em bytes e em pixels de imagens antes de upar pro servidor. No entanto, só estou conseguindo exibir as imagens já alteradas mas, ao enviar para o servidor, a imagem que vai é a original, do computador, não alterada. Veja:

HTML:

HTML:
<input type="file" name="file" id="file" accept="image/*">

<img class="img-responsive" id="image-preview" src="" alt="foto">


JAVASCRIPT:

JavaScript:
const compress = new Compress()

const preview = document.getElementById('image-preview')

const upload = document.getElementById('file') upload.addEventListener('change', (evt) => {

  const files = [...evt.target.files]

  compress.compress(files, {
    size: 4,
    quality: 0.75,
    maxWidth: 1280, // the max width of the output image
    maxHeight: 720, // the max height of the output image   
    resize: true
  }).then((images) => {

    const img = images[0]

    // returns an array of compressed images
    preview.src = `${img.prefix}${img.data}`      })

}, false)

No Javascript acima as imagens são convertidas para 1280x720 com até 2MB. O preview mostra a imagem já convertida (ao "salvar como" o tamanho em byte e dimensões da imagem apresentada no preview ficam com as dimensões convertidas). Somente quando envio pro servidor é que a imagem vai "crua", ou seja, sem a conversão.

Preciso muito resolver esse problema.

Obrigado!
 
Last edited by a moderator:

mourabraz

Membro
Moderador
Cadastro
23/12/20
Postagens
113
Curtidas
158
Pontuação
100
Cidade
Leiria
@Bene Júnior Bom dia!

Pelo que pude entender você faz a compressão/alteração das imagens, mas não chega a mudar o que vai na request... Vc pode escolher alterar os files do próprio input ou alterar na request (mais fácil se estiver controlando isto manualmente).

Quando as imagens estiverem alteradas você atualiza o preview, mas não chega a atualizar o campo "files" no form. Podes atualizar ele da mesma forma que atribuiste um novo valor ao "src" da tag "img". No caso será no input do type="file", e não será o "src", mas o atributo apropriado "files". Vê na documentação porque acho que tem que ser um array, mas não tenho certeza!

Abraços!
 

Bene Júnior

Novo Membro
Cadastro
8/6/21
Postagens
4
Curtidas
0
Pontuação
1
Cidade
Sumaré
@Bene Júnior Bom dia!

Pelo que pude entender você faz a compressão/alteração das imagens, mas não chega a mudar o que vai na request... Vc pode escolher alterar os files do próprio input ou alterar na request (mais fácil se estiver controlando isto manualmente).

Quando as imagens estiverem alteradas você atualiza o preview, mas não chega a atualizar o campo "files" no form. Podes atualizar ele da mesma forma que atribuiste um novo valor ao "src" da tag "img". No caso será no input do type="file", e não será o "src", mas o atributo apropriado "files". Vê na documentação porque acho que tem que ser um array, mas não tenho certeza!

Abraços!

Moura, obrigado pela resposta!

Como atribuo o novo valor ao input? Tem algum link ou tópico que trata desse assunto?
 

mourabraz

Membro
Moderador
Cadastro
23/12/20
Postagens
113
Curtidas
158
Pontuação
100
Cidade
Leiria
@Bene Júnior

Eu falei errado no post anterior, peço descula por ter lhe induzido no caminho errado.

Não vai ser possível atribuir dinamicamente os valores ao input de files. Hum... será que criando um novo FormData e depois fazendo o upload com ele daria certo?

Se quiser posso tentar fazer. Você consegue compartilhar o problema completo. Tipo qual a rota para o upload da imagem e que campos essa request precisa?

Abraços:
 

Bene Júnior

Novo Membro
Cadastro
8/6/21
Postagens
4
Curtidas
0
Pontuação
1
Cidade
Sumaré
Boa noite, Mourabraz!

Os códigos completos são:

JAVASCRIPT:

<script>
JavaScript:
const compress = new Compress();
const preview = document.getElementById('image-preview');
const output = document.getElementById('output');
const upload = document.getElementById('file');

upload.addEventListener('change', (evt) => {
  const files = [...evt.target.files]
  compress.compress(files, {
    size: 4, // the max size in MB, defaults to 2MB
    quality: 0.75, // the quality of the image, max is 1,
    maxWidth: 500, // the max width of the output image, defaults to 1920px
    maxHeight: 300, // the max height of the output image, defaults to 1920px
    resize: true // defaults to true, set false if you do not want to resize the image width and height
  }).then((images) => {

const img = images[0];
preview.src = `${img.prefix}${img.data}`;
imgElement.onload = function (e) {
      const canvas = document.createElement("canvas");
      const MAX_WIDTH = 400;
const scaleSize = MAX_WIDTH / e.target.width;
      canvas.width = MAX_WIDTH;
      canvas.height = e.target.height * scaleSize;

const ctx = canvas.getContext("2d");
ctx.drawImage(e.target, 0, 0, canvas.width, canvas.height);
const srcEncoded = ctx.canvas.toDataURL(e.target, "image/jpeg");
document.querySelector("#image-preview").src = srcEncoded;
})
}, false)
<script>

O JavaScript acima pega a imagem original, converte para 500x300 pixels (máximo de 2MB) e mostra na tela.

HTML:
<input type="file" name="file" id="file" accept=".jpg, .jpeg, .png, .gif">
<img class="img-responsive" id="image-preview" src="" alt="foto">
Ao clicar no botão para enviar a imagem, o que é enviado é a imagem original, não da mostrada na tela (preview).
 
Last edited by a moderator:

mourabraz

Membro
Moderador
Cadastro
23/12/20
Postagens
113
Curtidas
158
Pontuação
100
Cidade
Leiria
Bom dia @Bene Júnior Desculpa a demora!

Eu queria era ver como estás a enviar o "form". Se tiver como enviar por javascript acredito que adicionar as imagens comprimidas a um formData seja mais fácil.Já que adicionar o arquivo ao atributo files do input não dá!
 

Bene Júnior

Novo Membro
Cadastro
8/6/21
Postagens
4
Curtidas
0
Pontuação
1
Cidade
Sumaré
Bom dia @Bene Júnior Desculpa a demora!

Eu queria era ver como estás a enviar o "form". Se tiver como enviar por javascript acredito que adicionar as imagens comprimidas a um formData seja mais fácil.Já que adicionar o arquivo ao atributo files do input não dá!
Boa noite!

O meu script JavaScript está assim:

const compress = new Compress();
const preview = document.getElementById('image-preview');
const output = document.getElementById('output');
const upload = document.getElementById('file');


upload.addEventListener('change', (evt) => {
const files = [...evt.target.files]
compress.compress(files, {
size: 4, // the max size in MB, defaults to 2MB
quality: 0.75, // the quality of the image, max is 1,
maxWidth: 500, // the max width of the output image, defaults to 1920px
maxHeight: 300, // the max height of the output image, defaults to 1920px
resize: true // defaults to true, set false if you do not want to resize the image width and height
}).then((images) => {

const img = images[0];
// returns an array of compressed images
preview.src = `${img.prefix}${img.data}`;

imgElement.onload = function (e) {
const canvas = document.createElement("canvas");
const MAX_WIDTH = 400;

const scaleSize = MAX_WIDTH / e.target.width;
canvas.width = MAX_WIDTH;
canvas.height = e.target.height * scaleSize;

const ctx = canvas.getContext("2d");

ctx.drawImage(e.target, 0, 0, canvas.width, canvas.height);

const srcEncoded = ctx.canvas.toDataURL(e.target, "image/jpeg");

// you can send srcEncoded to the server
document.querySelector("#image-preview").src = srcEncoded;

};

const { endSizeInMb, initialSizeInMb, iterations, sizeReducedInPercent, elapsedTimeInSeconds, alt } = img;

output.innerHTML = `<b>Start Size:</b> ${initialSizeInMb} MB <br/><b>End Size:</b> ${endSizeInMb} MB <br/><b>Compression Cycles:</b> ${iterations} <br/><b>Size Reduced:</b> ${sizeReducedInPercent} % <br/><b>File Name:</b> ${alt}`

})
}, false)

HTML:

<form action="/bcadmin/clientes/{$cliente.idcliente}" method="post" enctype="multipart/form-data" role="form">
<input type="file" name="file" id="file" accept=".jpg, .jpeg, .png, .gif">
<img class="img-responsive" id="image-preview" src="{$cliente.desphoto}" alt="foto">
 
Top