【问题标题】:Extracting Pixels From SDL2 Surface Created With SDL_TTF从使用 SDL_TTF 创建的 SDL2 表面提取像素
【发布时间】:2018-08-17 03:44:11
【问题描述】:

我正在开发一个使用http://www.fontspace.com/work-ins-studio/variane-script 创建 SDL_Surface 的程序。我将表面的背景设置为透明。然后我从表面提取像素,并将它们放置在 opengl 纹理的一部分中。

一切都很好,除了文本最终看起来像这样(文本应该是“测试”)

我的问题:我是否以某种方式搞砸了数学并自己做这件事,还是这只是 SDL_TTF 的行为?而且,如果只是 SDL_TTF 的行为,我该如何解决它以获取我可以使用的像素数据?

以下是相关代码:

int main(int argc, char* args[]) {
//other sdl and opengl overhead stuff here...
TTF_Init();
//shader setup here...
TTF_Font *font;
font = TTF_OpenFont("VarianeScript.ttf", 50);
SDL_Surface* surface;
SDL_Color color = { 255, 0, 0 };
surface = TTF_RenderText_Solid(font, "testing", color);
SDL_SetSurfaceAlphaMod(surface, 255);
int surfaceWidth = surface->w;
int surfaceHeight = surface->h;
Uint8 red, green, blue, alpha;
float* textImage = new float[(surfaceWidth * surfaceHeight) * 4];
int countText = 0;
SDL_LockSurface(surface);
Uint8* p = (Uint8*)surface->pixels;
for (int y = 0; y < surfaceHeight; ++y) {
    for (int x = 0; x < (surfaceWidth); ++x) {
        Uint8 pixel = p[(y * surface->w) + x];
        SDL_GetRGBA(pixel, surface->format, &red, &green, &blue, &alpha);
        textImage[countText] = ((float)red / 255.0f);
        ++countText;
        textImage[countText] = ((float)green / 255.0f);
        ++countText;
        textImage[countText] = ((float)blue / 255.0f);
        ++countText;
        textImage[countText] = ((float)alpha / 255.0f);
        ++countText;
    }
}
SDL_UnlockSurface(surface);
SDL_FreeSurface(surface);
GLuint texture;
float* image;
int width = 1000, height = 1000;
int textX = width - (int)(width / 1.5);
int textY = height - (int)(height / 1.5);
setupTexture(texture, shader, width, height, image, textImage, textX, textY, surfaceWidth, surfaceHeight);
//etc...

还有(重要的部分从我声明 startpos 变量的地方开始)

void setupTexture(GLuint &texture, Shader &shader, int &width, int &height, float* &image, float* text, int textX, int textY, int textW, int textH) {
glGenTextures(1, &texture);
image = new float[(width * height) * 3];
for (int a = 0; a < (width * height) * 3; ) {
    if (a < ((width * height) * 3) / 2) {
        image[a] = 0.5f;
        ++a;
        image[a] = 1.0f;
        ++a;
        image[a] = 0.3f;
        ++a;
    }
    else {
        image[a] = 0.0f;
        ++a;
        image[a] = 0.5f;
        ++a;
        image[a] = 0.7f;
        ++a;
    }
}
int startpos1, startpos2;
for(int y = 0; y < textH; ++y) {
    for(int x = 0; x < textW; ++x) {
        startpos1 = (((y + textY) * width) * 3) + ((x + textX) * 3);
        startpos2 = ((y * textW) *4) + (x * 4);
        if (text[startpos2 + 3] != 0.0) {
            image[startpos1] = text[startpos2];
            image[startpos1 + 1] = text[startpos2 + 1];
            image[startpos1 + 2] = text[startpos2 + 2];
        }
    }
}
glActiveTexture(GL_TEXTURE0);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_FLOAT, image);
glUniform1i(glGetUniformLocation(shader.shaderProgram, "texSampler"), 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}

【问题讨论】:

  • 因为你创建了一个紧凑的 RGB 纹理,你必须设置glPixelStore(GL_UNPACK_ALIGNMENT, 1)
  • 我将如何在我的代码中实现它?我对opengl很陌生,对不起
  • textXtextY 根据硬编码常量 1000 计算得出,并不代表 textImage 的实际音高。常量应该是什么意思?不应该是surfaceWidthsurfaceHeight 吗?
  • textX 和 textY 表示文本像素将覆盖图像像素的区域的原点(左上角)
  • 我看到的问题不在于我的代码本身。这是 sdl_ttf 将文本环绕到像素数组的前面以节省空间(我假设),我不知道如何使用它。或者我可能把数学搞砸了。我会尝试实现你的代码并报告

标签: c++ opengl sdl sdl-2 sdl-ttf


【解决方案1】:

您的问题在于您从表面提取像素的方式:

Uint8 pixel = p[(y * surface->w) + x];

您假设每个像素占用一个字节(可以通过检查 surface-&gt;format-&gt;BytesPerPixel 来验证),并且每行的长度为 surface-&gt;w*1 字节 - 但事实并非如此。相反,每一行都是surface-&gt;pitch 字节长,所以你的代码应该是

Uint8 pixel = p[y * surface->pitch + x];

(仍然假设它是 1 个字节长,但这不是重点)。

使用浮点数来表示像素数据是很奇怪的,因为它除了加载速度慢得多之外什么都没有。

【讨论】:

  • 我以为我在某处看到 opengl 将 8bit 0-255 值转换为浮点数?也许我弄错了。你会推荐只使用 8 位无符号整数吗?
  • 我也更改了您建议的行,现在程序崩溃而没有显示任何内容。是否需要任何进一步的更改才能使其正常工作?另外,我会检查每像素的字节数,谢谢,我希望有人能向我解释如何找到我想要的格式,很好。
  • 我添加了这行代码:std::cout format->BytesPerPixel
  • 我认为没有任何技术信息就无法诊断崩溃。在调试器中运行它以查看它崩溃的位置和原因。如果您无法弄清楚,请将该信息和当前代码编辑到问题中。
  • 我也试过 BitsPerPixel,它输出 8。我不知道为什么使用 pitch 会导致程序崩溃,如果 pitch 是每行的字节数。
猜你喜欢
  • 2014-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-04
  • 2017-07-07
  • 1970-01-01
相关资源
最近更新 更多