вывод картинки и vrml
Здравствуйте, народ, со светлыми зимними праздниками:victory:
Хочу реализовать такую штуку как вывод картинки(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 маленькой, но заметной картинкой. Увы похоже моё предположение подтверждается.. или у современных браузеров есть другие средства для реализации данного действия? |
1. а зачем передавать с сервера картинку,
2. которую отображать должен браузер, 3. браузеру, который отдаст её 4. js-у, чтобы тот передал ее браузеру и 2. которую отображать должен браузер?! - а?! :blink: |
Gozar,
Вы пожалуй переборщили с игрой слов, на самом деле всё не так запутано, и воможно(если удасться сделать корректным document.open('image/gif')) даже имеет интересное практическое применение. Например, реализовать на javascript почтовый клиент, который будет принимать письма от сервера в самом непосредственном виде, а именно: с заголовками, с двоичным содержимым закодированном в base64. Конечно можно сделать эту обработку на пхп(что почти всегда и делается), но концепция разумного клиент-серверного программирования такова: надо стараться максимально переложить нагрузку с сервера на клиент. Вот я к чему... |
Цитата:
думаю скажет: - опа. и всё. :blink: |
Цитата:
|
Gozar,
теоретически, это могло бы стать костылем для data:url, а в последствии и имплементации canvas на IE6 на голом js без флеша. :) mister_maxim, увы, ни через document.open, ни через src="javascript:'string'" работать оно не будет. |
Цитата:
Цитата:
Цитата:
subzey, а из какого источника Вы точно уверены что это не реализуемо, может он недостаточно достоверный.. можете дать ссылку на него? но вот что инетресное заметил - в Опере всё таки появляется контейнер для картинки, но ка- будто с отсутствующим ресурсом URI в атрибуте src тега img. но и всё равно пишет абру-кадабру вначале. В IE6 вообще пусто в новом окне. Эти два обстоятельства наводят на мысль что может надо всё таки как то добавить в это всё дело тег img а внутри него байтовое содержимое картинки... но глубоко сомневаюсь что получится. Самое обидное, то что если это не возможно, а в интернете пишут что мол - пользуйтесь, например на этой казалось бы англоязычной а значит авторитетной странице. Цитата:
Тем временем проверил я колличество символов строк с содержимым картинки, и в пхп, что выводятся в echo и на javascript что выводятся в document.write просто возникло подозрение что символы при записи в строчку как и на пхп могут сокращаться (см. ps1 первого поста в сабже). Но везде было 58 байт, столько же занимает и сам файл картинки. Но на всякий случай я сделал посимвольный(побайтовый) вывод в write() чтобы точно избежать всяческих "химических реакций" между символами.. но и это не помогло - не вывелась картинка. |
Цитата:
Цитата:
|
Вы меня извините, но по-моему это извращение декодировать текст письма на клиентской стороне в браузере, это надо делать на сервере и чтобы каждый раз не декодировать использовать кеш (или в базу ложить отпрасеный результат), а картинки и вложения к письму ложить на файловую систему и отдавать через веб-сервер
|
Kolyaj,
Всё таки я делал предположение, что отпарсить содержимое письма и выполнить функцию base64_decode для каждого вложения для пхп будет тяжелее чем отправить вместе с апачем всё в непосредственном и чуть большем по объему виде на вывод и плюс отправить дополнительный код javascript, который будет раскодировать и парсить. Но если моё предположение не верно, то Вы безусловно правы. Насчет других серверных технологий для эффективной работы со строками(не пхп), то я ими не владею, а какую бы из них Вы бы посоветовали изучить?.. perl, asp, phyton, java или что то-то еще? Michael83, Не спорю, в силу необычности воспринимается как извращение. А что касается серверного кэширования, то кэшировать можно не только обработанный текст но и отправленные фрагменты непосредственного письма. |
Часовой пояс GMT +3, время: 06:40. |