Russian Qt Forum
Ноябрь 25, 2024, 06:15 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 [2] 3   Вниз
  Печать  
Автор Тема: Быстрый вывод картинки  (Прочитано 32965 раз)
Keiko
Гость
« Ответ #15 : Апрель 28, 2005, 23:38 »

и ещё - OpenGL крайне не рекомедую - это сильно device-dependend решение, ну ты понял Улыбающийся Томозить это будет без драйверов на видео ОЧЕНЬ сильно.
Записан
Keiko
Гость
« Ответ #16 : Апрель 28, 2005, 23:40 »

Код:

/***************************************************************************
                          sq_pixmap.h  -  description
                             -------------------
    begin                : Apr 10 2005
    copyright            : (C) 2005 by Baryshev Dmitry
    email                : ksquirrel@tut.by
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

/*
 *
 * Originally written by
 * Dmitry Smirnov,
 * Saint-Petersburg, Russia
 *
 */

#ifndef SQ_PIXMAP_H
#define SQ_PIXMAP_H

#include <X11/Xlib.h>
#include <X11/extensions/XShm.h>

#include <sys/timeb.h>

class QPaintDevice;

class SQ_Pixmap
{
    public:
        SQ_Pixmap(int, int);
SQ_Pixmap();
        ~SQ_Pixmap();

    private:
        XImage*          m_pXImage;
        XShmSegmentInfo* m_pXShmSegmentInfo;

    public:
        void draw(QPaintDevice *, int, int);
void fillPixmap(unsigned char *data, const int w, const int h);

int width() const;
int height() const;
int region_width() const;
int region_height() const;

    public:
        int* data;
        int  m_width;
        int  m_height;
        int  m_w, m_h;
};

inline int SQ_Pixmap::width() const
{
    return m_width;
}

inline int SQ_Pixmap::height() const
{
    return m_height;
}

inline int SQ_Pixmap::region_width() const
{
    return m_w;
}

inline int SQ_Pixmap::region_height() const
{
    return m_h;
}

#endif
Записан
Keiko
Гость
« Ответ #17 : Апрель 28, 2005, 23:41 »

Код:

/***************************************************************************
                          sq_pixmap.cpp  -  description
                             -------------------
    begin                : Apr 10 2005
    copyright            : (C) 2005 by Baryshev Dmitry
    email                : ksquirrel@tut.by
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include <qpaintdevice.h>
#include <qapplication.h>

#include <X11/Xutil.h>
#include <sys/ipc.h>
#include <sys/shm.h>

#include "sq_pixmap.h"

SQ_Pixmap::SQ_Pixmap()
{
QDesktopWidget *d = QApplication::desktop();

SQ_Pixmap::SQ_Pixmap(d->width()+2, d->height()+2);
}

SQ_Pixmap::SQ_Pixmap(int iWidth, int iHeight) : m_w(0), m_h(0)
{
        m_width  = iWidth;
        m_height = iHeight;

        // create the shared segment
        m_pXShmSegmentInfo = new XShmSegmentInfo;

        // create the shared memory image
        m_pXImage = XShmCreateImage(QPaintDevice::x11AppDisplay(),
(Visual *)QPaintDevice::x11AppVisual(),
QPaintDevice::x11AppDepth(),
ZPixmap, 0,
m_pXShmSegmentInfo, m_width, m_height);

        // create the shared memory segment
m_pXShmSegmentInfo->shmid = shmget(IPC_PRIVATE, m_pXImage->bytes_per_line * m_pXImage->height, IPC_CREAT | 0777);

        // attach the shared memory segment to process
data = (int *)shmat(m_pXShmSegmentInfo->shmid, 0, 0);
m_pXShmSegmentInfo->shmaddr = m_pXImage->data = (char *)data;

        // make the shared memory segment writable
m_pXShmSegmentInfo->readOnly = false;

        // attach the shared memory segment to server
        XShmAttach(QPaintDevice::x11AppDisplay(), m_pXShmSegmentInfo);

memset(data, 0x80, m_width * m_height * 4);
}

SQ_Pixmap::~SQ_Pixmap()
{
        // detach the shared memory segment from server
        XShmDetach(QPaintDevice::x11AppDisplay(), m_pXShmSegmentInfo);

        // destroy the shared memory image
        XDestroyImage(m_pXImage);

        // destroy the shared memory segment
        shmdt(m_pXShmSegmentInfo->shmaddr);
        shmctl(m_pXShmSegmentInfo->shmid, IPC_RMID, 0);
}

void SQ_Pixmap::draw(QPaintDevice* pPaintDevice, int x, int y)
{
    // synchronize X server
    QApplication::syncX();

    // create device context
    GC gc = XCreateGC(pPaintDevice->x11Display(), pPaintDevice->handle(), 0, 0);

    // draw the shared memory image
    XShmPutImage(pPaintDevice->x11Display(), pPaintDevice->handle(), gc,
m_pXImage, 0, 0, x, y, m_w, m_h, true);

    // free device context
    XFreeGC(pPaintDevice->x11Display(), gc);
}

void SQ_Pixmap::fillPixmap(unsigned char *buf, const int w, const int h)
{
    m_w = w;
    m_h = h;

    const int row_stride = w << 2;

    if(w < m_width)
    {
for(int i = 0;i < h;i++)
   memcpy(data+m_width*i, buf + i*row_stride, row_stride);
    }
    else
memcpy(data, buf, (m_width * m_height) << 2);

}
Записан
Keiko
Гость
« Ответ #18 : Апрель 28, 2005, 23:44 »

Работает с несжатыми данными RGBA. Использование:

Код:

unsigned char *data = // ... каким-то образом получаешь данные
int w = 300, h = 200;

SQ_Pixmap *p  = new SQ_Pixmap(w, h);

p->fillPixmap(data, w, h);

// отрисовка по координатам x,y
p->draw(this, 10, 10);
Записан
Admin
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1988



Просмотр профиля
« Ответ #19 : Апрель 29, 2005, 00:07 »

надо попробовать
только вот colortable пугает
Записан
Keiko
Гость
« Ответ #20 : Апрель 29, 2005, 00:15 »

чем ? Улыбающийся Если данные 32-битные (RGBA), colortable = NULL.
Записан
Admin
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1988



Просмотр профиля
« Ответ #21 : Апрель 29, 2005, 00:16 »

у меня данные RGB и без палитры
Записан
Keiko
Гость
« Ответ #22 : Апрель 29, 2005, 00:29 »

надо RGBA - RGB QImage'ем не поддерживается. без палитры, как я уже говорил, colortable = NULL, numColors = 0.
Записан
Admin
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1988



Просмотр профиля
« Ответ #23 : Апрель 29, 2005, 07:18 »

понятно спасибо

буду значит преобразовывать в промежуточныйй формат
Записан
Admin
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1988



Просмотр профиля
« Ответ #24 : Апрель 29, 2005, 08:52 »

в продолжение:

есть QScroollView, в нем картинка сидит QImage
при движение scrollbar картинка смещается и позволяет пользователю просматривать ее, когда она больше чем экран

так вот такой код в paintEvent

Код:
QPixmap pm(*m_pQImg);
bitBlt(viewport(), 0, 0, &pm,contentsX () ,contentsY () ,m_pQImg->width(),m_pQImg->height(),CopyROP, TRUE );


отрабатывает, но возникает проблема, что картинка ездит прекрасно
но края не переририсоваваются. Это понятно когда прогу свернешь и развернешь. Тогда рисует все ок.


что бы послать такое, QScrollBar что бы он перерисовался
Записан
Ruslan Popov
Гость
« Ответ #25 : Апрель 29, 2005, 08:59 »

А я вчера SDLWidget внедрил в свой проект и оно даже работает Улыбающийся
Добавил в него функциональность для работы с оверлеем.
Постараюсь на выходных начать бросать на него кадры из потока...

Насчёт перерисовки, у тебя QPaintEvent не появляется, зови ручками...
Записан
west
Гость
« Ответ #26 : Апрель 29, 2005, 11:06 »

У меня приложение MDI, размер загружемых изображений до гига. Проверял 1300 Мбт, грузило нормально (но долго). Машинки по т.з. слабенькие , ULTRA SPARC 1000, видео стоит совсем дохленькое. GL вертится, но слабо. А с загруженными изображениями еще надо работать - менять яркость - контраст, масштаб,  рисовать объекты и ессетственно скроллировать. Поэтому пришлось делать так - документе (MDI) хранил unsigned char* массив данных изображения. В docView  (он наследован от QScrollView) размещал QImage* m_pImage, размером с видимую userу часть viewport'а. Все события по изменению размера viewport - скроллы, ресайз, масштаб и все такое завязаны на свой метод типа createImage, куда передаю новый размер окна и положение ползунков. В соответствии с этими данными формирую новое изображение. Т.е.  сначала сохраняю существующую палитру из QImage::colorTable , потом m_pImage-reset() m_pImage->create(.........),  потом копирование ( memcpy) соответствующей позиции скроллов и размеру View части изображения из unsigned char* прямо в m_pImage->bits(), копирование назад в новое изображение палитры. Для рисования переописал drawContext(....), в нем вызываю painter->drawImage(....).
где, естесственно рисую свой новый Image. paintEvent не трогал вообще. Получается следующее: дергаешь скролл, попадаешь в обработчик скролла, в котором создается новое изображение. DrawContext система вызовет сама. Для отдельных случаев написал repaintImage, в котором вызывается тот же drawContext , только с параметрами по перерисовке всей видимой области. (Если он вызывается системой, то перерисовывает только добавившуюся , например при рисайзе, часть изображения). Впринципе, своего добился, если изображение загружется (оперативки всего 512 метров,  > 700Мбт свопит жутко), то работает быстро.
Записан
Ruslan Popov
Гость
« Ответ #27 : Апрель 29, 2005, 12:16 »

Я не разбирался с таким вопросом, но думаю в SDL на эту тему есть ответ.

Но если подойти в общем к решению проблемы, то надо посмотреть в сторону mmap (на MSWin тоже есть подобное). Смысл - отображение куска файла в память и никаких свопов!
Записан
west
Гость
« Ответ #28 : Апрель 29, 2005, 13:25 »

Если изображение больше размера оперативки, свопить будет полюбому. Не к файлу же мне каждый раз обращаться.
Записан
Zmey
Гость
« Ответ #29 : Апрель 29, 2005, 13:34 »

Почему бы не использовать QCanvas, QCanvasImage?
Я вывожу через него картинку 2000х1000 12 бит, работает мгновенно.
Записан
Страниц: 1 [2] 3   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.085 секунд. Запросов: 22.