2011-07-27 27 views
7

Tôi gặp vấn đề nhỏ: Tôi không thể sửa đổi pixel của màn hình SDL.Làm cách nào để sửa đổi pixel bằng SDL?

Cụ thể, mã sau không hoạt động.

Uint32 * pixels = (Uint32 *) screen -> pixels; 
screen -> pixels = pixels; 

Biên dịch này, nhưng nó không hiển thị gì cả. Tôi đang thiếu gì?

+0

im không thay đổi bất kỳ điểm ảnh đặc biệt ở đây. Tôi chỉ đơn giản là sao chép tất cả mọi thứ ra và cố gắng để sao chép tất cả trở lại. Và theo định dạng, bạn có ý nghĩa gì? – nory

+4

Bạn nhận ra mã của mình không có gì? 'screen-> pixel = screen-> pixel;'. –

+0

tất nhiên.im chỉ rối tung xung quanh, làm quen với cú pháp và các công cụ – nory

Trả lời

-2

Bạn không được sửa đổi nội dung của cấu trúc SDL_Surface. Nếu bạn muốn sao chép các điểm ảnh, bạn nên malloc() một số bộ nhớ và sau đó memcpy() các điểm ảnh.

+0

nhưng mục tiêu của tôi là làm rối tung các pixel – nory

+0

Bạn có thể làm rõ _why_ chúng tôi ** không được sửa đổi ** nội dung của SDL_Surface không? Liệu/nó có thể dẫn đến lỗi/hành vi bất ngờ? – snapfractalpop

+0

@snapfractalpop: Từ tệp 'SDL_video.h':" Cấu trúc này [SDL_Surface] phải được coi là chỉ đọc, ngoại trừ 'pixel' [...] ". Nếu bạn không tuân thủ bạn đang phá vỡ struct bất biến và do đó thư viện sẽ không hoạt động chính xác. – rodrigo

18

Tôi có các chức năng sau nằm xung quanh để đặt pixel trong SDL_Surface. Có hai phiên bản cho các bề mặt 32 bit, 24 bit, 16 bit và 8 bit. Nếu bạn chỉ muốn đặt một pixel, bạn sẽ sử dụng các phiên bản thông thường. Nhưng nếu bạn muốn thiết lập một loạt các điểm ảnh, trước tiên bạn khóa bề mặt, sau đó bạn sử dụng phiên bản nolock (có tên như vậy bởi vì nó không khóa bề mặt), sau đó bạn mở khóa. Bằng cách này bạn không liên tục khóa và mở khóa bề mặt, mà được coi là một hoạt động đắt tiền, mặc dù tôi không nghĩ rằng tôi đã bao giờ thực sự thử nghiệm nó.

void PutPixel32_nolock(SDL_Surface * surface, int x, int y, Uint32 color) 
{ 
    Uint8 * pixel = (Uint8*)surface->pixels; 
    pixel += (y * surface->pitch) + (x * sizeof(Uint32)); 
    *((Uint32*)pixel) = color; 
} 

void PutPixel24_nolock(SDL_Surface * surface, int x, int y, Uint32 color) 
{ 
    Uint8 * pixel = (Uint8*)surface->pixels; 
    pixel += (y * surface->pitch) + (x * sizeof(Uint8) * 3); 
#if SDL_BYTEORDER == SDL_BIG_ENDIAN 
    pixel[0] = (color >> 24) & 0xFF; 
    pixel[1] = (color >> 16) & 0xFF; 
    pixel[2] = (color >> 8) & 0xFF; 
#else 
    pixel[0] = color & 0xFF; 
    pixel[1] = (color >> 8) & 0xFF; 
    pixel[2] = (color >> 16) & 0xFF; 
#endif 
} 

void PutPixel16_nolock(SDL_Surface * surface, int x, int y, Uint32 color) 
{ 
    Uint8 * pixel = (Uint8*)surface->pixels; 
    pixel += (y * surface->pitch) + (x * sizeof(Uint16)); 
    *((Uint16*)pixel) = color & 0xFFFF; 
} 

void PutPixel8_nolock(SDL_Surface * surface, int x, int y, Uint32 color) 
{ 
    Uint8 * pixel = (Uint8*)surface->pixels; 
    pixel += (y * surface->pitch) + (x * sizeof(Uint8)); 
    *pixel = color & 0xFF; 
} 

void PutPixel32(SDL_Surface * surface, int x, int y, Uint32 color) 
{ 
    if(SDL_MUSTLOCK(surface)) 
     SDL_LockSurface(surface); 
    PutPixel32_nolock(surface, x, y, color); 
    if(SDL_MUSTLOCK(surface)) 
     SDL_UnlockSurface(surface); 
} 

void PutPixel24(SDL_Surface * surface, int x, int y, Uint32 color) 
{ 
    if(SDL_MUSTLOCK(surface)) 
     SDL_LockSurface(surface); 
    PutPixel24_nolock(surface, x, y, color); 
    if(SDL_MUSTLOCK(surface)) 
     SDL_LockSurface(surface); 
} 

void PutPixel16(SDL_Surface * surface, int x, int y, Uint32 color) 
{ 
    if(SDL_MUSTLOCK(surface)) 
     SDL_LockSurface(surface); 
    PutPixel16_nolock(surface, x, y, color); 
    if(SDL_MUSTLOCK(surface)) 
     SDL_UnlockSurface(surface); 
} 

void PutPixel8(SDL_Surface * surface, int x, int y, Uint32 color) 
{ 
    if(SDL_MUSTLOCK(surface)) 
     SDL_LockSurface(surface); 
    PutPixel8_nolock(surface, x, y, color); 
    if(SDL_MUSTLOCK(surface)) 
     SDL_UnlockSurface(surface); 
} 
+2

Tôi biết đây là một câu hỏi/câu trả lời cũ, nhưng tôi muốn chỉ ra rằng chương trình sẽ sụp đổ nếu bạn cố gắng lấy một điểm ảnh nằm ngoài giới hạn của bề mặt. Ví dụ, cố gắng để có được một điểm ảnh tại một tọa độ X của 64 từ một bề mặt 64 chiều rộng sẽ sụp đổ vì điểm ảnh cuối cùng là 63. – TyCobb

2

Thao tác nội dung screen->pixels sẽ sửa đổi pixel, với một vài lưu ý.

Đầu tiên, như bạn đã thể hiện trong đoạn mã, lưu ý rằng screen->pixels là một con trỏ trỏ đến dữ liệu pixel của bề mặt. Bản thân dữ liệu pixel được truy cập dưới dạng một mảng tuyến tính từ con trỏ đó dựa trên bề rộng của bề mặt (surface->pitch) và kích thước của pixel theo byte. Kích thước pixel (còn gọi là chiều sâu) được đặt trong khi khởi tạo, sử dụng SDL_SetVideoMode() và có thể được tìm thấy trong screen->format->BytesPerPixel.

Việc khóa bề mặt trước khi thực hiện thay đổi có thể là cần thiết.

Ngoài ra, tùy thuộc vào các tùy chọn được chuyển đến SDL_SetVideoMode() bạn cũng có thể cần gọi số SDL_Flip() để hiển thị các thay đổi bạn đã thực hiện.

Ví dụ làm việc về thao tác pixel có thể được tìm thấy here.


Như đã được chỉ ra trong các nhận xét, mã được liệt kê trong câu hỏi sẽ không thực sự hiển thị khi không có thay đổi nào được thực hiện cho dữ liệu pixel.

1

Thêm một biến thể SDL2 thao tác pixel không phải trên một bề mặt nhưng trong một renderer (và đó không sụp đổ nếu bạn cố gắng để thao tác pixel bên ngoài màn hình của bạn, không giống như câu trả lời trước)

void putPixelRGB(SDL_Renderer* renderer, int x, int y, unsigned char r, unsigned char g, unsigned char b) 
{ 
    SDL_SetRenderDrawColor(renderer, (Uint8)r, (Uint8)g, (Uint8)b, 255); 
    SDL_RenderDrawPoint(renderer, x, y); 
} 
-1

tại sao thay đổi một điểm ảnh ?

tạo ra một bề mặt mới & một Rect

// MÃ ------------>

SDL_Surface *screen, *PIXEL = NULL; 

SDL_Rect PIXELRect; 
PIXELRect.h=5; 
PIXELRect.w=5; 
PIXELRect.x=100; 
PIXELRect.y=100; 

screen = SDL_SetVideoMode(640, 468, 32, SDL_DOUBLEBUF | SDL_HWSURFACE | SDL_ANYFORMAT); 

while(running){ 
SDL_FillRect(screen, &PIXELRect, (#color)); 
} 
Các vấn đề liên quan