Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 07.01.2010, 16:20
Аспирант
Отправить личное сообщение для mister_maxim Посмотреть профиль Найти все сообщения от mister_maxim
 
Регистрация: 09.02.2009
Сообщений: 57

вывод картинки и vrml
Здравствуйте, народ, со светлыми зимними праздниками
Хочу реализовать такую штуку как вывод картинки(image/gif) в документ средствами javascript методами document.open("image/gif"); document.write(str); и document.close();, но увы: выводится лишь текст str, а не картинка.
Скрипты все что выкладываю писал в кодировке windows-1251, т.к. нужно чтобы были однобайтовые все символы по умолчанию.
Вот пример:
<html>
<head>
<script language="JavaScript">
Base64 = {
 
	// private property
	//алфавит кодировки base64
	_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
	//отображение символов в с кодами >127 в кодировке w1251 в коды символов в кодировке utf-16be
    w1251_to_utf16be:[1026, 1027, 8218, 1107, 8222, 8230, 8224, 8225, 8364, 8240, 1033, 8249, 1034, 1036, 1035, 1039, 1106, 8216, 8217, 8220, 8221, 8226, 8211, 8212, , 8482, 1113, 8250, 1114, 1116, 1115, 1119, 160, 1038, 1118, 1032, 164, 1168, 166, 167, 1025, 169, 1028, 171, 172, 173, 174, 1031, 176, 177, 1030, 1110, 1169, 181, 182, 183, 1105, 8470, 1108, 187, 1112, 1029, 1109, 1111, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103],
	     //преобразует число 0..255 в символ в кодировки документа w1251
	f_numb_w1251_to_char_utf16be: function(c)//0<=c<=255
	{
	    if(c<128) return String.fromCharCode(c);
        return String.fromCharCode(this.w1251_to_utf16be[c-128]);
    },
	// public method for decoding
	decode : function (input) {
		var output = "";
		var chr1, chr2, chr3;
		var enc1, enc2, enc3, enc4;
		var i = 0;
 
		input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
 
		while (i < input.length) {
 
			enc1 = this._keyStr.indexOf(input.charAt(i++));
			enc2 = this._keyStr.indexOf(input.charAt(i++));
			enc3 = this._keyStr.indexOf(input.charAt(i++));
			enc4 = this._keyStr.indexOf(input.charAt(i++));
 
			chr1 = (enc1 << 2) | (enc2 >> 4);
			chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
			chr3 = ((enc3 & 3) << 6) | enc4;
 
			output = output + this.f_numb_w1251_to_char_utf16be(chr1);
 
			if (enc3 != 64) {
				output = output + this.f_numb_w1251_to_char_utf16be(chr2);
			}
			if (enc4 != 64) {
				output = output + this.f_numb_w1251_to_char_utf16be(chr3);
			}
 
		}
 
		return output;
 
	}
};

function openImage(){
    var b64="R0lGODlhCQAKAIABAOUCAv///yH5BAEAAAEALAAAAAAJAAoAAAIRjAOnuAbfXlISnjoRnjv1LxUAOw==";//красный треугольник в коде base64 строка такая же как и в m.php
    var bytes=Base64.decode(b64);//получили строку из байт
    document.getElementById('div').innerHTML=bytes;//можем проверить и сравнить при закоментированном header('Content-Type: image/gif'); в m.php

    var w= open("about:blank", "displayWindow", 
    "width=500,height=400,status=0,toolbar=0,menubar=0");//открыли новое окно
    //ps. всё удивляюсь: зачем нужен второй параметр "displayWindow" если он не работает как ссылка на созданное окно, а работает возвращаемое "w"
    var d= w.document;//получили ссылку на docunent нового окна для вывода в него
    
    d.open("image/gif", "replace");//на вывод-картинку
    d.write(bytes);//пишем байты из которых состоит картинка
    
    d.close();//не забываем закрыть вывод  
};
</script>
</head>
<body>
    <input type=button value="image" onclick="openImage();">
    <div id='div'></div>
</body>
</html>

код картинки в переменной b64 в формате base64 можете проверить в скрипте, и увидеть что он выдает красный маленький треугольник в формате gif:
<?
 $s='R0lGODlhCQAKAIABAOUCAv///yH5BAEAAAEALAAAAAAJAAoAAAIRjAOnuAbfXlISnjoRnjv1LxUAOw==';
    $s=base64_decode($s);
    header('Content-Type: image/gif');
    echo  $s;
?>

Вы можете закоментировать header и увидеть что выдаваемая абара-кадабра полностью совпадает с тем что выдается в появляющемся окошке, значит раскодирование с base64 происходит правильно не смотря на нетривиальность кода. Значит возможно дело в функционировании браузера, но я проверял на ie6, fairfox3, google chrome, и в opera под виндой икспи, и нигде картинка в появляющемся окне не отображается - только текстовое представление.

Значения массива w1251_to_utf16be - свойство объекта Base64 я получил из скрипта:
<?
        //----------преобразует строку $str в массив с указанным типом $format и наоборот
    //$format: С* - байт в виде цедого числа, И* - 32 битное целое число
    // n* - целое беззнаковое 2-байтовое
   function str_arType($str,$format){
        $ar=unpack($format,$str);
        array_unshift($ar,0);
        array_shift($ar);
        return $ar;
    }
   function arType_str($ar,$format){
        array_unshift($ar,$format);
        $str=call_user_func_array("pack",$ar);
        return $str;
    }

    $str="";
    for($i=0; $i<256; $i++)
    {
        $ar=array();
        $ar[]=$i;
        $s=arType_str($ar,"C*");
        $s=iconv('WINDOWS-1251','UTF-16BE',$s);
        $ar=str_arType($s,"n*");
        echo $ar[0].", ";
    };
?>


ps1:
Кстати, разрабатывая последний скрипт на получение массива, наткнулся на весьма неприятные вещи в php.
Он оказывается некорректно как-то конкатенирует строки представленные в кодировке utf-16be на текущей кодировки windows-1251, вот сам фокус:
<?
        //----------преобразует строку $str в массив с указанным типом $format и наоборот
    //$format: С* - байт в виде цедого числа, И* - 32 битное целое число
    // n* - целое беззнаковое 2-байтовое
   function str_arType($str,$format){
        $ar=unpack($format,$str);
        
        //чтобы не было текстовых ключей начинающих отчет с "1"
        array_unshift($ar,0);// вставляем в начало массива - массив преобразуется в список(массив с всегда отсортированными по возрастанию числовыми ключами)
        array_shift($ar);//удаляем вставленный для преобразования элемент
        return $ar;
    }
   function arType_str($ar,$format){
        array_unshift($ar,$format);//преобразуем в массив с параметрами для вызова функции pack
        $str=call_user_func_array("pack",$ar);
        return $str;
    }
    //--------------------
   
    // фокус номер 1
    $a=array();
    for($i=0; $i<256; $i++)
    {
        $a[$i]=$i;
    };
    $s=arType_str($a,"C*");
    echo strlen($s)."<br>\n";//всё верно 256
    $s=iconv('WINDOWS-1251','UTF-16BE',$s);//по идее размер должен быть увеличен вдвое
    echo strlen($s)."<br>\n";//почему-то выдает не 512, а 304!!!!
    
    // фокус номер 2
    $str="";
    $ars=array();
    for($i=0; $i<256; $i++)
    {
        $ar=array();
        $ar[]=$i;
        $s=arType_str($ar,"C*");
        $s=iconv('WINDOWS-1251','UTF-16BE',$s);
        echo "$i ".strlen($s)."<br>\n";//везде по 2 байта(2 w1251 cимвола) на utf-16be символ, всё верно
        
        $str.=$s;//прилепливаем к строке 1 вариант соединения
        $ars[]=$s;//откладываем в массив 2 вариант соединения

    };
    echo strlen($str)."<br>\n";// по 1 варианту получаем не 512 а 510!!!
    echo strlen(implode('',$ars))."<br>\n";//просто сливаем двухбайтовые строчки массива в одну. по 2 варианту получаем не 512 а тоже 510!!!!!!
    
?>

Может кто найдет этому объяснение? исходная кодировка windows-1251 как я уже говорил... я пока думаю эта нелепица происходит из за управляющих символов, которые, находясь по соседству в строке пожирают друг друга или сливаются.. другого объяснения не вижу.
ps2:
А начиналось всё с того что я решил освоить VRML, и там я набрел на такую ссылку: но итоговый код не заработал, тоже выдавался текст вместо трехмерного кубика. Однако проигрыватель vrml у меня установлен, их даже два у меня:
кортонка и
флукс-плейр
в отдельном файле *.wrl этот представленный куб отображается, а вот выводится в новое окно не хочет, отображается и в окне браузера.. вообщем много тщетно бился, думая что это уже устаревшие стандарты все возможные миме типы попробывал: //x-world/x-vrml, model/vrml,x-world/vrml,application/x-cortona,model/fx3d.
Потом я сделал предположение, что может вывод путем open+write+close в современных браузерах просто напросто не поддерживает mime типы отличные от text/html и text/plain(последний кстати не работает в google chrome почему-то, я проверял). Вот и решил проверить своё предположение на примере с gif маленькой, но заметной картинкой. Увы похоже моё предположение подтверждается.. или у современных браузеров есть другие средства для реализации данного действия?
Ответить с цитированием
  #2 (permalink)  
Старый 08.01.2010, 19:41
Аватар для Gozar
Отправить личное сообщение для Gozar Посмотреть профиль Найти все сообщения от Gozar
 
Регистрация: 07.06.2007
Сообщений: 7,504

1. а зачем передавать с сервера картинку,
2. которую отображать должен браузер,
3. браузеру, который отдаст её
4. js-у, чтобы тот передал ее браузеру и
2. которую отображать должен браузер?!
- а?!
Ответить с цитированием
  #3 (permalink)  
Старый 08.01.2010, 23:15
Аспирант
Отправить личное сообщение для mister_maxim Посмотреть профиль Найти все сообщения от mister_maxim
 
Регистрация: 09.02.2009
Сообщений: 57

Gozar,
Вы пожалуй переборщили с игрой слов, на самом деле всё не так запутано, и воможно(если удасться сделать корректным document.open('image/gif')) даже имеет интересное практическое применение. Например, реализовать на javascript почтовый клиент, который будет принимать письма от сервера в самом непосредственном виде, а именно: с заголовками, с двоичным содержимым закодированном в base64. Конечно можно сделать эту обработку на пхп(что почти всегда и делается), но концепция разумного клиент-серверного программирования такова: надо стараться максимально переложить нагрузку с сервера на клиент. Вот я к чему...
Ответить с цитированием
  #4 (permalink)  
Старый 08.01.2010, 23:31
Аватар для Gozar
Отправить личное сообщение для Gozar Посмотреть профиль Найти все сообщения от Gozar
 
Регистрация: 07.06.2007
Сообщений: 7,504

Сообщение от mister_maxim Посмотреть сообщение
Gozar,
Конечно можно сделать эту обработку на пхп(что почти всегда и делается), но концепция разумного клиент-серверного программирования такова: надо стараться максимально переложить нагрузку с сервера на клиент. Вот я к чему...
Как интересно, а что сделает браузер, когда его заставят принять картинку размером в 2 мегабайта или 5 таких картинок в base64, а Вы посредством js-а заставите её или их отрисовать?!

думаю скажет:
- опа.

и всё.
Ответить с цитированием
  #5 (permalink)  
Старый 08.01.2010, 23:36
Новичок на форуме
Отправить личное сообщение для Kolyaj Посмотреть профиль Найти все сообщения от Kolyaj
 
Регистрация: 19.02.2008
Сообщений: 9,177

Сообщение от mister_maxim
Например, реализовать на javascript почтовый клиент, который будет принимать письма от сервера в самом непосредственном виде, а именно: с заголовками, с двоичным содержимым закодированном в base64.
А зачем? Just for fun?
Ответить с цитированием
  #6 (permalink)  
Старый 09.01.2010, 03:45
Аватар для subzey
Пионэр
Отправить личное сообщение для subzey Посмотреть профиль Найти все сообщения от subzey
 
Регистрация: 16.11.2009
Сообщений: 1,322

Gozar,
теоретически, это могло бы стать костылем для data:url, а в последствии и имплементации canvas на IE6 на голом js без флеша.

mister_maxim,
увы, ни через document.open, ни через src="javascript:'string'" работать оно не будет.

Последний раз редактировалось subzey, 09.01.2010 в 03:49.
Ответить с цитированием
  #7 (permalink)  
Старый 10.01.2010, 13:19
Аспирант
Отправить личное сообщение для mister_maxim Посмотреть профиль Найти все сообщения от mister_maxim
 
Регистрация: 09.02.2009
Сообщений: 57

Сообщение от Gozar
браузер, когда его заставят принять картинку размером в 2 мегабайта или 5 таких картинок в base64, а Вы посредством js-а заставите её или их отрисовать?!
Ну вообще-то знаю что javascript не так уж и быстр, однако не настолько же тугодумен, чтобы запаздывать с перекодированием и парсингом поступающих с интернета байт. Скорость потоков в сети гораздо меньше же внутренних. И кроме того, пхп может и не за 1 запрос передавать сразу всё содержимое письма, javascript может послать несколько поочередных запросов AJAXом после каждой обработки отдельного вложения, или даже по фрагментам одного из вложений, поэтому количество вложений роли играть не будет, да и размер каждого из них тоже..

Сообщение от Kolyaj
А зачем? Just for fun?
Зачем обрабатывать непосредственное содержимое письма скриптом на яваскрипт а не на пхп, это Вы хотели спросить? - затем чтобы не напрягать пхп - вот ответ. Или зачем вообще почтовый клиент нужен на сайте нужен, когда есть прекрасный outlook? или The bat..? - затем что пользователю может не охото париться устанавливая и настраивая эти клиенты, к примеру на чужом компе, где они не стоят, ну и кроме того есть возможность увеличить функциональность, понятность, простоту использования и дизайн.

Сообщение от subzey
увы, ни через document.open, ни через src="javascript:'string'" работать оно не будет.
увы.. увы..
subzey, а из какого источника Вы точно уверены что это не реализуемо, может он недостаточно достоверный.. можете дать ссылку на него?
но вот что инетресное заметил - в Опере всё таки появляется контейнер для картинки, но ка- будто с отсутствующим ресурсом URI в атрибуте src тега img. но и всё равно пишет абру-кадабру вначале. В IE6 вообще пусто в новом окне. Эти два обстоятельства наводят на мысль что может надо всё таки как то добавить в это всё дело тег img а внутри него байтовое содержимое картинки... но глубоко сомневаюсь что получится. Самое обидное, то что если это не возможно, а в интернете пишут что мол - пользуйтесь, например на этой казалось бы англоязычной а значит авторитетной странице.
Цитата:
So if you open it with a gif type, then it will expect you to send a GIF image. Example:
document.open("image/gif");
Хоть бы уж соизволили проверить на работоспособность прежде чем это писать, или продемонстрировали самодостаточный пример а не эту одну строчку, а такового я еще нигде не видел

Тем временем проверил я колличество символов строк с содержимым картинки, и в пхп, что выводятся в echo и на javascript что выводятся в document.write просто возникло подозрение что символы при записи в строчку как и на пхп могут сокращаться (см. ps1 первого поста в сабже). Но везде было 58 байт, столько же занимает и сам файл картинки. Но на всякий случай я сделал посимвольный(побайтовый) вывод в write() чтобы точно избежать всяческих "химических реакций" между символами.. но и это не помогло - не вывелась картинка.
Ответить с цитированием
  #8 (permalink)  
Старый 10.01.2010, 14:11
Новичок на форуме
Отправить личное сообщение для Kolyaj Посмотреть профиль Найти все сообщения от Kolyaj
 
Регистрация: 19.02.2008
Сообщений: 9,177

Сообщение от mister_maxim
Зачем обрабатывать непосредственное содержимое письма скриптом на яваскрипт а не на пхп, это Вы хотели спросить?
Только не на PHP в частности, а на сервере.

Сообщение от mister_maxim
затем чтобы не напрягать пхп
А где там напряжение? Раскодировать base64 и выдать его клиенту в отдельном запросе, в результате чего и объем передаваемых данных уменьшится.
Ответить с цитированием
  #9 (permalink)  
Старый 11.01.2010, 02:35
Интересующийся
Отправить личное сообщение для Michael83 Посмотреть профиль Найти все сообщения от Michael83
 
Регистрация: 05.01.2010
Сообщений: 28

Вы меня извините, но по-моему это извращение декодировать текст письма на клиентской стороне в браузере, это надо делать на сервере и чтобы каждый раз не декодировать использовать кеш (или в базу ложить отпрасеный результат), а картинки и вложения к письму ложить на файловую систему и отдавать через веб-сервер
Ответить с цитированием
  #10 (permalink)  
Старый 11.01.2010, 10:04
Аспирант
Отправить личное сообщение для mister_maxim Посмотреть профиль Найти все сообщения от mister_maxim
 
Регистрация: 09.02.2009
Сообщений: 57

Kolyaj,
Всё таки я делал предположение, что отпарсить содержимое письма и выполнить функцию base64_decode для каждого вложения для пхп будет тяжелее чем отправить вместе с апачем всё в непосредственном и чуть большем по объему виде на вывод и плюс отправить дополнительный код javascript, который будет раскодировать и парсить. Но если моё предположение не верно, то Вы безусловно правы.
Насчет других серверных технологий для эффективной работы со строками(не пхп), то я ими не владею, а какую бы из них Вы бы посоветовали изучить?.. perl, asp, phyton, java или что то-то еще?
Michael83, Не спорю, в силу необычности воспринимается как извращение. А что касается серверного кэширования, то кэшировать можно не только обработанный текст но и отправленные фрагменты непосредственного письма.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как проверить загружены ли все картинки браузером Aderba jQuery 13 29.05.2014 14:18
Получение координат от картинки EmDmAl Events/DOM/Window 4 08.11.2009 14:34
Как изменить размер картинки? Mihail Общие вопросы Javascript 1 25.10.2009 13:42
Пошаговый вывод скрипта для IE всех версий. Zidky Элементы интерфейса 10 17.06.2009 18:27
Preview большой картинки jusalex Элементы интерфейса 4 15.01.2009 18:01