嵌入式 SDL进行图片的切割与移动

原创 2013年12月02日 14:55:11
测试Demo,但不要以为就可以随意为之,良好的代码风格和设计思想在哪都是需要注意的

下面来看看博主的工程结构:

工程下多了一个sheet.jpg,这就是今天要用于切割的图片

图片是400 * 400 pixel(像素)
接下来我们要做的工作就是,把这张图切割成4个圆,并且把背景变成透明

说明:博主在SDL_fun.h这个头文件中增加了一个类,用于管理全局唯一的屏幕接口我的考虑是,screen surface实际上只需要建立一个。并且,其他的surface实际上都是“依赖”于这个surface才能显示出来的。在SDL中,多次SDL_SetVideoMode()的效果实际上是保留了最后一次的surface作为了screen surface,所以,多次SDL_SetVideoMode()其实是没有实际意义的。

01  
07  
08 #ifndef SDL_FUN_H_
09 #define SDL_FUN_H_
10  
11 #include
12 #include
13  
14 class ScreenSurface{
15  
16 public:
17 ScreenSurface(SDL_Surface* screen);
18 ScreenSurface(int width, int height, int bpp = 32, Uint32 flags = SDL_SWSURFACE);
19 ~ScreenSurface(void);
20 bool flip(void) const;
21 SDL_Surface* acquire(void);
22  
23 private:
24 SDL_Surface* screen;
25 };
26  
27 void drawBitmap(ScreenSurface s, const char* fileName);
28 void readKeyboard(ScreenSurface s);
29 void getRadioInfo(ScreenSurface s);
30 void renderPictures(ScreenSurface s, const char* fgFile, const char* bgFile);
31 void drawClips(ScreenSurface s, const char* file, SDL_Rect* clip = NULL, int size = 0);
32  
33 #endif
大家看到了吧,其中的ScreenSurface的flip方法是将数据化的SDL_Surface Push到屏幕上,让用户看到,而acquire是获取当前的屏幕接口,其他的就是一些构造方法和构析方法。下面的方法都需要传一个ScreenSurface,这样是不是就统一管理了呢?全局就只需创建一个唯一的通向物理屏幕的接口~


头文件中的drawClips就是图片分割的方法,下面是它的实现:

01  
02 void drawClips(ScreenSurface s, const char* file, SDL_Rect* clip, int size) {
03  
04 SDL_Surface* dots = IMG_Load(file);
05 SDL_Surface* optimizedImage = NULL;
06  
07 if (s.acquire() == 0 || dots == 0 || clip == NULL) {
08 std::cerr << SDL_GetError() << " 227 \n";
09 return;
10 } else {
11 optimizedImage = SDL_DisplayFormat(dots);
12 SDL_FreeSurface(dots);
13 //这两句代码把图片背景置为透明
14 Uint32 colorkey = SDL_MapRGB(optimizedImage->format, 0, 0xFF, 0xFF);
15 SDL_SetColorKey(optimizedImage, SDL_SRCCOLORKEY, colorkey);
16 }
17  
18 //把整个背景填充为白色
19 SDL_FillRect(s.acquire(), &s.acquire()->clip_rect,
20 SDL_MapRGB(s.acquire()->format, 0xFF, 0xFF, 0xFF));
21  
22 bool over = false;
23 SDL_Event event;
24 SDL_Rect offset;
25 while (!over) {
26  
27 SDL_ClearError();
28 SDL_PollEvent(&event);
29 if (event.type == SDL_QUIT || event.key.keysym.sym == SDLK_ESCAPE) {
30 over = true;
31 }
32 //参数size代表图片切割的数量,也就是clip数组的数量
33 for (int x = 0; x < size; x++) {
34  
35 offset.x = clip[x].x + x*100;
36 offset.y = clip[x].y + x*100;
37  
38 if (SDL_BlitSurface(optimizedImage, &clip[x], s.acquire(), &offset)
39 != 0) {
40 std::cerr << SDL_GetError() << " 275 \n";
41 break;
42 }
43 }
44  
45 if (!s.flip()) {
46 std::cerr << SDL_GetError() << " 281\n";
47 break;
48 }
49 }
50  
51 SDL_FreeSurface(dots);
52 }

再来看看main的入口函数:

01 //===================================================================
02 // Name : SDL_demo.cpp
03 // Author : Christian
04 // Version :
05 // Copyright : Copyright (c) Christian 2012/9/28
06 // Description : Hello World in C++, Ansi-style
07 //===================================================================
08 #include "include/SDL_init.h"
09 #include "include/SDL_fun.h"
10  
11 using namespace std;
12 //这里定义了4个clip
13 void cutPic(ScreenSurface s){
14 SDL_Rect clip[4];
15 //Clip range for the top left
16 clip[0].x = 0;
17 clip[0].y = 0;
18 clip[0].w = 100;
19 clip[0].h = 100;
20  
21 //Clip range for the top right
22 clip[1].x = 100;
23 clip[1].y = 0;
24 clip[1].w = 100;
25 clip[1].h = 100;
26  
27 //Clip range for the bottom left
28 clip[2].x = 0;
29 clip[2].y = 100;
30 clip[2].w = 100;
31 clip[2].h = 100;
32  
33 //Clip range for the bottom right
34 clip[3].x = 100;
35 clip[3].y = 100;
36 clip[3].w = 100;
37 clip[3].h = 100;
38  
39 drawClips(s, "sheet.jpg", clip, 4);
40 }
41  
42 int main(int argc, char* args[]) {
43 //SDL_putenv("SDL_VIDEODRIVER=directx");
44 //putenv("SDL_VIDEODRIVER=directx");
45  
46 createSDL("Christian Test");
47 ScreenSurface s(600, 600);
48  
49 //drawBitmap(s, "3.jpg");
50 //readKeyboard();
51 //getRadioInfo();
52 //renderPictures(s, "3.jpg", "2.bmp");
53 cutPic(s);
54  
55  
56 atexit(destorySDL);
57  
58 return EXIT_SUCCESS;
59 }

下面是运行效果:

博主是按照官网文档去做的,为什么图片背景还是没有完全透明请高手解答一下。

好了,图片切割完成!下面讲讲如果对图片进行移动~第一章的时候咱们不是讲了SDL的按键的事件功能么,是时候结合一下了~

下面是改动后的drawClips函数:

01  
02 void drawClips(ScreenSurface s, const char* file, SDL_Rect* clip, int size) {
03  
04 SDL_Surface* dots = IMG_Load(file);
05 SDL_Surface* optimizedImage = NULL;
06  
07 if (s.acquire() == 0 || dots == 0 || clip == NULL) {
08 std::cerr << SDL_GetError() << " 227 \n";
09 return;
10 } else {
11 optimizedImage = SDL_DisplayFormat(dots);
12 SDL_FreeSurface(dots);
13  
14 Uint32 colorkey = SDL_MapRGB(optimizedImage->format, 0, 0xFF, 0xFF);
15 SDL_SetColorKey(optimizedImage, SDL_SRCCOLORKEY, colorkey);
16 }
17  
18 //把整个背景填充为白色
19 SDL_FillRect(s.acquire(), &s.acquire()->clip_rect,
20 SDL_MapRGB(s.acquire()->format, 0xFF, 0xFF, 0xFF));
21  
22 bool over = false;
23 SDL_Event event;
24 SDL_Rect offset;
25 Uint8* keys;
26 offset.x = 0;
27 offset.y = 0;
28  
29 while (!over) {
30 //从这里获取每个按键的即时状态,监听8个按键,w/s/a/d/up/down/left/right
31 keys = SDL_GetKeyState(0);
32 if (keys[SDLK_UP] || keys[SDLK_w]) {
33 offset.y -= 1;
34 }
35 if (keys[SDLK_DOWN] || keys[SDLK_s]) {
36 offset.y += 1;
37 }
38 if (keys[SDLK_LEFT] || keys[SDLK_a]) {
39 offset.x -= 1;
40 }
41 if (keys[SDLK_RIGHT] || keys[SDLK_d]) {
42 offset.x += 1;
43 }
44  
45 SDL_ClearError();
46 SDL_PollEvent(&event);
47 if (event.type == SDL_QUIT || event.key.keysym.sym == SDLK_ESCAPE) {
48 over = true;
49 }
50  
51 for (int x = 0; x < size; x++) {
52  
53 // offset.x = clip[x].x;
54 // offset.y = clip[x].y;
55  
56 if (SDL_BlitSurface(optimizedImage, &clip[x], s.acquire(), &offset)
57 != 0) {
58 std::cerr << SDL_GetError() << " 275 \n";
59 break;
60 }
61 }
62  
63 if (!s.flip()) {
64 std::cerr << SDL_GetError() << " 281\n";
65 break;
66 }
67 }
68  
69 SDL_FreeSurface(dots);
70 }

好了,就这么简单~只需在轮询线程内加上事件监听,判断后做出响应即可
运行结果图:

移植SDL到JZ2440显示BMP图片

写这类教程的目的是, 熟悉Linux基本操作和嵌入式开发流程, 希望对你有所帮助.   前面我们讲过系统起来后开机LOGO的制作, 韦老师第3期讲了如何显示jpeg图片, 那么怎么显示bm...
  • thisway_diy
  • thisway_diy
  • 2017年06月29日 11:07
  • 477

java 对图片进行切割,灰度化,切割操作

有时候项目中会对图片进行操作,像切图啦,二值化啦,灰度啦。。 在验证码识别的时候很有用 现在将java对图片操作的部分方法写下来  不管图片如何操作,关键是在new BufferIm...
  • joeyon
  • joeyon
  • 2014年12月26日 17:20
  • 959

SDL移植到ARM-linux下

 SDL移植到ARM-linux上   参考自:bluedrum笔《SDL及扩展库在ARM-Linux 完整移植》 我用的编译环境是ubuntu10.10                ...
  • u012075739
  • u012075739
  • 2014年05月02日 15:48
  • 645

SDL图片的旋转与缩放

#include #include "SDL_rotozoom.h" #include "SDL_image.h" #include "math.h" #include "string.h"...
  • douyuan888
  • douyuan888
  • 2013年07月01日 10:25
  • 1585

SDL 使用,播放一张图片实例

一、简介 SDL(Simple DirectMedia Layer)是一套开放源代码的跨平台多媒体开发库,使用C语言写成。SDL提供了数种控制图像、声音、输出入的函数,让开发者只要用相同或是相似的代...
  • zhangliang_571
  • zhangliang_571
  • 2014年05月14日 10:48
  • 2411

总结:SDL_第一课 在屏幕上显示一张图片

#include "SDL.h" int main( int argc, char* args[] ) { //The images SDL_Surface* hello = NULL...
  • u012325397
  • u012325397
  • 2014年05月16日 22:29
  • 1469

opencv切割并保存图片

使用opencv切割并保存图片,需要使用Rect类进行操作。 这里讨论如何加载图片,切割图片,保存图片,销毁窗口和waitKey()函数的用法。 #include #include usin...
  • LordofRobots
  • LordofRobots
  • 2017年05月16日 17:21
  • 1822

使用SDL编写一个拖动开关点亮灯泡的程序

对于SDL我也只是一个初学的菜鸟,接下来和大家分享一个我自己写的拖动开关点亮灯泡的一个C++程序。 如果你同样是一个SDL的初学者,那么推荐给你一个连接:http://adolfans.github....
  • qq_29883591
  • qq_29883591
  • 2016年10月04日 22:14
  • 1825

SDL学习笔记二(图片的加载和显示)

图像加载是游戏常用到的步骤,SDL提供了简单的方法来加载并显示图片 不过在这之前,得先创建一个窗口来显示,SDL提供下面这个简便的函数 SDL_Surface* SDL_SetVideoMode(...
  • fp_hzq
  • fp_hzq
  • 2013年04月28日 17:56
  • 1992

SDL2.0 扣色(png图片重叠,前景色透明)

如图,小人的背景是青色的(R:0,G:FF,B:FF),那么我们现在要将小人背景透明化,则现在的color key就是青色的。   Color Keying(抠色)" title="SDL...
  • sz76211822
  • sz76211822
  • 2017年06月22日 13:47
  • 354
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:嵌入式 SDL进行图片的切割与移动
举报原因:
原因补充:

(最多只允许输入30个字)