2025年8月7日 星期四

讀取 jpeg 圖片, 本來以為是透明效果, 不過這個好像是漸層效果顯示, 另外實做了透明效果。



這是我在 2002 寫的程式, 對透明色處理有興趣, 想自己寫出來, 找了很久, 忘記在哪本書看到這個演算法, 透過 linux/sgvalib 實做出來, 寫出來時還蠻開心的, 那時候用的版本控制軟體是 rcs。

2002 沒有 chatgpt, 光是使用 jpeg lib 就難倒我, 啃著英文文件, 也不知道有沒看懂, 硬是讓我成功解出 jpeg 內容, 現在有 chatgpt, 應該秒會用吧!



看起來還蠻像一回事。在 20250804 想到 pc9801 遊戲 16 色時突然想到這個, 把這程式以 framebuffer 重新改寫, 沒辦法, svgalib 可能沒辦法在現今的平台執行, 看到演算法, 並沒有和背景色做運算, 我傻眼, 這好像不是透明演算法。問了 chatgpt 這個演算法, 還真的不是, chatgpt 說這是漸層演算法, 整整搞錯 23 年。

framebuffer 繪圖則是問 chatgpt, 節省不少時間。

透明色公式是:
final = src_color * alpha + background_color * (1 - alpha);

由於在螢幕上顯示圖形非常複雜, 需要理解 vga 顯示模式和影像格式, 我挑了最簡單的方式做, 在 640x480 24bit color 上顯示 24bit jpeg 圖檔, 可以避開 Quantization + Dithering 的問題, 現在有 chatgpt, 比較容易找到這 2 個演算法, 23 年科技進步的太大了。

在 2025 年, 這些技術也不需要, 2025 年應該不會有 256 色的顯示模式了。

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

沒有留言:

張貼留言

使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。

我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。