perl-tk: интерактивность визуализирует большие двухмерные растровые данные (например, xvcg) - PullRequest
1 голос
/ 09 января 2011

Я хочу написать приложение на Perl, используя tk для визуализации большого 2-мерного графика (его можно рассматривать как 2-мерное изображение).Мне нужно прокрутить и изменить размер.Также мне не нужно хранить все изображение в памяти.

Он слишком велик, чтобы его можно было сохранить на одной огромной картинке, но я могу легко перерисовать любую ее часть.Итак, я хочу написать графическое приложение для просмотра этих данных в интерактивном режиме.Это похоже на то, что делает xvcg для графиков: http://blogs.oracle.com/amitsaha/resource/blog-shots/apt-rdepends.png (это пример интерфейса. Имеются полосы прокрутки x и y и полосы масштабирования)

Мои данные немного похожи на http://www.access -excel-vba.com /iantchart.png без текста с более тонкими (1px) линиями, множеством точек на них и размерами (на данный момент) от 33000x23000 и будет больше.Я использую 2-битные изображения на пиксель.

Итак, как я могу программировать прокручиваемый и масштабируемый просмотрщик изображений в perl / tk?Требуется не хранить все изображение в памяти (теперь 190 МБ и будет больше!), А попросить некоторую функцию нарисовать его по частям.

О выборе языка / набора инструментов.Мой генератор данных написан на Perl, ОС - Unix / POSIX, поэтому я не хочу переключать язык.Я могу переключиться на другой графический инструментарий, но на целевых ПК уже установлен perl / tk.

Ответы [ 4 ]

2 голосов
/ 09 января 2011

Использование виджета Canvas .Вы можете размещать изображения или рисовать напрямую, в этом случае встроенный метод scale будет обрабатывать изменение размера.С правильными обработчиками для прокрутки вы можете динамически загружать и выгружать контент при перемещении, чтобы сохранить разумное использование памяти.например, обратный вызов для -xscrollcommand будет обнаруживать, когда вы прокручиваете вправо в незагруженную область и загружаете контент для этой области.Вы можете выгрузить предметы один раз, а затем выйти за пределы экрана.

2 голосов
/ 09 января 2011

Это может звучать забавно, но я думаю, что ваш лучший подход - взглянуть на несколько статей о написании эффективной 2D-игры с прокруткой плиток.Я написал что-то похожее на то, что вы описали ранее в Java, но основные понятия те же.Если вы можете понять, как разбить изображение на более мелкие фрагменты, это просто вопрос потоковой передачи и масштабирования только видимых фрагментов.

В качестве альтернативы, вы можете визуализировать все изображение на диск, а затем использовать что-то вродеhttp://www.labnol.org/internet/design/embed-large-pictures-panoramas-web-pages-google-maps-image-viewer/2606/.Карты Google решают ту же проблему, о которой вы упоминали, но в гораздо большем масштабе.Этот метод может сломать изображение, которое вы создали для вас, а затем позволит вам передать его в решение на основе браузера.Имейте в виду, это выходит за рамки ваших требований Perl, но может удовлетворить ваши потребности.

1 голос
/ 11 января 2011

Из ваших примеров данных видно, что то, что вы пытаетесь сделать, может вписаться в различные веб-технологии (либо в массивную таблицу с фоновыми цветами, либо с нуля с тегом HTML <canvas>).

Для Perl, вы можете использовать один из многих методов веб-разработки на стороне сервера или использовать что-то вроде XUL :: Gui , который я написал, который в основном использует Firefox (или другой поддерживаемые браузеры) в качестве движка рендеринга графического интерфейса для Perl.

Вот краткий пример, показывающий, как использовать элемент <canvas> (в данном случае, чтобы нарисовать треугольник Серпинского, из примеров модуля):

use strict;
use warnings;
use XUL::Gui 'g->';

my $width = 400;
my $height = sqrt($width**2 - ($width/2)**2);

g->display(
    g->box(
        g->fill,
        g->middle,
        style => q{
            background-color: black;
            padding:          40px;
        },
        g->canvas(
            id     => 'canvas',
            width  => $width,
            height => int $height,
        )
    ),
    g->delay(sub {
        my $canvas = g->id('canvas')->getContext('2d');
        $canvas->fillStyle = 'white';

        my @points = ([$width/2, 0],
            [0, $height], [$width, $height],
        );
        my ($x, $y) = @{ $points[0] };
        my $num = @points;
        my ($frame, $p);
        while (1) {
            $p = $points[ rand $num ];
            $x = ($x + $$p[0]) / 2;
            $y = ($y + $$p[1]) / 2;

            # draw the point with a little anti-aliasing
            $canvas->fillRect($x + 1/4, $y + 1/4, 1/2, 1/2);

            if (not ++$frame % 1_000) {  # update screen every 1000 points
                $frame % 100_000
                       ? g->flush
                       : g->doevents # keeps firefox happy
            }
        }
    })
);
1 голос
/ 10 января 2011

Если вы не хотите справляться с этим, работая с мозаичными фотоизображениями на холсте (что, по сути, предлагают Майкл Карман и NBJack), вы можете написать свой собственный тип изображения (требует некоторого кода на языке Си). API, который необходимо реализовать, - Tk_CreateImageType, который позволяет настроить пять ключевых аспектов изображений (как они создаются, устанавливаются в отображаемый контекст, рисуются, освобождаются от контекста и удаляются). ). Мне говорят, но, по общему признанию, я не могу сказать, что это достаточно простой в реализации API. Одним из преимуществ этого является то, что вам не нужно иметь почти столько же сложности, сколько существует в типе фотоизображения (который включает в себя все виды экзотики, например, обработку редких типов отображения), и поэтому вы можете использовать более эффективную структуру данных и быстрее обработка.

...