Показать сообщение отдельно
  #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 маленькой, но заметной картинкой. Увы похоже моё предположение подтверждается.. или у современных браузеров есть другие средства для реализации данного действия?
Ответить с цитированием