2012-11-26 35 views
5

Tôi khá mới đối với C++/Qt và tôi đang cố gắng tạo một ứng dụng với Visual Studio C++ và Qt (4.8.3). Ứng dụng hiển thị hình ảnh bằng cách sử dụng QGraphicsView, tôi cần thay đổi hình ảnh ở mức pixel.Các vấn đề với QImage lớn

Mã cơ bản (giản thể):

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); 

này hoạt động tốt cho hình ảnh lên đến khoảng 12000x6000 pixel. Điều kỳ lạ xảy ra ngoài kích thước này. Khi tôi đặt img_width=16000img_height=8000, ví dụ: dòng img = new QImage(...) trả về một hình ảnh rỗng. Dữ liệu hình ảnh nên có khoảng 512.000.000 byte, do đó, nó không nên quá lớn, ngay cả trên một hệ thống 32 bit. Ngoài ra, máy của tôi (Win 7 64bit, 8 GB RAM) nên có khả năng giữ dữ liệu.

Tôi cũng đã thử phiên bản này:

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

Lúc đầu, công trình này. Con trỏ img là hợp lệ và gọi số img->width() ví dụ trả về chiều rộng hình ảnh chính xác (thay vì 0, trong trường hợp con trỏ hình là rỗng). Nhưng ngay sau khi tôi gọi img->setPixel(), con trỏ trở thành null và img->width() trả về 0.

Vì vậy, tôi đang làm gì sai? Hoặc là có cách nào tốt hơn để sửa đổi hình ảnh lớn trên cấp pixel?

Kính trọng, David

+0

Cố gắng không bằng tay bộ nhớ malloc'd trước để xem liệu phân bổ có thực sự hoạt động hay không. –

+0

Hãy xem xét điều này: [Qt Project Wiki: Loading Large Images] (http://qt-project.org/wiki/LoadingLargeImages) – dschulz

+0

Hãy nhớ rằng trên một ứng dụng 32 bit cửa sổ phân bổ lớn nhất mặc định bạn có thể tạo ra kết quả phân vùng không gian địa chỉ sẽ là khoảng 1,2 GB (không gian địa chỉ ứng dụng 2GB) mà không sử dụng cờ liên kết/LARGEADDRESSAWARE và/hoặc rebasing các dll mà ứng dụng của bạn sử dụng để giảm phân mảnh. – drescherjm

Trả lời

1

Cách tiếp cận thứ hai của bạn là đúng cách để đi. Vấn đề bạn đang gặp phải là khi bạn gọi setPixel(), QImage tạo bản sao của bộ đệm ngoài mà bạn đã cung cấp và hết bộ nhớ cho nó.

Thử thay đổi giá trị pixel trực tiếp trong bộ đệm được cung cấp. Bạn có thể sử dụng scanLine() để đưa con trỏ đến vùng đệm của một dòng. Tôi sẽ không sử dụng setPixel() anyway vì nó thực sự chậm.

+0

Ok, cảm ơn. Tôi sẽ xem xét scanLine(). –

4

QImage hỗ trợ tối đa 32768x32768 hình ảnh px (đã ký ngắn). Điều này theo sau điều kiện: chiều rộng * chiều cao * colordepth < INT_MAX (4 tỷ) -> 32768 * 32768 * 4 = 4 tỷ. Điều kiện thứ hai là tất nhiên malloc có thể phân bổ bộ nhớ được yêu cầu.

Nếu bạn thực sự cần hình ảnh lớn hơn, bạn sẽ phải sử dụng một trình bao bọc khác hoặc được chia thành nhiều QImage.

2

Tôi đã theo dõi sự cố. Tôi chỉ quên thêm cờ /LARGEADDRESSAWARE vào tùy chọn Trình liên kết.

Tôi cũng thực sự đánh giá cao câu trả lời của Stephen Chu với gợi ý scanLine(). Đầu tiên nó tiết kiệm một số bộ nhớ, thứ hai nó thực sự nhanh hơn rất nhiều.

Bây giờ tôi có thể tạo hình ảnh lên đến 32000x16000 pixel một cách an toàn, đó là mục tiêu mong muốn của tôi.

Các vấn đề liên quan