SDL2将像素数组制作成纹理
SDL2 make pixel array into texture
我试图渲染一张特殊的图像,它只是一堆没有格式的像素。它是一种 42x 42 像素的原始图像。这些图像是调色板,所以我也很好奇我应该如何处理这种情况。
如何在 SDL2 中将像素数组转换为纹理?
我最后应用调色板了吗?
更多详情:
目前我正在打开图像并添加一些透明(黑色字节)并将其存储到 char 数组中。我需要渲染这些像素。
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <SDL.h>
#include <SDL_image.h>
#include <stdio.h>
#include <windows.h>
#include <vector>
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
FILE* OpenCelFile(const char * filepath) {
FILE* ptr = fopen(filepath, "rb");
return ptr;
}
DWORD FrameCount[1] = { 0 };
DWORD DataStart[1] = { 0 };
DWORD dummy[1] = { 0 };
signed char CommandByte[1] = { 0 };
void SkipToData(FILE* pFile, DWORD* dataStart, int bytesRead)
{
int MoveForwardBytes = *dataStart - bytesRead;
fseek(pFile, MoveForwardBytes, SEEK_CUR);
}
// There is more to this , but it isn't 100% important.
void ReadCelHeader(FILE* pFile)
{
fread((void*)FrameCount, 4, 1, pFile);
fread((void*)DataStart, 4, 1, pFile);
SkipToData(pFile, DataStart, 8);
}
void ReadCommandByte(FILE* pFile)
{
fread((void*)CommandByte, 1, 1, pFile);
}
std::vector<char> backBuffer;
int CreateRawImageBuffer(FILE* pFile) {
ReadCommandByte(pFile);
int bytesRead = 0;
// handel transparent bytes;
if (*(BYTE*)CommandByte >= 0x80) {
// this is a negative byte
signed int skipBytes = *(BYTE*)CommandByte - 256;
// convert it to positive number.
skipBytes = abs(skipBytes);
for (skipBytes; skipBytes != NULL; skipBytes--) {
backBuffer.push_back(0x00);
bytesRead++;
}
}
// set real pixels
if (*(BYTE*)CommandByte < 0x80) {
signed int byteCount = *(BYTE*)CommandByte;
for (byteCount; byteCount != NULL; byteCount--) {
BYTE t_char[1] = {0x00};
fread((void*)t_char, 1, 1, pFile);
backBuffer.push_back(*t_char);
bytesRead++;
}
}
return bytesRead;
}
int main(int argc, char* args[]) {
SDL_Window* window = NULL;
SDL_Surface* screenSurface = NULL;
bool RunningMainGameLoop = true;
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
fprintf(stderr, "could not initialize sdl2: %s\n", SDL_GetError());
return 1;
}
window = SDL_CreateWindow("Renderunkimage", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
if (window == NULL) {
fprintf(stderr, "could not create window: %s\n", SDL_GetError());
return 1;
}
FILE* ptr = OpenCelFile("C:\Users\luzer\source\repos\unkimages\unkimage.cel");
ReadCelHeader(ptr);
int TotalFramePixels = 48 * 48;
int fc = *FrameCount;
int pixelsAdded = { 0 };
for (fc; fc != 0; fc--) {
for (TotalFramePixels; TotalFramePixels != NULL; TotalFramePixels = TotalFramePixels - pixelsAdded) {
pixelsAdded = CreateRawImageBuffer(ptr);
}
}
screenSurface = SDL_GetWindowSurface(window);
SDL_FillRect(screenSurface, NULL, SDL_MapRGB(screenSurface->format, 0x00, 0x00, 0x00));
SDL_UpdateWindowSurface(window);
while (RunningMainGameLoop)
{
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
RunningMainGameLoop = false;
break;
}
}
// handle renders...
}
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
您需要先使用 SDL_Surface 使用以下内容:
SDL_CreateRGBSurfaceFrom(data, IMAGE_WIDTH, IMAGE_HEIGHT, 8, IMAGE_WIDTH /*pitch*/, 0, 0, 0, 0);
我正在加载的图像实际上只是每种颜色的一个字节,然后我必须对它们应用调色板。有一种 RLE 编码或压缩,这就是为什么我必须加载它们,否则你只需加载它们并将它们传递到表面。
这里是所有感兴趣的人的完整代码。
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <SDL.h>
#include <SDL_image.h>
#include <stdio.h>
#include <windows.h>
#include <vector>
#include <fstream>
#include <iterator>
#include <algorithm>
#include <array>
#define SCREEN_WIDTH 200
#define SCREEN_HEIGHT 200
#define TICK_INTERVAL 45
static Uint32 next_time;
SDL_Color palData[256];
DWORD FrameCount[1] = { 0 };
DWORD DataStart[1] = { 0 };
DWORD dummy[1] = { 0 };
signed char CommandByte[1] = { 0 };
int TotalFramePixels = 48 * 48;
int IMAGE_WIDTH = 48;
int IMAGE_HEIGHT = 48;
struct Color {
uint8_t r;
uint8_t g;
uint8_t b;
};
struct celFrame {
byte ImageData[2304]; //fixed size of image. 48*48
};
FILE* OpenCelFile(const char * filepath) {
FILE* ptr = fopen(filepath, "rb");
return ptr;
}
void LoadPalette(const char* pszFileName)
{
FILE* PalFile = fopen(pszFileName, "rb");
for (int idx = 0; idx < 255; idx++) {
fread(&palData[idx].r, 1, 1, PalFile);
fread(&palData[idx].g, 1, 1, PalFile);
fread(&palData[idx].b, 1, 1, PalFile);
}
}
void SkipToData(FILE* pFile, DWORD* dataStart, int bytesRead)
{
int MoveForwardBytes = *dataStart - bytesRead;
fseek(pFile, MoveForwardBytes, SEEK_CUR);
}
// There is more to this , but it isn't 100% important.
void ReadCelHeader(FILE* pFile)
{
fread((void*)FrameCount, 4, 1, pFile);
fread((void*)DataStart, 4, 1, pFile);
SkipToData(pFile, DataStart, 8);
}
void ReadCommandByte(FILE* pFile)
{
fread((void*)CommandByte, 1, 1, pFile);
}
int CreateRawImageBuffer(FILE* pFile, struct celFrame* s_celFrame, int bytesRead) {
ReadCommandByte(pFile);
// handel transparent bytes;
if (*(BYTE*)CommandByte >= 0x80) {
// this is a negative byte
signed int skipBytes = *(BYTE*)CommandByte - 256;
// convert it to positive number.
skipBytes = abs(skipBytes);
for (skipBytes; skipBytes != NULL; skipBytes--) {
s_celFrame->ImageData[bytesRead] = 0xff;
bytesRead++;
}
}
// set real pixels
if (*(BYTE*)CommandByte < 0x80) {
signed int byteCount = *(BYTE*)CommandByte;
for (byteCount; byteCount != NULL; byteCount--) {
BYTE t_char[1] = {0xff};
fread((void*)t_char, 1, 1, pFile);
s_celFrame->ImageData[bytesRead] = *t_char;
bytesRead++;
}
}
if (bytesRead >= TotalFramePixels) {
return bytesRead;
}
CreateRawImageBuffer(pFile, s_celFrame, bytesRead);
}
Uint32 time_left(void)
{
Uint32 now;
now = SDL_GetTicks();
if (next_time <= now)
return 0;
else
return next_time - now;
}
int main(int argc, char* args[]) {
SDL_Window* window = NULL;
SDL_Surface* screenSurface = NULL;
SDL_Renderer* renderer = NULL;
SDL_Surface* PentagramSurface[8] = {0};
SDL_Texture* pentagramTexture[8] = { 0 };
int frameCount = 0;
bool RunningMainGameLoop = true;
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
fprintf(stderr, "could not initialize sdl2: %s\n", SDL_GetError());
return 1;
}
window = SDL_CreateWindow("RenderCEL", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
if (window == nullptr) {
fprintf(stderr, "could not create window: %s\n", SDL_GetError());
return 1;
}
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if (renderer == nullptr) {
std::cout << "SDL_CreateRenderer Error: " << SDL_GetError() << std::endl;
return 1;
}
FILE* pfile = OpenCelFile("C:\Users\luzer\source\repos\RenderCEL\PentSpin.cel");
LoadPalette("C:\Users\luzer\source\luzer\RenderCEL\cut2.pal");
ReadCelHeader(pfile);
int fc = *FrameCount;
int pixelsAdded = { 0 };
celFrame s_celFrame[8] = {0};
// Create individual frames of each image
// by storing them in structs
for (int fidx = 0; fidx != fc; fidx++) {
int bytes_read = CreateRawImageBuffer(pfile, &s_celFrame[fidx], 0);
PentagramSurface[fidx] = SDL_CreateRGBSurfaceFrom(&s_celFrame[fidx], IMAGE_WIDTH, IMAGE_HEIGHT, 8, IMAGE_WIDTH /*pitch*/, 0, 0, 0, 0);
SDL_SetPaletteColors(PentagramSurface[fidx]->format->palette, palData, 0, 256);
pentagramTexture[fidx] = SDL_CreateTextureFromSurface(renderer, PentagramSurface[fidx]);
SDL_FreeSurface(PentagramSurface[fidx]);
}
screenSurface = SDL_GetWindowSurface(window);
SDL_FillRect(screenSurface, NULL, SDL_MapRGB(screenSurface->format, 0x00, 0x00, 0x00));
while (RunningMainGameLoop)
{
next_time = SDL_GetTicks() + TICK_INTERVAL;
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
RunningMainGameLoop = false;
break;
}
}
// handle renders...
SDL_Rect drect = {0,0,48,48};
SDL_RenderClear(renderer);
SDL_RenderCopyEx(renderer, pentagramTexture[frameCount], NULL, NULL, 0, NULL, SDL_FLIP_VERTICAL);
SDL_RenderPresent(renderer);
SDL_Delay(time_left());
next_time += TICK_INTERVAL;
frameCount++;
if (frameCount == 8) { frameCount = 0; }
}
for (int idx = 0; idx < 8; idx++) {
SDL_DestroyTexture(pentagramTexture[idx]);
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
我试图渲染一张特殊的图像,它只是一堆没有格式的像素。它是一种 42x 42 像素的原始图像。这些图像是调色板,所以我也很好奇我应该如何处理这种情况。
如何在 SDL2 中将像素数组转换为纹理?
我最后应用调色板了吗?
更多详情: 目前我正在打开图像并添加一些透明(黑色字节)并将其存储到 char 数组中。我需要渲染这些像素。
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <SDL.h>
#include <SDL_image.h>
#include <stdio.h>
#include <windows.h>
#include <vector>
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
FILE* OpenCelFile(const char * filepath) {
FILE* ptr = fopen(filepath, "rb");
return ptr;
}
DWORD FrameCount[1] = { 0 };
DWORD DataStart[1] = { 0 };
DWORD dummy[1] = { 0 };
signed char CommandByte[1] = { 0 };
void SkipToData(FILE* pFile, DWORD* dataStart, int bytesRead)
{
int MoveForwardBytes = *dataStart - bytesRead;
fseek(pFile, MoveForwardBytes, SEEK_CUR);
}
// There is more to this , but it isn't 100% important.
void ReadCelHeader(FILE* pFile)
{
fread((void*)FrameCount, 4, 1, pFile);
fread((void*)DataStart, 4, 1, pFile);
SkipToData(pFile, DataStart, 8);
}
void ReadCommandByte(FILE* pFile)
{
fread((void*)CommandByte, 1, 1, pFile);
}
std::vector<char> backBuffer;
int CreateRawImageBuffer(FILE* pFile) {
ReadCommandByte(pFile);
int bytesRead = 0;
// handel transparent bytes;
if (*(BYTE*)CommandByte >= 0x80) {
// this is a negative byte
signed int skipBytes = *(BYTE*)CommandByte - 256;
// convert it to positive number.
skipBytes = abs(skipBytes);
for (skipBytes; skipBytes != NULL; skipBytes--) {
backBuffer.push_back(0x00);
bytesRead++;
}
}
// set real pixels
if (*(BYTE*)CommandByte < 0x80) {
signed int byteCount = *(BYTE*)CommandByte;
for (byteCount; byteCount != NULL; byteCount--) {
BYTE t_char[1] = {0x00};
fread((void*)t_char, 1, 1, pFile);
backBuffer.push_back(*t_char);
bytesRead++;
}
}
return bytesRead;
}
int main(int argc, char* args[]) {
SDL_Window* window = NULL;
SDL_Surface* screenSurface = NULL;
bool RunningMainGameLoop = true;
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
fprintf(stderr, "could not initialize sdl2: %s\n", SDL_GetError());
return 1;
}
window = SDL_CreateWindow("Renderunkimage", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
if (window == NULL) {
fprintf(stderr, "could not create window: %s\n", SDL_GetError());
return 1;
}
FILE* ptr = OpenCelFile("C:\Users\luzer\source\repos\unkimages\unkimage.cel");
ReadCelHeader(ptr);
int TotalFramePixels = 48 * 48;
int fc = *FrameCount;
int pixelsAdded = { 0 };
for (fc; fc != 0; fc--) {
for (TotalFramePixels; TotalFramePixels != NULL; TotalFramePixels = TotalFramePixels - pixelsAdded) {
pixelsAdded = CreateRawImageBuffer(ptr);
}
}
screenSurface = SDL_GetWindowSurface(window);
SDL_FillRect(screenSurface, NULL, SDL_MapRGB(screenSurface->format, 0x00, 0x00, 0x00));
SDL_UpdateWindowSurface(window);
while (RunningMainGameLoop)
{
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
RunningMainGameLoop = false;
break;
}
}
// handle renders...
}
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
您需要先使用 SDL_Surface 使用以下内容:
SDL_CreateRGBSurfaceFrom(data, IMAGE_WIDTH, IMAGE_HEIGHT, 8, IMAGE_WIDTH /*pitch*/, 0, 0, 0, 0);
我正在加载的图像实际上只是每种颜色的一个字节,然后我必须对它们应用调色板。有一种 RLE 编码或压缩,这就是为什么我必须加载它们,否则你只需加载它们并将它们传递到表面。
这里是所有感兴趣的人的完整代码。
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <SDL.h>
#include <SDL_image.h>
#include <stdio.h>
#include <windows.h>
#include <vector>
#include <fstream>
#include <iterator>
#include <algorithm>
#include <array>
#define SCREEN_WIDTH 200
#define SCREEN_HEIGHT 200
#define TICK_INTERVAL 45
static Uint32 next_time;
SDL_Color palData[256];
DWORD FrameCount[1] = { 0 };
DWORD DataStart[1] = { 0 };
DWORD dummy[1] = { 0 };
signed char CommandByte[1] = { 0 };
int TotalFramePixels = 48 * 48;
int IMAGE_WIDTH = 48;
int IMAGE_HEIGHT = 48;
struct Color {
uint8_t r;
uint8_t g;
uint8_t b;
};
struct celFrame {
byte ImageData[2304]; //fixed size of image. 48*48
};
FILE* OpenCelFile(const char * filepath) {
FILE* ptr = fopen(filepath, "rb");
return ptr;
}
void LoadPalette(const char* pszFileName)
{
FILE* PalFile = fopen(pszFileName, "rb");
for (int idx = 0; idx < 255; idx++) {
fread(&palData[idx].r, 1, 1, PalFile);
fread(&palData[idx].g, 1, 1, PalFile);
fread(&palData[idx].b, 1, 1, PalFile);
}
}
void SkipToData(FILE* pFile, DWORD* dataStart, int bytesRead)
{
int MoveForwardBytes = *dataStart - bytesRead;
fseek(pFile, MoveForwardBytes, SEEK_CUR);
}
// There is more to this , but it isn't 100% important.
void ReadCelHeader(FILE* pFile)
{
fread((void*)FrameCount, 4, 1, pFile);
fread((void*)DataStart, 4, 1, pFile);
SkipToData(pFile, DataStart, 8);
}
void ReadCommandByte(FILE* pFile)
{
fread((void*)CommandByte, 1, 1, pFile);
}
int CreateRawImageBuffer(FILE* pFile, struct celFrame* s_celFrame, int bytesRead) {
ReadCommandByte(pFile);
// handel transparent bytes;
if (*(BYTE*)CommandByte >= 0x80) {
// this is a negative byte
signed int skipBytes = *(BYTE*)CommandByte - 256;
// convert it to positive number.
skipBytes = abs(skipBytes);
for (skipBytes; skipBytes != NULL; skipBytes--) {
s_celFrame->ImageData[bytesRead] = 0xff;
bytesRead++;
}
}
// set real pixels
if (*(BYTE*)CommandByte < 0x80) {
signed int byteCount = *(BYTE*)CommandByte;
for (byteCount; byteCount != NULL; byteCount--) {
BYTE t_char[1] = {0xff};
fread((void*)t_char, 1, 1, pFile);
s_celFrame->ImageData[bytesRead] = *t_char;
bytesRead++;
}
}
if (bytesRead >= TotalFramePixels) {
return bytesRead;
}
CreateRawImageBuffer(pFile, s_celFrame, bytesRead);
}
Uint32 time_left(void)
{
Uint32 now;
now = SDL_GetTicks();
if (next_time <= now)
return 0;
else
return next_time - now;
}
int main(int argc, char* args[]) {
SDL_Window* window = NULL;
SDL_Surface* screenSurface = NULL;
SDL_Renderer* renderer = NULL;
SDL_Surface* PentagramSurface[8] = {0};
SDL_Texture* pentagramTexture[8] = { 0 };
int frameCount = 0;
bool RunningMainGameLoop = true;
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
fprintf(stderr, "could not initialize sdl2: %s\n", SDL_GetError());
return 1;
}
window = SDL_CreateWindow("RenderCEL", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
if (window == nullptr) {
fprintf(stderr, "could not create window: %s\n", SDL_GetError());
return 1;
}
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if (renderer == nullptr) {
std::cout << "SDL_CreateRenderer Error: " << SDL_GetError() << std::endl;
return 1;
}
FILE* pfile = OpenCelFile("C:\Users\luzer\source\repos\RenderCEL\PentSpin.cel");
LoadPalette("C:\Users\luzer\source\luzer\RenderCEL\cut2.pal");
ReadCelHeader(pfile);
int fc = *FrameCount;
int pixelsAdded = { 0 };
celFrame s_celFrame[8] = {0};
// Create individual frames of each image
// by storing them in structs
for (int fidx = 0; fidx != fc; fidx++) {
int bytes_read = CreateRawImageBuffer(pfile, &s_celFrame[fidx], 0);
PentagramSurface[fidx] = SDL_CreateRGBSurfaceFrom(&s_celFrame[fidx], IMAGE_WIDTH, IMAGE_HEIGHT, 8, IMAGE_WIDTH /*pitch*/, 0, 0, 0, 0);
SDL_SetPaletteColors(PentagramSurface[fidx]->format->palette, palData, 0, 256);
pentagramTexture[fidx] = SDL_CreateTextureFromSurface(renderer, PentagramSurface[fidx]);
SDL_FreeSurface(PentagramSurface[fidx]);
}
screenSurface = SDL_GetWindowSurface(window);
SDL_FillRect(screenSurface, NULL, SDL_MapRGB(screenSurface->format, 0x00, 0x00, 0x00));
while (RunningMainGameLoop)
{
next_time = SDL_GetTicks() + TICK_INTERVAL;
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
RunningMainGameLoop = false;
break;
}
}
// handle renders...
SDL_Rect drect = {0,0,48,48};
SDL_RenderClear(renderer);
SDL_RenderCopyEx(renderer, pentagramTexture[frameCount], NULL, NULL, 0, NULL, SDL_FLIP_VERTICAL);
SDL_RenderPresent(renderer);
SDL_Delay(time_left());
next_time += TICK_INTERVAL;
frameCount++;
if (frameCount == 8) { frameCount = 0; }
}
for (int idx = 0; idx < 8; idx++) {
SDL_DestroyTexture(pentagramTexture[idx]);
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}