SDL2解析并显示24位bmp

记录一下,备忘

1.SDL2 画点参考

http://blog.csdn.net/korekara88730/article/details/70880061

2.24位bmp图片格式参考

http://wojiaolongyinong.iteye.com/blog/1896092

选择 24位bmp 的原因是 这种图片格式最简单

资源:

第一个图用于测试,第二个图片是自己用 画图板调试时用的,只有4x2大小,方便观察格式内容,开发过程中便于调试




开发过程中遇到的问题:

1.bmp 文件数据的组织排列形式(小端)

2.文件读取时的逻辑错误。最终用一个自己手绘的 4x2的小图,参照 hex 16进制编辑器 (sublime ,notepad++ 都有插件可以用,vitual studio 可以监视内存),最后解决读取时错误的内存偏移


代码:

main.cpp mp3.h mp3.cpp Application.h Application.cpp


mp3.h mp3.cpp

定义了 24位bmp 的 类,并实现了一个 读取bmp 文件的函数

Applicatoin.h Application.cpp  使用 SDL2库, 逐点绘制 24位bmp 图像


1.main.cpp

#include 

#include "Application.h"
#include "mp3.h"


miaomp3::The24BitBmp bitmap;

int main()
{
	//miaomp3::testmp3("res/login.mp3");	
	miaomp3::testmp3("res/laoshi.bmp",bitmap);
	//miaomp3::testmp3("res/linshiyin.bmp",bitmap);
	//miaomp3::testmp3("res/ceshi.bmp", bitmap);

	Application app;
	app.initialize(bitmap.width, bitmap.height);
	//app.initialize(95,95);
	app.mainLoop();
	return 0;
}
mp3.h

#ifndef __MP3_H__
#define __MP3_H__

#include 
namespace miaomp3
{
	/*
		addr 地址
		bytes 多少字节 (每个字节是8位)
	*/
	int getDecimal(char* addr, int bytes);

	class The24BitBmp
	{
	public:
		~The24BitBmp()
		{
			delete[] data;
			data = nullptr;
		}

		long fileSize;
		long dataOffset;

		int width;
		int height;

		char* data;

		int fillZeroPerLine;
		int sizePerLine;
		
		unsigned char getRAt(int x, int y);
		unsigned char getGAt(int x, int y);
		unsigned char getBAt(int x, int y);
		char* getAddrAt(int x, int y);
	};


	void testmp3(std::string filePath, The24BitBmp& bitmap);

}

#endif //__MP3_H__

mp3.cpp

#include "mp3.h"
#include 

namespace miaomp3
{
	unsigned char The24BitBmp::getRAt(int x, int y)
	{
		char* addr = getAddrAt(x, y);
		char col = addr[2];
		return col;
	}

	unsigned char The24BitBmp::getGAt(int x, int y)
	{
		char* addr = getAddrAt(x, y);
		char col = addr[1];
		return col;
	}

	unsigned char The24BitBmp::getBAt(int x, int y)
	{
		char* addr = getAddrAt(x, y);
		char col = addr[0];
		return col;
	}

	char* The24BitBmp::getAddrAt(int x, int y)
	{
		long offset = sizePerLine * y + x * 3;
		return this->data + offset;
	}


	long fileSize(FILE* fp)
	{
		fseek(fp, 0L, SEEK_END);
		long pos = ftell(fp);
		fseek(fp,0L,SEEK_SET);
		return pos;
	}

	/*
		addr 地址 
		bytes 多少字节 (每个字节是8位)
	*/
	int getDecimal(char* addr,int bytes)
	{
		int ret = 0;
		assert(bytes%2 == 0);
		for (int index = 0; index < bytes;index++)
		{
			int base = addr[index];
			int pownum = index * 2;
			int inc = base * pow(16, pownum);
			//printf("base:%d,pownum:%d,inc:%d\n",base,pownum,inc);
			ret += inc;
		}
		return ret;
	}


	void testmp3(std::string file,The24BitBmp& bitmap)
	{
		FILE*	fp = fopen(file.c_str(), "rb");
		if (fp == nullptr) return;

		long size = fileSize(fp);

		char* fd = new char[size];


		for (long index = 0; index < size;index++)
		{
			fd[index] = 0;
		}
	
		fread(fd, size,1, fp);
		fclose(fp);

		bitmap.dataOffset = getDecimal(fd + 10, 4);
		bitmap.fileSize = getDecimal(fd + 2, 4);
		bitmap.width = getDecimal(fd + 18, 4);
		bitmap.height = getDecimal(fd + 22, 4);
		long dataSize = bitmap.fileSize - bitmap.dataOffset;
		bitmap.data = new char[dataSize]();
		memcpy(bitmap.data, fd + bitmap.dataOffset, dataSize);


		int shouldBytesPerLine = bitmap.width * 3;
		bitmap.fillZeroPerLine = 0;
		if (shouldBytesPerLine %4 != 0)
		{
			printf("123");
		}

		bitmap.sizePerLine = shouldBytesPerLine + bitmap.fillZeroPerLine;
		delete[] fd;
	}
}

Application.h

#ifndef __APPLICATION_H__
#define __APPLICATION_H__

#include "SDL.h"
#include 

class Application
{
public:
	Application();
	virtual ~Application();

public:
	bool initialize(int screenWidth,int screenHeight);
	void mainLoop();
	void cleanup();

		
private:
	SDL_Window*		_pWindow;
	SDL_Surface*	_pScreenSurface;
	SDL_Renderer*	_pRenderer;

	int _screenWidth, _screenHeight;

private:
	void startGame();
	void showMainMenu();
	void restartGame();
};

#endif //__APPLICATION_H__


Application.cpp

#include "Application.h"
#include 
#include 
#include "mp3.h"


const int SCALE_FACTOR = 1;
//const int SCALE_FACTOR = 200;

Application::Application()
: _pWindow(nullptr)
, _pScreenSurface(nullptr)
, _pRenderer(nullptr)
, _screenWidth(100)
, _screenHeight(100)
{
	
}

Application::~Application()
{
	cleanup();
}

bool Application::initialize(int screenWidth, int screenHeight)
{
	if (SDL_Init(SDL_INIT_VIDEO) < 0)
	{
		printf("SDL can not initialized!SDL Error:%s\n", SDL_GetError());
		return false;
	}

	_screenWidth = screenWidth * SCALE_FACTOR;
	_screenHeight = screenHeight * SCALE_FACTOR;

	_pWindow = SDL_CreateWindow("msdl1", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, _screenWidth, _screenHeight, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
	//_pWindow = SDL_CreateWindow("msdl1", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, _screenWidth, _screenHeight, SDL_WINDOW_SHOWN | SDL_WINDOW_FULLSCREEN);
	if (_pWindow == nullptr)
	{
		printf("SDL can't create window!SDL Error:%s\n", SDL_GetError());
		return false;
	}

	int w, h;
	SDL_GetWindowSize(_pWindow, &w, &h);
	printf("Viewport Size: %d,%d\n",w,h);


	_pScreenSurface = SDL_GetWindowSurface(_pWindow);
	_pRenderer = SDL_CreateRenderer(_pWindow, -1, SDL_RENDERER_ACCELERATED);
	if (_pRenderer == nullptr)
	{
		return false;
	}
	SDL_FillRect(_pScreenSurface, nullptr, SDL_MapRGBA(_pScreenSurface->format, 0, 0, 0, 0));
	return true;
}

void Application::cleanup()
{
	SDL_DestroyRenderer(_pRenderer);
	SDL_DestroyWindow(_pWindow);
	SDL_Quit();
}


void Application::mainLoop()
{
	bool quit = false;
	SDL_Event evt;
	while (!quit)
	{
		while (SDL_PollEvent(&evt) != 0)
		{
			if (evt.type == SDL_QUIT){
				quit = true;
			}
		}
		
		{
			SDL_SetRenderDrawColor(_pRenderer, (Uint8)255, (Uint8)255, (Uint8)255, 0xff);
			SDL_RenderClear(_pRenderer);

			SDL_SetRenderDrawColor(_pRenderer, 0x00, 0x00, 0x00, 0xff);
			SDL_Rect fillRect = { 0, 0, _screenWidth, _screenHeight };
			SDL_RenderFillRect(_pRenderer, &fillRect);
		}

		for (int row = 0; row < _screenHeight; row++)
		{
			for (int col = 0; col < _screenWidth; col++)
			{

				/*
				int r = rand() / 100 % 256;
				int g = rand() / 100 % 256;
				int b = rand() / 100 % 256;
				*/

				extern miaomp3::The24BitBmp bitmap;
				int x = col/SCALE_FACTOR;
				int y = row/SCALE_FACTOR;
				y = bitmap.height - y - 1;

				Uint8 r, g, b;
				r = (Uint8)bitmap.getRAt(x, y);
				g = (Uint8)bitmap.getGAt(x,y);
				b = (Uint8)bitmap.getBAt(x,y);

				//printf("(%d,%d):[%d,%d,%d]\n",x,y,r,g,b);

				SDL_SetRenderDrawColor(_pRenderer, r, g, b, 0xff);
				SDL_RenderDrawPoint(_pRenderer, col, row);
			}
		}

		SDL_RenderPresent(_pRenderer);
	}
}


void Application::startGame()
{

}

void Application::showMainMenu()
{

}

void Application::restartGame()
{

}


结果:

SDL2解析并显示24位bmp_第1张图片



你可能感兴趣的:(折腾)