C++ 什么';从图像文件中读取纹理信息并使用SDL2获取像素的最佳方法是什么?

C++ 什么';从图像文件中读取纹理信息并使用SDL2获取像素的最佳方法是什么?,c++,sdl,C++,Sdl,可以使用CreateTexture()在SDL2中创建纹理,然后使用LockTexture()访问该纹理中的像素。但要做到这一点,您需要将SDL_TEXTUREACCESS_STREAMING标志传递给CreateTexture调用 有一个相当标准的用于加载图像的助手库,称为SDL_image。我使用它将图像文件读入纹理(纹理是供临时观察者使用的图形卡驻留图像)。我当前正在使用IMG_LoadTexture()加载纹理。我的问题是,在这种情况下,我看不到如何设置SDL_TEXTUREACCESS

可以使用CreateTexture()在SDL2中创建纹理,然后使用LockTexture()访问该纹理中的像素。但要做到这一点,您需要将SDL_TEXTUREACCESS_STREAMING标志传递给CreateTexture调用

有一个相当标准的用于加载图像的助手库,称为SDL_image。我使用它将图像文件读入纹理(纹理是供临时观察者使用的图形卡驻留图像)。我当前正在使用IMG_LoadTexture()加载纹理。我的问题是,在这种情况下,我看不到如何设置SDL_TEXTUREACCESS_流标志。所以我无法获取SDL_图像加载纹理的像素数据

我想得到像素的原因是从像素中提取九个面片数据。(我可能最终拥有9种纹理)。因此,我只需要在开始的时候,这个信息一次,我只需要读取纹理数据,而不是写入它。如果可能的话,我还想使用现有的图像文件读取库


所以问题是:从图像文件中读取纹理信息并使用SDL2获取像素的最佳方法是什么

决定最好使用曲面,然后转换为纹理。这个代码有效。它只做了九个补丁的左上角以保持简单。(这也忽略了九个面片图像第一行和第一列中的九个面片大小信息的复杂性)

typedef无符号字符字节;
NinePatch::NinePatch(常量字符串fname,SDL_渲染器*渲染器){
//获取曲面和每个像素的位
SDL_Surface*Surface=IMG_Load(fname.c_str());
每像素整数字节=表面->格式->每像素字节数;
//只需查看4字节/像素的9个补丁,即可简化操作
if(字节/像素!=4){
日志信息(“加载”+fname+
“期望像素数据为4,但它有:”+
到字符串(每像素字节数);
出口(1);
}
//将曲面分割为九个面片的曲面偏移
无符号整数左、右、上、下;
//通过查看最上面一行的像素,找到我们需要的宽度
字节t*ptr=(字节t*)表面->像素;
uint32像素,最后一个像素=0;
对于(int i=0;iw;i++){
//我们知道它们是4字节的像素,否则我们就无法到达这里。
像素=*(uint32_t*)ptr;
//在像素数据的顶行中查找“边”
如果(像素>最后一个像素){
左=i;
}
else if(像素<最后一个像素){
右=i;
}
最后一个像素=像素;
//获得下一个像素
ptr+=每像素字节数;
}
//通过查看左边的像素列,找到我们需要的高度
ptr=(byte_t*)表面->像素;
最后一个像素=0;
对于(int i=0;ih;i++){
//我们知道它们是4字节的像素,否则我们就无法到达这里。
像素=*(uint32_t*)ptr;
//在像素数据的左列中查找“边”
如果(像素>最后一个像素){
top=i;
}
else if(像素<最后一个像素){
底部=i;
}
最后一个像素=像素;
//降低下一个像素
ptr+=字节/像素*表面->w;
}
//SDL将每个像素解释为32位数字,因此
//必须取决于机器的尾数(字节顺序)
Uint32 rmask、gmask、bmask、amask;
#如果SDL_字节顺序==SDL_BIG_ENDIAN
rmask=0xff000000;
gmask=0x00ff0000;
bmask=0x0000ff00;
amask=0x000000ff;
#否则
rmask=0x000000ff;
gmask=0x0000ff00;
bmask=0x00ff0000;
amask=0xff000000;
#恩迪夫
const uint32_t unused_标志=0;
const int pixel_size=32;//以位为单位
//我们用来打破九块补丁的划痕表面
//表面变成小纹理。
SDL_表面*s;
SDL_Rect src_Rect;
//创建一个曲面以保持左上角
s=SDL_CreateRGB曲面(未使用的_标志,左侧,顶部,
像素大小、rmask、gmask、bmask、amask);
//将九面片图像曲面的一部分复制到新曲面中
src_rect.x=0;
src_rect.y=0;
src_rect.w=左;
src_rect.h=顶部;
SDL_BlitSurface(曲面和src_rect,s,NULL);
//将新的角曲面转换为纹理
顶部\左\纹理=SDL \ U CreateTextureFromSurface(渲染器,s);
//清除划痕表面
SDL_自由曲面(s);
}
typedef unsigned char byte_t;

NinePatch::NinePatch(const string fname, SDL_Renderer * renderer) {

    // get the surface and the bits per pixel
    SDL_Surface * surface = IMG_Load(fname.c_str());
    int bytes_per_pixel = surface->format->BytesPerPixel;

    // keep things simple by only looking at 4 byte/pixel nine-patches
    if (bytes_per_pixel != 4) {
        log_msg("Loading " + fname + 
                " expecting pixel data to be 4 but it has: " + 
                to_string(bytes_per_pixel));
        exit(1);
    }

    // offsets into the surface that divide the surface into a nine-patch
    unsigned int left, right, top, bottom;

    // find the widths we need by looking at the top row of pixels
    byte_t * ptr = (byte_t*)surface->pixels;
    uint32_t pixel, last_pixel = 0;
    for (int i = 0; i < surface->w; i++) {

        // we know they're 4 byte pixels cause otherwise we don't get here.
        pixel = *(uint32_t*)ptr;

        // look for "edges" in the top row of pixel data
        if (pixel > last_pixel) {
            left = i;
        }
        else if (pixel < last_pixel) {
            right = i;            
        }
        last_pixel = pixel;

        // get the next pixel across
        ptr += bytes_per_pixel;
    }


    // find the heights we need by looking at the left column of pixels
    ptr = (byte_t*)surface->pixels;
    last_pixel = 0;
    for (int i = 0; i < surface->h; i++) {

        // we know they're 4 byte pixels cause otherwise we don't get here.
        pixel = *(uint32_t*)ptr;

        // look for "edges" in the left column of pixel data
        if (pixel > last_pixel) {
            top = i;
        }
        else if (pixel < last_pixel) {
            bottom = i;
        }
        last_pixel = pixel;

        // get the next pixel down
        ptr += bytes_per_pixel * surface->w;
    }

    // SDL interprets each pixel as a 32-bit number, so our masks 
    // must depend on the endianness (byte order) of the machine 
    Uint32 rmask, gmask, bmask, amask;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
    rmask = 0xff000000;
    gmask = 0x00ff0000;
    bmask = 0x0000ff00;
    amask = 0x000000ff;
#else
    rmask = 0x000000ff;
    gmask = 0x0000ff00;
    bmask = 0x00ff0000;
    amask = 0xff000000;
#endif

    const uint32_t unused_flags = 0;
    const int pixel_size = 32; // in bits

    // scratch surface we use for breaking the nine-patch 
    // surface into little textures.
    SDL_Surface * s;
    SDL_Rect src_rect;

    // create a surface to hold the top left corner
    s = SDL_CreateRGBSurface(unused_flags, left, top, 
                             pixel_size, rmask, gmask, bmask, amask);

    // copy part of the nine-patch image surface into the new surface
    src_rect.x = 0;
    src_rect.y = 0;
    src_rect.w = left;
    src_rect.h = top;
    SDL_BlitSurface(surface, &src_rect, s, NULL);

    // convert the new corner surface into a texture
    top_left_texture =  SDL_CreateTextureFromSurface(renderer, s);

    // free the scratch surface
    SDL_FreeSurface(s);
}