Canvas toDataUrl увеличивает размер файла изображения

При использовании toDataUrl() для установки источника тега изображения я обнаружил, что изображение при сохранении намного больше исходного изображения.

В приведенном ниже примере я не указываю второй параметр для функции toDataUrl, поэтому используется качество по умолчанию. Это приводит к значительному увеличению размера оригинального изображения. При задании 1 для полного качества созданное изображение еще больше.

Кто-нибудь знает, почему это происходит или как я могу это остановить?

            // create image
            var image = document.createElement('img');

            // set src using remote image location
            image.src = 'test.jpg';

            // wait til it has loaded
            image.onload = function (){

            // set up variables
            var fWidth = image.width;
            var fHeight = image.height;

            // create canvas
            var canvas = document.createElement('canvas');
            canvas.id = 'canvas';
            canvas.width = fWidth;
            canvas.height = fHeight;
            var context = canvas.getContext('2d');

            // draw image to canvas
            context.drawImage(image, 0, 0, fWidth, fHeight, 0, 0, fWidth, fHeight);

            // get data url 
            dataUrl =  canvas.toDataURL('image/jpeg');

            // this image when saved is much larger than the image loaded in
            document.write('<img src="' + dataUrl + '" />');

            }

Спасибо: D

Вот пример, к сожалению, образ не может быть перекрестным доменом, поэтому мне нужно просто вытащить одно из изображений jsfiddle.

http://jsfiddle.net/ptSUd/

Изображение будет 7.4kb, если вы затем сохраните изображение, которое будет выведено, вы увидите, что оно равно 10kb. Разница более заметна с более подробными изображениями. Если вы установите для качества toDataUrl значение 1, тогда изображение будет 17kb.

Я также использую FireFox 10 для этого, при использовании Chrome размеры изображений еще больше, но не так сильно.

Ответы

Ответ 1

Строка, возвращаемая методом toDataURL(), не представляет исходных данных.

Я только что провел несколько обширных тестов, которые показали, что созданный URL-адрес данных зависит от браузера (а не от операционной системы).

 Environment             -    md5 sum                       - file size
    Original file        - c9eaf8f2aeb1b383ff2f1c68c0ae1085 - 4776 bytes
WinXP Chrome 17.0.963.79 - 94913afdaba3421da6ddad642132354a - 7702 bytes
Linux Chrome 17.0.963.79 - 94913afdaba3421da6ddad642132354a - 7702 bytes
Linux Firefox 10.0.2     - 4f184006e00a44f6f2dae7ba3982895e - 3909 bytes

Метод получения URI данных не имеет значения, следующий фрагмент был использован для проверки того, что URI данных из загрузки файла также отличается:

Тестовый пример: http://jsfiddle.net/Fkykx/

<input type="file" id="file"><script>
document.getElementById('file').onchange=function() {
    var filereader = new FileReader();
    filereader.onload = function(event) {
        var img = new Image();
        img.onload = function() {
            var c = document.createElement('canvas'); // Create canvas
            c.width = img.width;
            c.height = img.height;  c.getContext('2d').drawImage(img,0,0,img.width,img.height);
            var toAppend = new Image;
            toAppend.title = 'Imported via upload, drawn in a canvas';
            toAppend.src = c.toDataURL('image/png');
            document.body.appendChild(toAppend);
        }
        img.src = event.target.result; // Set src from upload, original byte sequence
        img.title = 'Imported via file upload';
        document.body.appendChild(img);
    };
    filereader.readAsDataURL(this.files[0]);
}
</script>

Ответ 2

Размер изображения определяется в основном качеством кодировщика, встроенного в браузер. Он имеет очень мало общего с размером исходного изображения. Когда вы нарисуете что-либо на canvas все, что у вас есть пиксели, у вас больше нет исходного изображения. toDataURL не волшебным образом восстанавливает изображение, которое было нарисовано на canvas. Если вам нужен файл с тем же размером, что и исходное изображение: используйте исходное изображение.

Ответ 3

Похож на кириллоид, и Роб прибил его. У меня тоже была эта проблема, и она кажется комбо:

  • dataURL использует кодировку base64, которая делает ее вокруг 1.37 X больше
  • каждый браузер обрабатывает функцию toDataURL по-разному

размер закодированного изображения base64

Я проверил мой генератор миниатюр в win8.1 firefox и chrome и получил размеры строки данныхURL:

  • firefox = 3.72kB
  • chrome = 3.24kB

Мое исходное изображение при преобразовании в dataURL перешло от 32 кБ до 45 КБ.

Я думаю, что часть base64 является более крупным фактором, поэтому я предполагаю, что теперь мой план состоит в том, чтобы преобразовать dataURL обратно в бинарный массив байтов, прежде чем я сохраню его на сервере (возможно, на стороне клиента, потому что мой сервер ленив).