 
			
				28.06.2020, 19:10
			
			
			
		  
	 | 
 
	
		
		
		
			
			| 
			
				
				
				 Кандидат Javascript-наук 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 28.12.2018 
					
					
					
						Сообщений: 138
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	| 
	
	
		
		
			
			 
				Как уменьшить размер картинки, сохранив пропорции?
			 
			
		
		
		
		При нажатии кнопки я получаю данные с canavas, с помощью метода toDataURL. Потом этот результат при нажатии на ссылки отображается в браузере  
вот так: 
data:image/png;base64,....... 
Картинка отображается в браузере полностью. Можно её как нибудь уменьшить, сохранив пропорции в пикселях, и снова её отобразить? 
data:image/png;base64,....... 
Вот код:
 
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<title></title>
		<meta name="description" content="" />
		<meta name="keywords" content="" />
		<meta name="author" content="" />
		<script src="jquery-2.1.1.min.js"></script>
    <script>
    window.onload = function()
    {
        var canvas = document.getElementById("drawCanvas"),
        context = canvas.getContext("2d");
        canvas.width = 800;
        canvas.height = 600;
       
        var img = new Image();
        img.src = "darth_vader_star_wars.jpg";
        
        img.onload = function()
        {
         context.drawImage(img, 0, 0);
        }
        $("#submitGraphic").click( function(){
           
            var canvas = document.getElementById("drawCanvas");
             var img = new Image();
            img.src = "darth_vader_star_wars.jpg"; 
            var context = canvas.getContext("2d");
            var tempCanvas = document.createElement("canvas"),
                 tCtx = tempCanvas.getContext("2d");
           
            tempCanvas.width = 640;
            tempCanvas.height = 480;
            tCtx.drawImage(canvas,0,0);
            var img = tempCanvas.toDataURL("image/png");
            document.write('<a href="'+img+'"><img src="'+img+'"/>Пример</a>');
        })
    }
  </script>
	</head>
 <body> 
    
		   <canvas id="drawCanvas"></canvas>
      <button id="submitGraphic">Click</button>
	</body>
</html>
 
		
	
		
		
		
		
		
		
		
						  
				
				Последний раз редактировалось Katy93, 28.06.2020 в 19:12.
				
				
			
		
		
	
		
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				28.06.2020, 19:22
			
			
			
		  
	 | 
 
	
		
		
		
			
			| 
			
				
				
				 Профессор 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 14.01.2015 
					
					
					
						Сообщений: 12,989
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	| 
	
	
		
		
		
		
		 <img style="width: пиксели,проценты,...;height: auto;" src="'+img+'"/> 
		
	
		
		
		
		
		
		
	
		
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				28.06.2020, 19:32
			
			
			
		  
	 | 
 
	
		
		
		
			
			| 
			
				
				
				 Кандидат Javascript-наук 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 28.12.2018 
					
					
					
						Сообщений: 138
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	
	
	
		
		
		
		
		Это тестовый пример, а если мне потом надо будет сохранить в папку, уменьшенную картинку.  
	
 
	| 
		
			 Цитата: 
		
	 | 
 
	
		<?php  
if ( isset($_POST["image"]) && !empty($_POST["image"]) ) {  
 
    
    $data = $_POST['image']; 
     
    
    $uri =  substr($data,strpos($data,",")+1); 
 
    
    $file = time().'.png'; 
 
    
    file_put_contents("./files/".$file, base64_decode($uri)); 
 
    
    echo $file; 
 
} 
?>
	 | 
 
	
 
  
		
	
		
		
		
		
		
		
	
		
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				28.06.2020, 19:38
			
			
			
		  
	 | 
 
	
		
		
		
			
			| 
			
				
				
				 Профессор 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 14.01.2015 
					
					
					
						Сообщений: 12,989
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	
	
	
		
		
		
		
		Вы о чем ведете речь? То что показано, это не уменьшение физических размеров, это отображение в указанных размерах. 
Если речь идет о сохранении на сервере с уменьшением, то уменьшайте, нет проблем. Но если вы уменьшенное хотите затем увеличить, то результат будет не из лучших. Хранят обычно две/более копии, оригинал и меньшие.
 
ile_put_contents("./files/".$file, base64_decode($uri)); - это не лучший вариант передачи на сервер, так как размер данных в три раза больше оригинала будет, есть и  более экономичный.  
		
	
		
		
		
		
		
		
	
		
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				28.06.2020, 20:26
			
			
			
		  
	 | 
 
	
		
		
		
			
			| 
			
				
				
				 Кандидат Javascript-наук 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 28.12.2018 
					
					
					
						Сообщений: 138
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	
	
	
		
		
		
		
		
	
 
	| 
		
			 Цитата: 
		
	 | 
 
	| 
		Если речь идет о сохранении на сервере с уменьшением, то уменьшайте, нет проблем.
	 | 
 
	
 
 В этом и заключается вопрос, как уменьшить размер картинки, с сохранением пропорций, даже если на сервере. То как это можно сделать?  
		
	
		
		
		
		
		
		
	
		
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				28.06.2020, 20:29
			
			
			
		  
	 | 
 
	
		
		
		
			  | 
			
			
				
				
				 Профессор 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 25.10.2016 
					
					
					
						Сообщений: 1,013
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	
	
	
		
		
		
		
		Katy93,
 
тебе надо уменьшить картинку, чтобы она вписалась в некоторый прямоугольник?
 
сначала вычисляем целевые размеры картинки:
 
function resizeToBounds(imgW, imgH, boundsW, boundsH) {
    if (imgW <= boundsW && imgH <= boundsH) {
        return null;
    }
    var rw = boundsW / imgW;
    var rh = boundsH / imgH;
    var r = Math.min(rw, rh);
    return {
        width: Math.round(imgW * r),
        height: Math.round(imgH * r)
    };
}
если это вернет null, то уменьшать не надо.
 
иначе создаем вспомогательную канву с такими размерами, кидаем на неё картинку методом drawImage с кучей параметров - 3 вариант отсюда  https://developer.mozilla.org/ru/doc...xt2D/drawImage
потом просто сохраняем вспомогательную канву.
 
кстати у канвы есть метод toBlob, обычно он более подходящий чем toDataURL  
		
	
		
		
		
		
		
		
	
		
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				28.06.2020, 20:39
			
			
			
		  
	 | 
 
	
		
		
		
			
			| 
			
				
				
				 Профессор 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 14.01.2015 
					
					
					
						Сообщений: 12,989
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	
	
	
		
		
		
		
		
	
 
	| 
		
			Сообщение от Katy93
			
		
	 | 
 
	| 
		То как это можно сделать?
	 | 
 
	
 
 Да сделать то проще простого, это можно сделать и на клиенте. Но тут есть маленькое но. На клиенте canvas использует не самый из хороших методов интерполяции в угоду быстродействия. В чем суть вопроса, можете почитать, например, тут:
 https://www.cambridgeincolour.com/ru...erpolation.htm
https://overcoder.net/q/9369/html5-c...ачества
Но если в вашем проекте это не критично, то можно и на клиенте уменьшить, контролируя процесс визуально. На сервере даже стандартное входящее в РНР расширение GD имеет гораздо больше выбора в методах. А уменьшить изображение в этом расширение в случае РНР версии начиная с 5.5, можно простой функцией  imagescale(). До этого можно выбрать и метод интерполяции. Почитайте о функциях GD. Ранее было проблемой использовать ImageMagick, еще одно богатейшее средство для работы с графикой, теперь на многих хостах оно имеется и предлагается, а в РНР добавлено как расширение. Правда многие функции его пока экспериментальные или не документированы.  
		
	
		
		
		
		
		
		
	
		
			
			
	
			
			
			
			
			
				 
			
			
			
			
			
			
				
			
			
			
		 
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				28.06.2020, 20:47
			
			
			
		  
	 | 
 
	
		
		
		
			  | 
			
			
				
				
				 Профессор 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 25.10.2016 
					
					
					
						Сообщений: 1,013
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	
	
	
		
		
		
		
		
	
 
	| 
		
			Сообщение от laimas
			
		
	 | 
 
	| 
		На клиенте canvas использует не самый из хороших методов интерполяции в угоду быстродействия.
	 | 
 
	
 
 для фотографий канвасное уменьшение картинки дает вполне приличный результат.
 
для нарисованных картинок не очень, но можно найти код, который это делает попиксельно с хорошим качеством  
		
	
		
		
		
		
		
		
	
		
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				28.06.2020, 20:53
			
			
			
		  
	 | 
 
	
		
		
		
			
			| 
			
				
				
				 Профессор 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 14.01.2015 
					
					
					
						Сообщений: 12,989
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	
	
	
		
		
		
		
		
	
 
	| 
		
			Сообщение от Alexandroppolus
			
		
	 | 
 
	| 
		для фотографий канвасное уменьшение картинки дает вполне приличный результат
	 | 
 
	
 
 Ну тут "приемлемый", это понятие относительное. Кому-то приемлемо, а кому-то ни к черту не годится.    Да и в случае если не требуется визуализации процесса, какая фиг разница кто этим займется, клиент или сервер.  
		
	
		
		
		
		
		
		
	
		
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				29.06.2020, 06:59
			
			
			
		  
	 | 
 
	
		
		
		
			
			| 
			
				
				
				 Профессор 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 14.01.2015 
					
					
					
						Сообщений: 12,989
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	
	
	
		
		
		
		
		Перечитал еще раз первый пост ваш,  Katy93, но так и не прояснилось назначение действа: картинка -> кнопка -> картинка -> сохранить.
 
Надо еще учитывать и фактор формата изображения. Застал ли ваш возраст такой девайс как видеомагнитофон не знаю, а те кто смотрел кино на нем знают, что Рембо не только гудосявит, но может и выглядеть как мультяшний персонаж, так как кассета, это Nn копия с Nn оригинала. Все потому, что в видео компрессор MJPEG. JPEG компрессия использует тот факт, что наше зрение больше восприимчиво к потерям яркости, чем к потерям цвета. В этом компрессоре RGB пространство преобразовывается в три компоненты - яркостную и две цветовые (хроматическую красную и синею), последние две и урезаются, имеют больший коэффициент сжатия, больше потерь. 
 
Когда изображение открывается в редакторе или в том же canvas, GD, ..., происходит декомпрессия с восстановлением RGB пространства. Естественно это пространство восстанавливается уже с потерями, ранее урезанными при компрессии. Если теперь сохранить изображение в формате JPEG, то цветовые компоненты опять будут сжаты при компрессии (урезаны), даже если изображение не масштабировалось. А при масштабировании будут и дополнительные потери (искажения, артефакты). В видео для цветовых составляющих выделена к тому же еще и более узкая полоса частот, чем у яркостной, поэтому в MJPEG Рембо легко превращается в мультика уже после нескольких последовательных копий с копий.
 
Масштабировать изображение нужно один раз при загрузке его на сервер. Как масштабировать, это зависит от условия. Если жестко определены ширина/высота, то сначала проверяется отношение сторон, если оно равно такому же отношению меньшего изображения, то, например, в GD функции imagescale достаточно передать только размер ширины. Если пропорции иные (отношения не равны), то вырезают пропорциональную часть изображения центрированную по ширине/высоте в зависимости от ориентации изображения, с последующим масштабированем. Или сначала масштабируют, а затем обрезают по краям. Если же ограничение только по одной стороне, то есть, не более W по ширине и не более H по высоте, при этом другая сторона может иметь произвольный размер, то поступают также как и при равных отношениях сторон. Чистая арифметика, а функций вырезать и скопировать, уменьшить, хватает. При этом, если нужно изготовить несколько малых копий с постоянным уменьшением, то готовить их все нужно с оригинала, а не каждую последующую с предыдущей. Иначе в такой матрешке самая последняя будет иметь наихудшее качество обусловленное многократным сжатием.  
 
А вот конечная цель масштабирования, это уже философия иного плана, сколько, чего и для чего. Может  это вам пригодится и определит в конечном итоге как поступить.  
		
	
		
		
		
		
		
		
		
						  
				
				Последний раз редактировалось laimas, 29.06.2020 в 07:21.
				
				
			
		
		
	
		
		
	
	
	 | 
 
 
	 
		 | 
 
 
 
 
 
 
 
	 | 
 
 
 |