fig 1. 棄捐勿復道, 努力加餐飯。
這是我在 2002 寫的程式, 對透明色處理有興趣, 想自己寫出來, 找了很久, 忘記在哪本書看到這個演算法, 透過 linux/sgvalib 實做出來, 寫出來時還蠻開心的, 那時候用的版本控制軟體是 rcs。
對於電腦繪圖方式有興趣, 研究了 vga 模式和圖形顯示的原理, 如果用 qt 之類的, 很容易就可以完成秀出一張圖片的功能, 甚至還可以作到縮放, 但我想多知道一些, 就研究了這些技術, 大部分是從 dos 時代的繪圖相關書籍學習。
2002 沒有 chatgpt, 光是使用 jpeg lib 就難倒我, 啃著英文文件, 也不知道有沒看懂, 硬是讓我成功解出 jpeg 內容, 現在有 chatgpt, 應該秒會用吧!
在 20250804 想到 pc9801 遊戲 16 色時突然想到這個, 把這程式以 framebuffer 重新改寫, 沒辦法, svgalib 可能沒辦法在現今的平台執行, 呈現的效果看起來還蠻像一回事。
重新檢視演算法, 並沒有和背景色做運算, 我傻眼, 這好像不是透明演算法。問了
chatgpt 這個演算法 , 還真的不是, chatgpt 說這是漸層演算法, 整整搞錯 23 年。
framebuffer 繪圖則是問 chatgpt, 節省不少時間。
由於在螢幕上顯示圖形非常複雜, 需要理解 vga 顯示模式和影像格式, 我挑了最簡單的方式做, 在 640x480 24bit color 上顯示 24bit jpeg 圖檔, 可以避開 Quantization + Dithering 的問題, 現在有 chatgpt, 比較容易找到這 2 個演算法, 23 年科技進步的太大了。
在 2025 年, 這些技術也不需要, 2025 年應該不會有 256 色的顯示模式了。
VIDEO
透明色公式是:
final = src_color * alpha + background_color * (1 - alpha);
重新挑戰透明色, 麻煩的是要怎麼取得背景圖, 就先不處理這個, 直接拿2張圖做透明計算。
list 1. fb-jpeg.cpp
1 /*
2 *
3 * $Author: descent $
4 * $Date: 2002/06/20 02:55:23 $
5 * $Id: jpeg.cpp,v 1.2 2002/06/20 02:55:23 descent Exp descent $
6 * $Revision: 1.2 $
7 * 程式功能:用 jpeg library 來讀取 jpeg 圖檔,改用 framebuffer 來秀圖
8 * 並加入XX效果。
9 */
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <fcntl.h>
14 #include <linux/fb.h>
15 #include <sys/mman.h>
16 #include <sys/ioctl.h>
17 #include <unistd.h>
18 #include <string.h>
19 #include <stdint.h>
20
21 #include <vector>
22 #include <iostream>
23 #include <string>
24
25 #include <jpeglib.h>
26 #include <jerror.h>
27
28 using namespace std;
29
30 uint8_t *fbp;
31 struct fb_var_screeninfo vinfo;
32 struct fb_fix_screeninfo finfo;
33
34 struct Color
35 {
36 Color (unsigned char r, unsigned char g, unsigned char b):r_ (r), g_ (g),
37 b_ (b)
38 {
39 }
40 unsigned char r () const
41 {
42 return r_;
43 }
44 unsigned char g () const
45 {
46 return g_;
47 }
48 unsigned char b () const
49 {
50 return b_;
51 }
52 private:
53 unsigned char r_, g_, b_;
54 };
55
56 class Bitmap
57 {
58 public:
59 Bitmap (int width, int height):width_ (width), height_ (height)
60 {
61 }
62 void set_color (const std::vector < Color > &color)
63 {
64 color_ = color;
65 }
66 const std::vector < Color > &color_pixel () const
67 {
68 return color_;
69 }
70 int w () const
71 {
72 return width_;
73 }
74 int h () const
75 {
76 return height_;
77 }
78 private:
79 int width_, height_;
80 std::vector < Color > color_;
81 };
82
83 int r = 127;
84 int g = 78;
85 int b = 50;
86 int color_value;
87
88 void show(const Bitmap & bitmap, int x, int y, int level = 256)
89 {
90 //bitmap.color_pixel();
91 std::vector < Color >::const_iterator it = bitmap.color_pixel ().begin ();
92 //gl_getpalettecolor(color_value,&r,&g,&b);
93
94 for (int i = 0; i < bitmap.h (); ++i)
95 {
96 usleep(1000);
97 for (int j = 0; j < bitmap.w (); ++j)
98 {
99 //gl_setpixelrgb(x+j,y+i,(*it).r()*level/256,(*it).g()*level/256,(*it).b()*level/256);
100 int pix_r = (*it).r ();
101 int pix_g = (*it).g ();
102 int pix_b = (*it).b ();
103 //gl_setpixelrgb(x+j,y+i,r +(pix_r - r)*level/256, g +(pix_g - g)*level/256, b + (pix_b - b)*level/256);
104 //gl_setpixelrgb(x+j,y+i,pix_r*level+r*(1-level),pix_g*level+g*(1-level),pix_b*level+b*(level));
105 long location = (y+i)*finfo.line_length + (x+j) * 4; // 4 bytes per pixel
106 uint32_t *pixel = (uint32_t *)(fbp + location);
107 //printf("i: %d, j: %d, pixel: %p, fbp: %p\n", i, j, pixel, fbp);
108 #if 1
109 if (i <= 120)
110 {
111 //gl_setpixelrgb (x + j, y + i, (*it).r (), (*it).g (), (*it).b ());
112 // 32-bit ARGB,alpha=0xFF (不透明),紅色R=0xFF, G=0x00, B=0x00
113 // 寫法是 0xAARRGGBB
114 unsigned int val = 0xff000000;
115 val |= ((*it).r() << 16);
116 val |= ((*it).g() << 8);
117 val |= (*it).b();
118 *pixel = val;
119 //*pixel = 0xFFFF0000;
120 }
121 else
122 {
123 unsigned int val = 0xff000000;
124 val |= (((*it).r () + (r - (*it).r ()) * level / 256) << 16);
125 val |= (((*it).g () + (g - (*it).g ()) * level / 256) << 8);
126 val |= ((*it).b () + (b - (*it).b ()) * level / 256);
127 *pixel = val;
128 //*pixel = 0xFFFF0000;
129 #if 0
130 gl_setpixelrgb (x + j, y + i,
131 (*it).r () + (r - (*it).r ()) * level / 256,
132 (*it).g () + (g - (*it).g ()) * level / 256,
133 (*it).b () + (b - (*it).b ()) * level / 256);
134 #endif
135 }
136 #endif
137 ++it;
138 }
139 }
140 //for ( ; it !=bitmap.color_pixel().end() ; ++it)
141
142 }
143
144 void get_hex (char c, char hex[])
145 {
146 char ascii[] = "0123456789abcdef";
147 int low = (c & 0x0f);
148 int high = ((c >> 4) & 0x0f);
149 hex[0] = ascii[high];
150 hex[1] = ascii[low];
151 }
152
153 int main(int argc, char *argv[])
154 {
155 struct jpeg_decompress_struct cinfo;
156 struct jpeg_error_mgr jerr;
157
158 cinfo.err = jpeg_std_error (&jerr);
159 jpeg_create_decompress (&cinfo);
160
161 if (argc < 2)
162 {
163 cout << "Enter a file name" << endl;
164 return -1;
165 }
166
167 string filename = argv[1];
168 FILE *infile;
169 if ((infile = fopen (filename.c_str (), "rb")) == NULL)
170 {
171 fprintf (stderr, "cann't open file");
172 return -1;
173 }
174 //int level=255;
175 //if (argc>=3)
176 //level=atoi(argv[2]);
177 jpeg_stdio_src (&cinfo, infile);
178 jpeg_read_header (&cinfo, true);
179 // set parameters fro decompress
180 //cinfo.scale_num=1;
181 //cinfo.scale_denom=2;
182 //cinfo.output_width=640;
183 //cinfo.output_height=480;
184 //cinfo.image_height=480;
185 jpeg_start_decompress (&cinfo);
186
187 JSAMPARRAY buffer;
188 int row_stride = cinfo.output_width * cinfo.output_components;
189 int jpeg_width = cinfo.output_width;
190 buffer =
191 (*cinfo.mem->alloc_sarray) ((j_common_ptr) & cinfo, JPOOL_IMAGE,
192 row_stride, 1);
193 JSAMPROW ptr = NULL;
194 int i = 0;
195
196 std::vector < Color > color;
197 Bitmap bitmap (cinfo.output_width, cinfo.output_height);
198 while (cinfo.output_scanline < cinfo.output_height)
199 {
200 jpeg_read_scanlines (&cinfo, buffer, 1);
201 ptr = buffer[0];
202 //cout << "line " << ++i << " : " << endl;
203 int index = 0;
204 // scanline 是圖檔的寬度 * 顏色的數目,在 full color 一個 pixel 要三個 byte
205 //for (int col=0 ; col < cinfo.image_width * cinfo.output_components ; col++)
206 for (int col = 0; col < cinfo.image_width; col++)
207 {
208 //cout << index++ << " : GETJSAMPLE(*ptr++) : " << GETJSAMPLE(*ptr++) << endl;
209 //bitmap.push_back(GETJSAMPLE(*ptr++));
210 //gl_setpixelrgb(x+dx,y,GETJSAMPLE(*ptr)*level/256,GETJSAMPLE(*(ptr+1))*level/256,GETJSAMPLE(*(ptr+2))*level/256);
211 color.
212 push_back (Color
213 (GETJSAMPLE (*ptr), GETJSAMPLE (*(ptr + 1)),
214 GETJSAMPLE (*(ptr + 2))));
215
216 #ifdef DUMP_BITMAP_DATA
217 char h[2];
218 get_hex(GETJSAMPLE(*ptr), h);
219 cout << h[0] << h[1] << " ";
220 get_hex(GETJSAMPLE(*(ptr+1)), h);
221 cout << h[0] << h[1] << " ";
222 get_hex(GETJSAMPLE(*(ptr+2)), h);
223 cout << h[0] << h[1] << " ";
224 cout << endl;
225 #endif
226 //gl_setpixelrgb(x+dx,y,GETJSAMPLE(*ptr),GETJSAMPLE(*(ptr+1)),GETJSAMPLE(*(ptr+2)));
227 //dx++;
228 ptr += 3;
229 }
230 //dx=0;
231 //y++;
232 #ifdef DUMP_BITMAP_DATA
233 cout << endl;
234 #endif
235 }
236 bitmap.set_color (color);
237 //vga_setmode(TEXT);
238 int color_components = cinfo.output_components;
239 //cout << "cinfo.output_components : " << cinfo.output_components << endl;
240 jpeg_finish_decompress (&cinfo);
241 jpeg_destroy_decompress (&cinfo);
242
243 fclose (infile);
244
245
246
247
248 int fb_fd = open("/dev/fb0", O_RDWR);
249 if (fb_fd == -1) {
250 perror("open fail");
251 return 1;
252 }
253
254
255 if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &finfo) == -1) {
256 perror("FBIOGET_FSCREENINFO");
257 close(fb_fd);
258 return 1;
259 }
260
261 if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &vinfo) == -1) {
262 perror("FBIOGET_VSCREENINFO");
263 close(fb_fd);
264 return 1;
265 }
266
267 printf("Resolution: %dx%d, %dbpp\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel);
268
269 if (vinfo.bits_per_pixel != 32) {
270 fprintf(stderr, "This program only supports 32-bit framebuffer.\n");
271 close(fb_fd);
272 return 1;
273 }
274
275 long screensize = vinfo.yres * finfo.line_length;
276 fbp = (uint8_t *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, 0);
277 if (fbp == MAP_FAILED) {
278 perror("mmap");
279 close(fb_fd);
280 return 1;
281 }
282
283 printf("load jpg\n");
284
285 int square_x = 300;
286 int square_y = 300;
287 int size = 80;
288 show(bitmap, 300, 200, 100);
289
290
291 #if 0
292 for (int y = 0; y < size; y++) {
293 for (int x = 0; x < size; x++) {
294 int px = square_x + x;
295 int py = square_y + y;
296
297 long location = py * finfo.line_length + px * 4; // 4 bytes per pixel
298
299 // 32-bit ARGB,alpha=0xFF (不透明),紅色R=0xFF, G=0x00, B=0x00
300 // 寫法是 0xAARRGGBB
301 uint32_t *pixel = (uint32_t *)(fbp + location);
302 *pixel = 0xFFFF0000;
303 }
304 }
305 #endif
306
307 munmap(fbp, screensize);
308 close(fb_fd);
309
310 return 0;
311 }
拜 chatgpt 之強大, 透明效果沒花太多時間就完成, 這次應該就是透明效果了, 需要用底圖來計算。
list 2. fb-tran.cpp
1 /*
2 *
3 * $Author: descent $
4 * $Date: 2002/06/20 02:55:23 $
5 * $Id: jpeg.cpp,v 1.2 2002/06/20 02:55:23 descent Exp descent $
6 * $Revision: 1.2 $
7 * 程式功能:用 jpeg library 來讀取 jpeg 圖檔,改用 framebuffer 來秀圖
8 * 並加入透明效果。
9 */
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <fcntl.h>
14 #include <linux/fb.h>
15 #include <sys/mman.h>
16 #include <sys/ioctl.h>
17 #include <unistd.h>
18 #include <string.h>
19 #include <stdint.h>
20
21 #include <vector>
22 #include <iostream>
23 #include <string>
24
25 #include <jpeglib.h>
26 #include <jerror.h>
27
28 using namespace std;
29
30 uint8_t *fbp;
31 struct fb_var_screeninfo vinfo;
32 struct fb_fix_screeninfo finfo;
33
34 struct Color
35 {
36 Color (unsigned char r, unsigned char g, unsigned char b):r_ (r), g_ (g),
37 b_ (b)
38 {
39 }
40 unsigned char r () const
41 {
42 return r_;
43 }
44 unsigned char g () const
45 {
46 return g_;
47 }
48 unsigned char b () const
49 {
50 return b_;
51 }
52 private:
53 unsigned char r_, g_, b_;
54 };
55
56 class Bitmap
57 {
58 public:
59 Bitmap(int width, int height):width_ (width), height_ (height)
60 {
61 }
62 Bitmap():width_ (0), height_ (0)
63 {
64 }
65 void set_w_h(int w, int h)
66 {
67 width_ = w;
68 height_ = h;
69 }
70 void set_color (const std::vector < Color > &color)
71 {
72 color_ = color;
73 }
74 const std::vector < Color > &color_pixel () const
75 {
76 return color_;
77 }
78 int w () const
79 {
80 return width_;
81 }
82 int h () const
83 {
84 return height_;
85 }
86 private:
87 int width_, height_;
88 std::vector < Color > color_;
89 };
90
91 int r = 127;
92 int g = 78;
93 int b = 50;
94 int color_value;
95
96 //final = src_color * alpha + background_color * (1 - alpha);
97
98 uint8_t alpha_blend(uint8_t fg, uint8_t bg, uint8_t alpha) {
99 // alpha: 0~255, fg 前景, bg 背景
100 return (fg * alpha + bg * (255 - alpha)) / 255;
101 }
102
103 void show(const Bitmap& bitmap, int x, int y, int level, const Bitmap& bg_bitmap)
104 {
105 //bitmap.color_pixel();
106 std::vector < Color >::const_iterator it = bitmap.color_pixel ().begin ();
107
108 std::vector < Color >::const_iterator bg_it = bg_bitmap.color_pixel ().begin ();
109 printf("bitmap.h(): %d, bitmap.w(): %d\n", bitmap.h(), bitmap.w());
110 printf("bg_bitmap.h(): %d, bg_bitmap.w(): %d\n", bg_bitmap.h(), bg_bitmap.w());
111
112 //gl_getpalettecolor(color_value,&r,&g,&b);
113
114 for (int i = 0; i < bitmap.h (); ++i)
115 {
116 //usleep(1000);
117 for (int j = 0; j < bitmap.w (); ++j)
118 {
119 //gl_setpixelrgb(x+j,y+i,(*it).r()*level/256,(*it).g()*level/256,(*it).b()*level/256);
120 int pix_r = (*it).r ();
121 int pix_g = (*it).g ();
122 int pix_b = (*it).b ();
123
124
125
126
127 //gl_setpixelrgb(x+j,y+i,r +(pix_r - r)*level/256, g +(pix_g - g)*level/256, b + (pix_b - b)*level/256);
128 //gl_setpixelrgb(x+j,y+i,pix_r*level+r*(1-level),pix_g*level+g*(1-level),pix_b*level+b*(level));
129 long location = (y+i)*finfo.line_length + (x+j) * 4; // 4 bytes per pixel
130 uint32_t *pixel = (uint32_t *)(fbp + location);
131 //printf("i: %d, j: %d, pixel: %p, fbp: %p\n", i, j, pixel, fbp);
132 //gl_setpixelrgb (x + j, y + i, (*it).r (), (*it).g (), (*it).b ());
133 // 32-bit ARGB,alpha=0xFF (不透明),紅色R=0xFF, G=0x00, B=0x00
134 // 寫法是 0xAARRGGBB
135 unsigned int val = 0x00000000;
136 unsigned char new_r, new_g, new_b;
137
138 //double alpha = 0.8;
139 unsigned char alpha = 100;
140 #if 0
141 new_r = (unsigned char)((*it).r() * alpha + (*bg_it).r() *(255-alpha))/255;
142 new_b = (unsigned char)((*it).b() * alpha + (*bg_it).b() *(255-alpha))/255;
143 new_g = (unsigned char)((*it).g() * alpha + (*bg_it).g() *(255-alpha))/255;
144 #endif
145
146 new_r = alpha_blend((*it).r(), (*bg_it).r(), alpha);
147 new_g = alpha_blend((*it).g(), (*bg_it).g(), alpha);
148 new_b = alpha_blend((*it).b(), (*bg_it).b(), alpha);
149
150
151 #if 0
152 new_r = (*bg_it).r();
153 new_g = (*bg_it).g();
154 new_b = (*bg_it).b();
155 #endif
156
157
158 val |= ((*it).r() << 16);
159 val |= ((*it).g() << 8);
160 val |= (*it).b();
161
162 unsigned int bg_val = 0x00000000;
163 bg_val |= ((*bg_it).r() << 16);
164 bg_val |= ((*bg_it).g() << 8);
165 bg_val |= (*bg_it).b();
166
167 unsigned int final_val = 0xff000000;
168
169 //final_val |= 0xff << 24;
170 final_val |= new_r << 16;
171 final_val |= new_g << 8;
172 final_val |= new_b;
173
174 *pixel = final_val;
175 #if 0
176 if (i <= 120)
177 {
178 //gl_setpixelrgb (x + j, y + i, (*it).r (), (*it).g (), (*it).b ());
179 // 32-bit ARGB,alpha=0xFF (不透明),紅色R=0xFF, G=0x00, B=0x00
180 // 寫法是 0xAARRGGBB
181 unsigned int val = 0xff000000;
182 val |= ((*it).r() << 16);
183 val |= ((*it).g() << 8);
184 val |= (*it).b();
185 *pixel = val;
186 //*pixel = 0xFFFF0000;
187 }
188 else
189 {
190 unsigned int val = 0xff000000;
191 val |= (((*it).r () + (r - (*it).r ()) * level / 256) << 16);
192 val |= (((*it).g () + (g - (*it).g ()) * level / 256) << 8);
193 val |= ((*it).b () + (b - (*it).b ()) * level / 256);
194 *pixel = val;
195 //*pixel = 0xFFFF0000;
196 #if 0
197 gl_setpixelrgb (x + j, y + i,
198 (*it).r () + (r - (*it).r ()) * level / 256,
199 (*it).g () + (g - (*it).g ()) * level / 256,
200 (*it).b () + (b - (*it).b ()) * level / 256);
201 #endif
202 }
203 #endif
204 ++it;
205 if (i < bg_bitmap.h ())
206 ++bg_it;
207 }
208 }
209 //for ( ; it !=bitmap.color_pixel().end() ; ++it)
210
211 }
212
213 void get_hex (char c, char hex[])
214 {
215 char ascii[] = "0123456789abcdef";
216 int low = (c & 0x0f);
217 int high = ((c >> 4) & 0x0f);
218 hex[0] = ascii[high];
219 hex[1] = ascii[low];
220 }
221
222 int jpeg_to_bitmap(const string &filename, Bitmap &bitmap)
223 {
224 struct jpeg_decompress_struct cinfo;
225 struct jpeg_error_mgr jerr;
226
227 cinfo.err = jpeg_std_error (&jerr);
228 jpeg_create_decompress (&cinfo);
229
230 FILE *infile;
231 if ((infile = fopen (filename.c_str (), "rb")) == NULL)
232 {
233 fprintf (stderr, "cann't open file");
234 return -1;
235 }
236 //int level=255;
237 //if (argc>=3)
238 //level=atoi(argv[2]);
239 jpeg_stdio_src (&cinfo, infile);
240 jpeg_read_header (&cinfo, true);
241 // set parameters fro decompress
242 //cinfo.scale_num=1;
243 //cinfo.scale_denom=2;
244 //cinfo.output_width=640;
245 //cinfo.output_height=480;
246 //cinfo.image_height=480;
247 jpeg_start_decompress (&cinfo);
248
249 JSAMPARRAY buffer;
250 int row_stride = cinfo.output_width * cinfo.output_components;
251 int jpeg_width = cinfo.output_width;
252 buffer =
253 (*cinfo.mem->alloc_sarray) ((j_common_ptr) & cinfo, JPOOL_IMAGE,
254 row_stride, 1);
255 JSAMPROW ptr = NULL;
256 int i = 0;
257
258 std::vector < Color > color;
259 bitmap.set_w_h(cinfo.output_width, cinfo.output_height);
260 while (cinfo.output_scanline < cinfo.output_height)
261 {
262 jpeg_read_scanlines (&cinfo, buffer, 1);
263 ptr = buffer[0];
264 //cout << "line " << ++i << " : " << endl;
265 int index = 0;
266 // scanline 是圖檔的寬度 * 顏色的數目,在 full color 一個 pixel 要三個 byte
267 //for (int col=0 ; col < cinfo.image_width * cinfo.output_components ; col++)
268 for (int col = 0; col < cinfo.image_width; col++)
269 {
270 //cout << index++ << " : GETJSAMPLE(*ptr++) : " << GETJSAMPLE(*ptr++) << endl;
271 //bitmap.push_back(GETJSAMPLE(*ptr++));
272 //gl_setpixelrgb(x+dx,y,GETJSAMPLE(*ptr)*level/256,GETJSAMPLE(*(ptr+1))*level/256,GETJSAMPLE(*(ptr+2))*level/256);
273 color.
274 push_back (Color
275 (GETJSAMPLE (*ptr), GETJSAMPLE (*(ptr + 1)),
276 GETJSAMPLE (*(ptr + 2))));
277
278 #ifdef DUMP_BITMAP_DATA
279 char h[2];
280 get_hex(GETJSAMPLE(*ptr), h);
281 cout << h[0] << h[1] << " ";
282 get_hex(GETJSAMPLE(*(ptr+1)), h);
283 cout << h[0] << h[1] << " ";
284 get_hex(GETJSAMPLE(*(ptr+2)), h);
285 cout << h[0] << h[1] << " ";
286 cout << endl;
287 #endif
288 //gl_setpixelrgb(x+dx,y,GETJSAMPLE(*ptr),GETJSAMPLE(*(ptr+1)),GETJSAMPLE(*(ptr+2)));
289 //dx++;
290 ptr += 3;
291 }
292 //dx=0;
293 //y++;
294 #ifdef DUMP_BITMAP_DATA
295 cout << endl;
296 #endif
297 }
298 bitmap.set_color (color);
299 //vga_setmode(TEXT);
300 int color_components = cinfo.output_components;
301 //cout << "cinfo.output_components : " << cinfo.output_components << endl;
302 jpeg_finish_decompress (&cinfo);
303 jpeg_destroy_decompress (&cinfo);
304
305 fclose (infile);
306 return 0;
307 }
308
309 int main(int argc, char *argv[])
310 {
311 if (argc < 2)
312 {
313 cout << "Enter 2 file name" << endl;
314 return -1;
315 }
316
317 //string filename = argv[1];
318
319 Bitmap fg_bitmap;
320 jpeg_to_bitmap(argv[1], fg_bitmap);
321
322 Bitmap bg_bitmap;
323 jpeg_to_bitmap(argv[2], bg_bitmap);
324
325
326
327 int fb_fd = open("/dev/fb0", O_RDWR);
328 if (fb_fd == -1) {
329 perror("open fail");
330 return 1;
331 }
332
333
334 if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &finfo) == -1) {
335 perror("FBIOGET_FSCREENINFO");
336 close(fb_fd);
337 return 1;
338 }
339
340 if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &vinfo) == -1) {
341 perror("FBIOGET_VSCREENINFO");
342 close(fb_fd);
343 return 1;
344 }
345
346 printf("Resolution: %dx%d, %dbpp\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel);
347
348 if (vinfo.bits_per_pixel != 32) {
349 fprintf(stderr, "This program only supports 32-bit framebuffer.\n");
350 close(fb_fd);
351 return 1;
352 }
353
354 long screensize = vinfo.yres * finfo.line_length;
355 fbp = (uint8_t *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, 0);
356 if (fbp == MAP_FAILED) {
357 perror("mmap");
358 close(fb_fd);
359 return 1;
360 }
361
362 printf("load jpg\n");
363
364 int square_x = 300;
365 int square_y = 300;
366 int size = 80;
367
368 #if 0
369 show(bg_bitmap, 300, 200, 100, );
370 sleep(2);
371 #endif
372
373 show(fg_bitmap, 300, 200, 100, bg_bitmap);
374 sleep(2);
375
376
377 #if 0
378 for (int y = 0; y < size; y++) {
379 for (int x = 0; x < size; x++) {
380 int px = square_x + x;
381 int py = square_y + y;
382
383 long location = py * finfo.line_length + px * 4; // 4 bytes per pixel
384
385 // 32-bit ARGB,alpha=0xFF (不透明),紅色R=0xFF, G=0x00, B=0x00
386 // 寫法是 0xAARRGGBB
387 uint32_t *pixel = (uint32_t *)(fbp + location);
388 *pixel = 0xFFFF0000;
389 }
390 }
391 #endif
392
393 munmap(fbp, screensize);
394 close(fb_fd);
395
396 return 0;
397 }
List 2 L98 是透明演算法。
g++ fb-tran.cpp -o fb-tran -ljpeg
VIDEO
現在應該都是透過顯示卡來做透明效果, 很少會用 cpu 計算了。