2012-11-26 12 views
5

C++/Qt için oldukça yeni ve Visual Studio C++ ve Qt (4.8.3) ile bir uygulama oluşturmaya çalışıyorum. Uygulama bir QGraphicsView kullanarak görüntüleri görüntüler, ben görüntüleri piksel düzeyinde değiştirmem gerekiyor.Büyük QImage ile ilgili sorunlar

temel kodu (basitleştirilmiş) olduğu:

QImage* img = new QImage(img_width,img_height,QImage::Format_RGB32); 
while(do_some_stuff) { 
    img->setPixel(x,y,color); 
} 
QGraphicsPixmapItem* pm = new QGraphicsPixmapItem(QPixmap::fromImage(*img)); 
QGraphicsScene* sc = new QGraphicsScene; 
sc->setSceneRect(0,0,img->width(),img->height()); 
sc->addItem(pm); 
ui.graphicsView->setScene(sc); 

Bu çevrede 12000x6000 piksele kadar görüntüler için iyi çalışır. Garip olan bu büyüklüğün ötesinde olur. Ben mesela img_width=16000 ve img_height=8000, boş bir görüntü verir img = new QImage(...) hattını ayarladığınızda. Görüntü verileri 512.000.000 bayt civarında olmalıdır, bu nedenle 32 bitlik bir sistemde bile çok büyük olmamalıdır. Ayrıca, makinem (Win 7 64bit, 8 GB RAM) verileri tutabilmelidir.

Ben de bu sürüm denedim: İlk başta

uchar* imgbuf = (uchar*) malloc(img_width*img_height*4); 
QImage* img = new QImage(imgbuf,img_width,img_height,QImage::Format_RGB32); 

, bu çalışır. Img işaretçisi geçerli ve img->width() numaralı telefonu çağırmak, örneğin doğru görüntü genişliğini (görüntü işaretçisinin boş olması durumunda 0 yerine) döndürür. Ama en kısa sürede img->setPixel() dediğimiz gibi, işaretçi boş olur ve img->width() döner yanlış yapıyorum Yani

0.? Yoksa büyük görüntülerin piksel düzeyinde değiştirilmesinin daha iyi bir yolu var mı?

Selamlar, David

+0

elle ayırma aslında çalışıp çalışmadığını görmek için ilk malloc'd hafızayı sıfır çalışın. –

+0

Şunlara bir göz atın: [Qt Project Wiki: Büyük Resim Yükleme] (http://qt-project.org/wiki/LoadingLargeImages) – dschulz

+0

Bir 32 bit pencere uygulamasında, sonuçta yapabileceğiniz varsayılan en büyük ayırmayı unutmayın. adres alanı parçalanma/LARGEADDRESSAWARE bağlayıcı işareti kullanılarak ve/veya uygulama parçalanması azaltmak için kullandığı DLL rebasing olmadan (2GB uygulama adres alanının) 1.2GB etrafında olacaktır. – drescherjm

cevap

1

Kişisel İkinci yaklaşım gitmek doğru yoldur. Eğer setPixel(), QImage sağlanan dış tampon bir kopyasını oluşturur ve bunun için bellek biterse çağırdığınızda onunla yaşadığınız sorundur.

Piksel değerini doğrudan sağlanan tamponda değiştirmeyi deneyin. İşaretçiyi bir satırın arabelleğine almak için scanLine()'u kullanabilirsiniz. Gerçekten yavaş olduğu için setPixel() kullanmam.

+0

Tamam, teşekkürler. ScanLine() 'a bir göz atacağım. –

4

Qimage 32768x32768 px görüntüleri (kısa imzalı) maksimum destekler. Bu durum aşağıdakilerden oluşur: genişlik * yükseklik * colordepth < INT_MAX (4 milyar) -> 32768 * 32768 * 4 = 4 milyar. İkinci koşul elbette malloc'un istenen belleği tahsis edebilmesidir.

Gerçekten daha büyük resimlere ihtiyacınız varsa, başka bir sarıcı kullanmanız veya birden çok QImage ürününe bölünmeniz gerekir.

2

Sorunu buldum. Linker seçeneklerine /LARGEADDRESSAWARE bayrağını eklemeyi unuttum.

Ayrıca Stephen Chen'in scanLine() ipucu yanıtını gerçekten takdir ettim. İlk önce biraz hafıza kazandırır, ikincisi gerçekten çok daha hızlıdır.

Artık istediğim hedefim olan 32000x16000 piksele kadar görüntüleri güvenli bir şekilde oluşturabilirim.