Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Как прочитать параметры файла JPEG ещё в браузере, до загрузки на сервер? (https://javascript.ru/forum/misc/44231-kak-prochitat-parametry-fajjla-jpeg-eshhjo-v-brauzere-do-zagruzki-na-server.html)

Webnode 12.01.2014 01:06

Как прочитать параметры файла JPEG ещё в браузере, до загрузки на сервер?
 
Добрый день!

Столкнулся с задачей определения параметров изображения в формате JPEG прямо в браузере, ещё до загрузки на сервер, интересуют следующие наиболее важные поля:
- качество изображения (quality)
- размер по вертикали и горизонтали
- тип цветового пространства (sRGB, AdobeRGB и пр.)

Это необходимо для защиты и без того слабого канала от массовой загрузки фото-хлама низкого качества, неподходящих размеров и цветового пространства. На сервере при помощи утилит ImageMagick я конечно это всё узнаЮ уже сейчас, а хочется отсекать ещё на подступах, до загрузки, прямо в браузере.

Понимаю, что это делается на JS+HTML5+FileReader (базовых полей про размер, имя и MIME-тип совсем недостаточно), навыки по написанию скриптов есть, адаптировать смогу, вопрос - где взять/почитать про это? Поиск в сети ничего вразумительного не дал, в основном из PNG при помощи canvas делают JPEG нужного качества и постят на сервер, а мне бы такой ImageMagick да для браузера! :)

Точно видел такое в действии, какой-то сайт по приёму изображений в печать, и как водится, тогда не надо было, а сейчас не найти...

Заранее спасибо за ответ!

kobezzza 12.01.2014 01:54

Считываешь картинку через FileReader, потом загоняешь в канвас, делаешь нужные там тебе трансформации, потом делаем toBlob с указанием нужного тебе качества сжатия и посылаешь аяксом на сервер.

Для уменьшения размера можно пользоваться встроенном в canvas api (drawImage), однако когда я делал такую штуку, то мне не понравилось качество получаемой картинки и я написал свою реализацию уменьшения используя алгоритм Ланцоша, а чтобы не лочился браузер запихнул операцию в отдельный поток (WebWorker).

Полифил для toBlob (не во всех браузерах есть)

if (!HTMLCanvasElement.prototype.toBlob) {
	var hasBlobConstructor = (function () {
		try {
			return Boolean(new Blob());

		} catch (ignore) {
			return false;
		}
	})();

	var hasArrayBufferViewSupport = hasBlobConstructor && (function () {
		try {
			return new Blob([new Uint8Array(100)]).size === 100;

		} catch (ignore) {
			return false;
		}
	})();

	HTMLCanvasElement.prototype.toBlob = function (callback,opt_mime,opt_quality) {
		var __NEJS_THIS__ = this;
		
		if (typeof opt_mime === "undefined") { opt_mime = 'image/png'; }
		if (typeof opt_quality === "undefined") { opt_quality = 1; }
		if (opt_mime === 'image/png') {
			callback(this['msToBlob']());
			return;
		}

		var byteString = atob(this.toDataURL(opt_mime, opt_quality).replace(/[^,]*,/, ''));

		var buffer = new ArrayBuffer(byteString.length),
			intArray = new Uint8Array(buffer);

		for (var i = -1; ++i < byteString.length;) {
			intArray[i] = byteString.charCodeAt(i);
		}

		if (hasBlobConstructor) {
			callback(new Blob(
				[hasArrayBufferViewSupport ? intArray : buffer],
				{type: opt_mime}
			));

			return;
		}

		var builder = new window['MSBlobBuilder']();
		builder['append'](buffer);

		callback(builder['getBlob'](opt_mime));
	}
}

Webnode 12.01.2014 02:19

Спасибо, но именно ваш ответ из мэйнстрима всех найденных мной вариантов, на stackoverflow например.

Мне не нужно уменьшать изображение перед посылкой, я хочу знать, какого качества мне пытаются загрузить фотографию, и если качество/размер/цветовой профиль не соответствует моим нескромным требованиям - то не делать загрузку не сервер, именно это я называл в исходном сообщении защитой от "массовой загрузки фото-хлама низкого качества".

То есть мне нужна фотки качеством не менее 95%, размером не менее 1200x1200 точек, и с профилем sRGB. Именно эти параметры я хочу прочитать на клиенте сразу, как он только выбрал для загрузки фотки.

P.S. Не всегда может кстати быть и EXIF & IPTC в изображении, однако мои костыли на серверной стороне видят несоответствие и в этом случае и бракуют фото.

kobezzza 12.01.2014 02:59

Webnode, ну дык canvas может дать представление изображения в виде массива (getImageData), исследуя этот массив можно сделать заключение о качестве изображения, разрешении и т.д.

danik.js 12.01.2014 05:57

Webnode, думаю лучше сначала разобраться какая инфа где содержится, потом поискать готовые скрипты для разбора jpeg. Например есть же exif ридер на js.

Яростный Меч 13.01.2014 15:28

Цитата:

Сообщение от danik.js
лучше сначала разобраться какая инфа где содержится

+1
в заголовочной части любого формата есть данные о размерах и всё прочее.
прочитываем файл как readAsArrayBuffer, находим нужные байты, делаем выводы.

Webnode 13.01.2014 20:44

+1 что надо содержимое читать, как автор топика поддерживаю! :D

Всё уже придумано до нас, есть библиотека, что читает параметры JPEG, даже drag'n'drop поддерживает примерчик, есть всё, кроме качества(степени сжатия) - это нужно вычислять, парся содержимое файла, как делает ImageMagick.

Библиотека - http://benno.id.au/blog/2009/12/30/h...leapi-jpegmeta ссылка на гитхаб в комментах. К ней - список полей TIFF, может кому пригодится...

Попутно была найдена интересная штука - "онлайн" ImageMagick

Рассказы о невозможности найти качество сходу, так как в файл не пишется - раз, два В первой ссылке этого блока есть кусок кода на C для думок, оттуда видимо и оттолкнусь для дописания jpegmeta(см. первый, так сказать лейбмотивный линк).

Есть здравые речи про двойную перепаковку из 50% качества в 90% или типа того в линке этом тогда всё совсем неопределённо становится, но это пограничный случай воспалённого сознания креатора картинок.

И ещё мнение, что качество - вещь пропиетарная для каждой программы тут, и надо считать в своих "попугаях" коэффициент сжатия. Вот только сильно от сюжета фото зависит это дело...


Часовой пояс GMT +3, время: 13:36.