30 мая 2011 г.

Silverlight. Компонент манипулирования над изображением.

Выкладываю свои наработки в Silverlight. Когда  мне захотелось в проект добавить возможность  просмотра изображений (png, jpg, bmp) я не смог найти приемлемого контрола для просмотра изображений. Deep Zoom не подошел так как требует первоначальной обработки тех самых изображений, Image тоже не подошел —  так как требовалось проводить такие манипуляции над изображениями как поворот изображения, масштабирование. Поэтому я сделал свой элемент управления реализующий  масштабирование и вращение изображения.

Скачать проект (Sulverlight4, Visual Studio Expresion 2010)
Скачать только элемент управления
Рис. 1 Компонент за работой
Как Вы видите на рис. 1 видны помимо изображения область залитая синим и зеленым цветом (оставлено для наглядности). Синий - фон  видимой области элемента управления (ScrollViewer), а зеленый — фон активной области, в которой происходит манипуляция над изображением (Grid). Видимая область элемента управления  имеет фиксированное значение ширины и высоты  и отвечает за появление полос прокруток при масштабировании изображений. Активная область определяет размер изображения. Как видно на рисунке 1 при вращение края изображения выступают за пределы активной области (Grid-а), но они не обрезаются, а учитываются в элементе управления путем задания определенных значений свойства margin элемента управления Grid. Наэтом вроде все хитрые моменты закончились, остальное можно увидеть в коде.

xmlns:local="clr-namespace:ImageViewer"
<local:ImageManipulate Width="500" Height="500" x:Name="imageViewer" ActivAreaHeight="600" ActivAreaWidth="600" Background="Blue" ZoomStep="30" RotateStep="3">
    <local:ImageManipulate.Source>
        <!-- Изображение которое будет отображаться -->
        <Image x:Name="imageContent"/>
    </local:ImageManipulate.Source>
    <local:ImageManipulate.CanvasInside>
        <!-- Холст для размещения поверх изображения (может пригодится) -->
                <Canvas Width="auto" Height="auto" x:Name="canavasContent">
        </Canvas>
    </local:ImageManipulate.CanvasInside>
</local:ImageManipulate>Syhi-подсветка кода

параметры Width, Height – ширина и высота элемента управления — видимая часть,
параметры ActivAreaWidth, ActivAreaHight – ширина и высота активной области,
ZoomStep – шаг масштабирования в px,
RotateStep – шаг поворота вокруг оси, проходящей через центральную точку  изображения в градусах.
Методы элемента управления ImageManipulate
Увеличение изображения:
imageViewer.zoomIn();
Уменьшения изображения:
imageViewer.zoomOut();
Поворот против часовой стрелки:
imageViewer.rotateLeft();
Поворот по часовой стрелке:
imageViewer.rotateRight();
Возвращение к первоначальным опциям
imageViewer.setInOriginalSizeAndOrientation();

29 мая 2011 г.

Метапрограммирование на Java Script

Стандартную программу на языке программирования можно представить в виде набора инструкций и набора данных обрабатываемые этими инструкциями. Поэтому суть метапрограммирования можно выразить в концепции  - инструкции это тоже данные, которые можно обрабатывать.
Чтобы погрузится в глубины метопрограммирования на JS надо разобраться с типами данными и с тем, что они из себя представляют.

Практическая ценность
Подумаем, зачем это может понадобится?
В тексте статьи предлагается объект MetaObject, который представляет облегченный инструмент для изучения доступных свойств объектов — полей и методов.  Приводится возможность модификации свойств объектов, внесение новых методов в прототип объекта. Так же приводится краткое изложение основных принципов объектной модели Javascript.

Поехали, в JS всего навсего 6 типов данных:
1.undefined
2.null
3.number
4.string
5.boolean
6.object

Что такое undefined и null.
The undefined value is a primitive value used when a variable has not been assigned a value.
undefined — пустое значение.
The null value is a primitive value that represents the null, empty, or non-existent reference
null — пустая ссылка, ссылка на спец объект, который бросается эксепшенами, когда обращаются к его свойствам/методам.

Что такое объекты в javascript в нескольких тезисах и пояснениях
1) Любой объект имеет ссылку на объект-прототип (в редких случаях эта ссылка может указывать на null) функции  которая создала этот объект.
Объекты в Mozilla/WebKit/KHtml имеют свойство __proto__ , который ссылается на прототип объекта функции создавшей этот объект. Прототип объекта, по умолчанию, имеет свойство   constructor, которая ссылается на искомую функцию. В Internet Explorer свойства __proto__ нет но есть доступ к методу constructor и его прототипу.
2) При доступе к свойству объекта на чтение или на вызов (для методов), если оно не найдено в самом объекте, то ищется в объекте-прототипе, и далее по цепочке.
3) Функция — тоже объект. Числа и строки не являются объектами, но конвертируются в них автоматически в момент вызова методов ('test'.charAt(0) == new String('test').charAt(0)).
4) Любой объект явно или неявно создается с помощью конструкции new и функции-конструктора ([1,2,3] == new Array(1,2,3)).
5) Любая функция имеет свойство prototype, которое как раз и содержит ссылку на объект, используемый в качестве прототипа при создании новых объектов (см. пункт 4). Таким образом — любая функция является конструктором.
//Рассмотрим механизм наследования свойств
function Foo() { } ; 
var f1 = new Foo();
Foo.prototype.x = "hello";
f1.x   //=> hello
Foo.x //=> undedfine
//Еще один пример на тему — любая функция является конструктором
function foo() { } ; 
var f1 = new foo();
f1.constructor === foo.prototype.constructor === foo  
//Заменим объект prototype:
foo.prototype = new Object();
//Что получилось
f1.constructor === foo.prototype.constructor === Object
//so now we say:
foo.prototype.constructor == foo
//all is well again
f1.constructor === foo.prototype.constructor === foo
6) Object, Function, Array, RegExp, String, Number и т.д. — это функции.
7) У любого объекта в начале цепочки прототипов стоит Object.prototype (кроме случаев когда у объекта вообще нет прототипа). У самого Object.prototype ссылка на объект-прототип равна null.
8) Все объекты  автоматически принимают свойства объекта прототипа, как если бы они были объявлены до создания этих объектов. Принятие одноименного свойства  с свойством прототипа объекта приводит к потери последнего:
function foo() { } 
f1 = new foo();
f2 = new foo();
foo.prototype.x = "hello";
f1.x  = "hello"
f2.x  = "hello";
f1.x = "goodbye";   //свойство f1.x скрывает foo.prototype.x
f1.x  = "goodbye"  //скрываем "hello" для экземпляра f1 только
f2.x  = "hello"
delete f1.x
f1.x  = "hello";   //foo.prototype.x снова доступен для f1.

Пример использования метапрограммирования в Javascript.
Бывают случаи, когда во время работы или отладки необходимо знать какими методами и полями обладает какой - либо объект:
$('#button').click(function(e){...})
или
element.onclick=function(e){...}
В первом и во втором случае обработчики события принимают в качестве значение объект e, какие они свойства имеют,  меняется ли набор свойств от браузера к браузеру ???

Для таких случаев был разработан объект MetaObject, способный ответить на эти вопросы.
В объекте всего три метода:
toString() - вывод всех свойств объектов
toFullString() - вывод всех свойств объектов с указанием их значений
feature(property_name, property_value) - метод для непосредственного изменения объектов, удаление|добавление свойств объектов.

//Создадим тестовый объект
function testObj(){
this.field1="mes1";
this.field2=19;
}
testObj.prototype.method1=function(){
if(console.log!=undefined) 
console.log("method1")
}
testObj.prototype.prop1={
"field1":"aaa",
"field2":12
}
//Создадим экземпляр тестового объекта
var obj1=new testObj()
//Создадим экземпляр объекта MetaObject,
// в качестве параметра принимается экземпляр тестового объекта
var objInfo1=new MetaObject(obj1);

window.onload=function(){
//### Добавление и вызов методов ###
//Объекту можно добавить свои методы:
objInfo1.feature("method2",function(){console.log("it is method2")})
objInfo1.feature("method3", new Function("x", "y", "alert(x*y)"))
objInfo1.feature("method4", new Function("x,y", "return x * y"))

//Вызываем свеже-созданный метод:
obj1.method2()
obj1.method3(3,2)
console.log(obj1.method4(9,4))
//Вызов метода передачей имени метода литерной константой:
objInfo1.obj["method2"]()
//#### Изучаем свойства объекта ###
//Получаем код метода:
console.log("Code of method1: %s",objInfo1.obj["method1"].toString())
// 0: Конструктор Объекта (Доступен из объекта прототипа)
console.log("Конструктор объекта: "+objInfo1.obj["constructor"].toString())
// 1: Определим тип объекта прототипа
// свойства __proto__ нет в IE
if (objInfo1.obj["__proto__"]!=null){
console.log("Find type of prototype object: %s",objInfo1.obj["__proto__"].toString())
}else{ 
console.log("Слава Internet Explorer : "+objInfo1.obj["constructor"].toString())
}
// 2: Выведем свойства объекта прототипа: 
var protoMetaObject=new MetaObject(objInfo1.obj["__proto__"]);
console.log("Select all proto fields && methods: %s",protoMetaObject.toString())
// 3: Получаем конструктор прототипа объекта - код функции:
console.log("Constructor of current object (source):\n%s",objInfo1.obj["__proto__"]["constructor"].toString())
//Внедрим в прототип объекта новое свойство поле pirat_field:
objInfo1.obj["__proto__"]["constructor"]["prototype"]["pirat_field"]="wowww"
//Замечания:
// 1) Чтобы внедрить новые свойства достаточно использовать сам объект:
obj1["__proto__"]["constructor"]["prototype"]["pirat_field2"]="wow2"
// 2) И не обязательно использовать свойство __proto__, которое не поддерживается IE:
obj1["constructor"]["prototype"]["pirat_field3"]="wow3"
//Все свойства объекта после махинаций
console.log("Fields & Methods at the end:\n%s",objInfo1.toString())
//С помощью MetaObject выведем все доступные методы и поля
var str=objInfo1.toString()
var testNode=document.getElementById('test1')
testNode.appendChild(document.createTextNode(str))
// и просто выведем их в окне в месте с содержимым:
alert(objInfo1.toFullString())
}
Рис. 1 Результат работы

Другое возможное применение метапрограммирования - слияние экземпляров объекта

//Функция слияния двух объектов mergeLeftObject
//конечный объект - это первый задаваемый объект с уникальными свойствами из второго объекта 
//(т.е. дубликаты из второго объекта не вставляются)
function mergeLObj(obj1,obj2){
var obj3=obj1
for(key in obj2){
if(!obj3[key]){
obj3[key]=obj2[key]
}
}
return obj3
}

console.log('Слияние двух объектов')
// 1-й объект
var dobj1={
"field1":"aaa",
"field2":12
}
// 2-й объект
var dobj2={
"field3":"bbb",
"field4":123
}
// 2-объект скрещиваем с первым и получаем третий объект
var dobj12=mergeLObj(dobj1, dobj2)
//Смотрим на результат
var dobjInfo = new MetaObject(dobj12)
console.log(dobjInfo.toFullString())

22 мая 2011 г.

VoGeeky

На просторах нашей Родины снова объявился журнал с печатной видео рекламой. На этот раз за день до предполагаемого конца света (20 мая) в июньском номере PlayBoy. Журнал был куплен в газетном киоске за 129 рублей, реклама извлечена и распотрошена.
Рис.1 Внутренности

Что на борту у «зверя» :

  1. процессор Ingenic JZ4725B 360Mhz
  2. RAM 16 или 32 MB (теоретически должно быть 32, но на экранчике промелькнуло 16)
  3. RAM 512 MB

Как же его назвать.
Когда устройство распространялся в журнале Vogue его можно было называть Вогоплеером, после PlayBoyя ???

Конфигурация на самом деле не вызывает большого восторга в связи с озвученными характеристиками, но судя по внутренностям данное устройство близко к игровым консолям вида Dingoo A320 и др. садо-мазо-гиковским устройствам  на тех же процах.
Хорошие новости:
К устройству можно припаять  еще 4 кнопки SD/MMC  и др.
На устройство можно прошить аж две оси: Linux и MiniOs (спасибо http://vogeeky.co.cc)
Причем к Linux прошивке можно подключится по ssh (через оставленный usb хвостик),
Плохие новости:
С паяльным делом не знакомы поэтому устройство снабдить элементарными средствами ввода не удастся.

Поэтому,  пока что мне удалось - прошить устройство, настроил интерфейс работы с устройством через ssh, раздобыть toolchain  и написал свою первую программу на C для Mips-овского проца.

Замечание:
В описание я не буду приводить процесс прошивки устройства (в Гуггле ищем по ключевым словам  habra и vogeeky). На устройстве было пришита Linux с сайта  http://vogeeky.co.cc .
Все мероприятия с voGeeky проводились в Ubuntu.
Описание будет немного дотошным, чтобы можно было диагностировать проблемы с подключением на разных этапах.

Подключение к устройству:
1-й Этап. Настраиваем сетевое подключение
И  так у на есть устройство с прошитым Linux, при помощи usb кабеля соединяем устройство  с ПК. В консоли выполняем
#: dmesg > file.txt
В файле file.txt  ищем упоминание о usb0 и подключенном «неведомом» устройстве → Ок
Проверяем доступность соединения usb0 командой:
#: ifconfig usb0 
Если в выдаче присутствует Mac адреса и прочее значит соединение с сетью usb0 есть
Регистрируем свой ПК в этой сети:
#: sudo ifconfig usb0 192.168.1.2 up
(Та же самая команда но с down для удаления)
Проверяем наличие своего ПК в сети usb0, повторяем команду:
#: ifconfig usb0 
В выдаче ищем введенный ip адрес. Если адрес есть то все нормально, можно переходить к ssh

2-й Этап. Подключаемся к ssh
Если ssh, sshd в системе не установлен то надо установить:
#: sudo apt-get install openssh-server
Запускаем sshd:
#: sudo /etc/init.d/ssh start 
(sudo /etc/init.d/ssh restart для перезапуска)
Проверяем статус
#: sudo /etc/init.d/ssh  status
Должны получить что то вроде «sshd is running»

Примечание: Может возникнуть ошибка «Host key verification failed» чтобы ее устранить надо перейти открыть файл ~/.ssh/known_hosts и удалить ключ соответствующего соединения
Так как команда запускается через sudo то файл надо искать в домашней папке root - /root/.ssh/known_hosts .

Устанавливаем коннект:
#: sudo ssh root@192.168.1.1
Пароля нет, все консольный доступ открыт

Примечание: после подключение может возникнуть проблему с роутером если он с тем же ip что и vogeeky

Работаем с voGeeky
Вывод на экран vogeeky
#: echo -e «\n Hello from console \n» > /dev/console
С помощью команды printf:
#: printf «\n Hello from console \n» > /dev/console
Можно раскрасить выдачу:
#: printf «\n\033[1;31m Hello from console\033[m\n» > /dev/console
Где фрагмент «\033[1;31m» приводит к переключение консоли в красный цвет, а «\033[m» возвращает цвет к обратному состоянию.
Подробнее на эту тему http://anton-pribora.ru/articles/os/freebsd/console/
Рис. 2 Экран устройства 
Передача файлов на vogeeky
Что бы передать файл используем команду:
#: cat file_name | ssh remotehost 'cat > file_name'
Для передачи папки:
#: scp -r mydir user@domain.ru:/dir/to
где /dir/to – место в файловой системе на удаленном компьютере 
Пишем программы на C/C++:
Идем на сайт проекта vogeeky http://vogeeky.co.cc/software/linux/kompilacia-adra.
Качаем toolchain и распаковываем его в /opt.
http://alt84.ru/pub_storage/ftp.ingenic.cn/3sw/01linux/00toolchain/mipseltools-gcc412-glibc261.tar.bz2
Добавляем тулчейн в $PATH
#: export PATH=/opt/mipseltools-gcc412-glibc261/bin:$PATH
Если при попытки откомпилировать программу система выдаст что не знает что за компилятор проверьте  наличие пути до папки с компилятором
#: echo $PATH 
в редакторе создаем файл test.c с следующим содержимым
#include
int main(int argc, char **argv) 
{
printf("Hello world Mipsel\n");
}
Компилируем test.c  и собираем исполняемый файл test_mipsel:
#: mipsel-linux-gcc -c test.c
#: mipsel-linux-gcc -o test_mipsel test.o
Копируем исполняемый файл на устройство
Добавляем права на исполнение
#: chmod 777 test_mipsel
Запускаем программу на устройстве:
#: ./test_mipsel 
Рис. 3 Запуск программы на устройстве