r956: README.BUILD - add more library recommendations
[cinelerra_cv/ct.git] / guicast / bcbitmap.C
blob4df131ec36843767a904c9509184b89e2c0b6651
1 #include "bcbitmap.h"
2 #include "bcipc.h"
3 #include "bcresources.h"
4 #include "bcsignals.h"
5 #include "bcwindow.h"
6 #include "colormodels.h"
7 #include "vframe.h"
9 #include <string.h>
10 #include <unistd.h>
11 #include <X11/extensions/Xvlib.h>
14 BC_Bitmap::BC_Bitmap(BC_WindowBase *parent_window, unsigned char *png_data)
16 // Decompress data into a temporary vframe
17         VFrame frame;
19         frame.read_png(png_data);
21 // Initialize the bitmap
22         initialize(parent_window, 
23                 frame.get_w(), 
24                 frame.get_h(), 
25                 parent_window->get_color_model(), 
26                 0);
28 // Copy the vframe to the bitmap
29         read_frame(&frame, 0, 0, w, h);
32 BC_Bitmap::BC_Bitmap(BC_WindowBase *parent_window, VFrame *frame)
34 // Initialize the bitmap
35         initialize(parent_window, 
36                 frame->get_w(), 
37                 frame->get_h(), 
38                 parent_window->get_color_model(), 
39                 0);
41 // Copy the vframe to the bitmap
42         read_frame(frame, 0, 0, w, h);
45 BC_Bitmap::BC_Bitmap(BC_WindowBase *parent_window, 
46         int w, 
47         int h, 
48         int color_model, 
49         int use_shm)
51         initialize(parent_window, 
52                 w, 
53                 h, 
54                 color_model, 
55                 use_shm ? parent_window->get_resources()->use_shm : 0);
58 BC_Bitmap::~BC_Bitmap()
60         delete_data();
63 int BC_Bitmap::initialize(BC_WindowBase *parent_window, 
64         int w, 
65         int h, 
66         int color_model, 
67         int use_shm)
69         this->parent_window = parent_window;
70         this->top_level = parent_window->top_level;
71         this->w = w;
72         this->h = h;
73         this->color_model = color_model;
74         this->use_shm = use_shm ? parent_window->get_resources()->use_shm : 0;
75         this->bg_color = parent_window->bg_color;
76         ximage[0] = 0;
77         xv_image[0] = 0;
78         data[0] = 0;
79         last_pixmap_used = 0;
80         last_pixmap = 0;
81         current_ringbuffer = 0;
82 // Set ring buffers based on total memory used.
83 // The program icon must use multiple buffers but larger bitmaps may not fit
84 // in memory.
85         int pixelsize = cmodel_calculate_pixelsize(color_model);
86         int buffer_size = w * h * pixelsize;
88         if(buffer_size < 0x40000)
89                 ring_buffers = 4;
90         else
91                 ring_buffers = 1;
93         allocate_data();
94         return 0;
97 int BC_Bitmap::match_params(int w, int h, int color_model, int use_shm)
99         if(this->w /* != */ < w ||
100                 this->h /* != */ < h ||
101                 this->color_model != color_model ||
102                 this->use_shm != use_shm)
103         {
104                 delete_data();
105                 initialize(parent_window, w, h, color_model, use_shm);
106         }
108         return 0;
111 int BC_Bitmap::params_match(int w, int h, int color_model, int use_shm)
113         int result = 0;
114         if(this->w == w &&
115                 this->h == h &&
116                 this->color_model == color_model)
117         {
118                 if(use_shm == this->use_shm || use_shm == BC_INFINITY)
119                         result = 1;
120         }
122         return result;
126 int BC_Bitmap::allocate_data()
128         int want_row_pointers = 1;
130 // Shared memory available
131     if(use_shm)
132         {
133                 switch(color_model)
134                 {
135 // Planar YUV.  Must use BC_WindowBase::accel_available before calling this.
136                         case BC_YUV420P:
137                         case BC_YUV422P:
138 // Packed YUV
139                         case BC_YUV422:
140                                 ring_buffers = BITMAP_RING;
141                                 xv_portid = top_level->xvideo_port_id;
142 // Create the X Image
143                                 xv_image[0] = XvShmCreateImage(top_level->display, 
144                                                         xv_portid, 
145                                                         cmodel_bc_to_x(color_model),
146                                                         0, 
147                                                         w,
148                                                         h,
149                                                         &shm_info);
150 // Create the shared memory
151                                 shm_info.shmid = shmget(IPC_PRIVATE, 
152                                         xv_image[0]->data_size * ring_buffers + 4, 
153                                         IPC_CREAT | 0777);
154                                 if(shm_info.shmid < 0) perror("BC_Bitmap::allocate_data shmget");
155                                 data[0] = (unsigned char *)shmat(shm_info.shmid, NULL, 0);
156 // setting ximage->data stops BadValue
157                                 xv_image[0]->data = shm_info.shmaddr = (char*)data[0];
158                                 shm_info.readOnly = 0;
160 // Get the real parameters
161                                 w = xv_image[0]->width;
162                                 h = xv_image[0]->height;
164 // Create remaining X Images
165                                 for(int i = 1; i < ring_buffers; i++)
166                                 {
167                                         data[i] = data[0] + xv_image[0]->data_size * i;
168                                         xv_image[i] = XvShmCreateImage(top_level->display, 
169                                                                 xv_portid, 
170                                                                 cmodel_bc_to_x(color_model),
171                                                                 (char*)data[i], 
172                                                                 w,
173                                                                 h,
174                                                                 &shm_info);
175                                         xv_image[i]->data = (char*)data[i];
176                                 }
178                                 if(color_model == BC_YUV422)
179                                 {
180                                         bytes_per_line = w * 2;
181                                         bits_per_pixel = 2;
182                                         want_row_pointers = 1;
183                                 }
184                                 else
185                                 {
186                                         bytes_per_line = 0;
187                                         bits_per_pixel = 0;
188                                         want_row_pointers = 0;
189                                 }
190                                 break;
192                         default:
193 // RGB
194                                 ring_buffers = BITMAP_RING;
195 // Create first X Image
196                         ximage[0] = XShmCreateImage(top_level->display, 
197                                         top_level->vis, 
198                                         get_default_depth(), 
199                                         get_default_depth() == 1 ? XYBitmap : ZPixmap, 
200                                         (char*)NULL, 
201                                         &shm_info, 
202                                         w, 
203                                         h);
205 // Create shared memory
206                                 shm_info.shmid = shmget(IPC_PRIVATE, 
207                                         h * ximage[0]->bytes_per_line * ring_buffers + 4, 
208                                         IPC_CREAT | 0777);
209                                 if(shm_info.shmid < 0) 
210                                         perror("BC_Bitmap::allocate_data shmget");
211                                 data[0] = (unsigned char *)shmat(shm_info.shmid, NULL, 0);
212                                 ximage[0]->data = shm_info.shmaddr = (char*)data[0];  // setting ximage->data stops BadValue
213                                 shm_info.readOnly = 0;
215 // Get the real parameters
216                                 bits_per_pixel = ximage[0]->bits_per_pixel;
217                                 bytes_per_line = ximage[0]->bytes_per_line;
219 // Create remaining X Images
220                                 for(int i = 1; i < ring_buffers; i++)
221                                 {
222                                         data[i] = data[0] + h * ximage[0]->bytes_per_line * i;
223                                         ximage[i] = XShmCreateImage(top_level->display, 
224                                                                                         top_level->vis, 
225                                                                                         get_default_depth(), 
226                                                                                         get_default_depth() == 1 ? XYBitmap : ZPixmap, 
227                                                                                         (char*)data[i], 
228                                                                                         &shm_info, 
229                                                                                         w, 
230                                                                                         h);
231                                         ximage[i]->data = (char*)data[i];
232 //printf("BC_Bitmap::allocate_data %p\n", ximage[i]);
233                                 }
234                                 break;
235                 }
237                 if(!XShmAttach(top_level->display, &shm_info))
238                 {
239                         perror("BC_Bitmap::allocate_data XShmAttach");
240                 }
242 // This causes it to automatically delete when the program exits.
243                 shmctl(shm_info.shmid, IPC_RMID, 0);
244         }
245         else
246 // Use unshared memory.
247         {
248                 ring_buffers = 1;
249 // need to use bytes_per_line for some X servers
250                 data[0] = 0;
252 // Use RGB frame
253 //printf("BCBitmap::allocate_data 1\n");
254                 ximage[0] = XCreateImage(top_level->display, 
255                                         top_level->vis, 
256                                         get_default_depth(), 
257                                         get_default_depth() == 1 ? XYBitmap : ZPixmap, 
258                                         0, 
259                                         (char*)data[0], 
260                                         w, 
261                                         h, 
262                                         8, 
263                                         0);
264 //printf("BCBitmap::allocate_data 1 %d\n", h * ximage[0]->bytes_per_line + 4);
266                 data[0] = (unsigned char*)malloc(h * ximage[0]->bytes_per_line + 4);
267 //printf("BCBitmap::allocate_data 2\n");
269                 XDestroyImage(ximage[0]);
270 //printf("BCBitmap::allocate_data 1\n");
272                 ximage[0] = XCreateImage(top_level->display, 
273                                         top_level->vis, 
274                                         get_default_depth(), 
275                                         get_default_depth() == 1 ? XYBitmap : ZPixmap, 
276                                         0, 
277                                         (char*)data[0], 
278                                         w, 
279                                         h, 
280                                         8, 
281                                         0);
282 //printf("BCBitmap::allocate_data 1\n");
283 // This differs from the depth parameter of the top_level.
284                 bits_per_pixel = ximage[0]->bits_per_pixel;
285                 bytes_per_line = ximage[0]->bytes_per_line;
286 //printf("BCBitmap::allocate_data 2\n");
287         }
289 // Create row pointers
290         if(want_row_pointers)
291         {
292 //printf("BC_Bitmap::allocate 1 %d %d %d %d\n", w, h, get_default_depth(), bytes_per_line);
293                 for(int j = 0; j < ring_buffers; j++)
294                 {
295                         row_data[j] = new unsigned char*[h];
296                         for(int i = 0; i < h; i++)
297                         {
298                                 row_data[j][i] = &data[j][i * bytes_per_line];
299                         }
300                 }
301         }
302         return 0;
305 int BC_Bitmap::delete_data()
307         if(data[0])
308         {
309                 if(use_shm)
310                 {
311                         switch(color_model)
312                         {
313                                 case BC_YUV420P:
314                                 case BC_YUV422P:
315                                 case BC_YUV422:
316 //printf("BC_Bitmap::delete_data 1\n");
317                                         if(last_pixmap_used) XvStopVideo(top_level->display, xv_portid, last_pixmap);
318                                         for(int i = 0; i < ring_buffers; i++)
319                                         {
320                                                 XFree(xv_image[i]);
321                                         }
322                                         XShmDetach(top_level->display, &shm_info);
323                                         XvUngrabPort(top_level->display, xv_portid, CurrentTime);
325                                         shmdt(shm_info.shmaddr);
326                                         shmctl(shm_info.shmid, IPC_RMID, 0);
327                                         break;
329                                 default:
330                                         for(int i = 0; i < ring_buffers; i++)
331                                         {
332                                                 XDestroyImage(ximage[i]);
333                                                 delete [] row_data[i];
334                                         }
335                                         XShmDetach(top_level->display, &shm_info);
337                                         shmdt(shm_info.shmaddr);
338                                         shmctl(shm_info.shmid, IPC_RMID, 0);
339                                         break;
340                         }
341                 }
342                 else
343                 {
344                         XDestroyImage(ximage[0]);
345                         delete [] row_data[0];
346                 }
348 // data is automatically freed by XDestroyImage
349                 data[0] = 0;
350                 last_pixmap_used = 0;
351         }
352         return 0;
355 int BC_Bitmap::get_default_depth()
357         if(color_model == BC_TRANSPARENCY)
358                 return 1;
359         else
360                 return top_level->default_depth;
364 int BC_Bitmap::set_bg_color(int color)
366         this->bg_color = color;
367         return 0;
370 int BC_Bitmap::invert()
372         for(int j = 0; j < ring_buffers; j++)
373                 for(int k = 0; k < h; k++)
374                         for(int i = 0; i < bytes_per_line; i++)
375                         {
376                                 row_data[j][k][i] ^= 0xff;
377                         }
378         return 0;
381 int BC_Bitmap::write_drawable(Drawable &pixmap, 
382                                                         GC &gc,
383                                                         int dest_x, 
384                                                         int dest_y, 
385                                                         int source_x, 
386                                                         int source_y, 
387                                                         int dest_w, 
388                                                         int dest_h,
389                                                         int dont_wait)
391         return write_drawable(pixmap, 
392                 gc,
393                 source_x, 
394                 source_y, 
395                 get_w() - source_x,
396                 get_h() - source_y,
397                 dest_x, 
398                 dest_y, 
399                 dest_w, 
400                 dest_h, 
401                 dont_wait);
404 void BC_Bitmap::rewind_ring()
406         current_ringbuffer--;
407         if(current_ringbuffer < 0) current_ringbuffer = ring_buffers - 1;
410 int BC_Bitmap::write_drawable(Drawable &pixmap, 
411                 GC &gc,
412                 int source_x, 
413                 int source_y, 
414                 int source_w,
415                 int source_h,
416                 int dest_x, 
417                 int dest_y, 
418                 int dest_w, 
419                 int dest_h, 
420                 int dont_wait)
422 //printf("BC_Bitmap::write_drawable 1 %p %d\n", this, current_ringbuffer);fflush(stdout);
423     if(use_shm)
424         {
425                 if(dont_wait) XSync(top_level->display, False);
427                 if(hardware_scaling())
428                 {
429 // printf("BC_Bitmap::write_drawable %d %d %d %d -> %d %d %d %d\n", source_x, 
430 //                              source_y, 
431 //                              source_w, 
432 //                              source_h, 
433 //                              dest_x, 
434 //                              dest_y, 
435 //                              dest_w, 
436 //                              dest_h);
437 //for(int i = 0; i < 1000; i++) xv_image[current_ringbuffer]->data[i] = 255;
438 //printf("BC_Bitmap::write_drawable 2 %d %d %p %p\n", xv_portid, 
439 //      pixmap, 
440 //      gc,
441 //      xv_image[current_ringbuffer]);
442                         XvShmPutImage(top_level->display, 
443                                 xv_portid, 
444                                 pixmap, 
445                                 gc,
446                                 xv_image[current_ringbuffer], 
447                                 source_x, 
448                                 source_y, 
449                                 source_w, 
450                                 source_h, 
451                                 dest_x, 
452                                 dest_y, 
453                                 dest_w, 
454                                 dest_h, 
455                                 False);
456 // Need to pass these to the XvStopVideo
457                         last_pixmap = pixmap;
458                         last_pixmap_used = 1;
459                 }
460                 else
461                 {
462 // printf("BC_Bitmap::write_drawable %d %d %d %d -> %d %d %d %d\n", source_x, 
463 //                              source_y, 
464 //                              source_w, 
465 //                              source_h, 
466 //                              dest_x, 
467 //                              dest_y, 
468 //                              dest_w, 
469 //                              dest_h);
470                 XShmPutImage(top_level->display, 
471                                 pixmap, 
472                                 gc, 
473                                 ximage[current_ringbuffer], 
474                                 source_x, 
475                                 source_y, 
476                                 dest_x, 
477                                 dest_y, 
478                                 dest_w, 
479                                 dest_h, 
480                                 False);
481                 }
483 // Force the X server into processing all requests.
484 // This allows the shared memory to be written to again.
485                 if(!dont_wait) XSync(top_level->display, False);
486 //TRACE("BC_Bitmap::write_drawable 5");
487         }
488     else
489         {
490         XPutImage(top_level->display, 
491                         pixmap, 
492                         gc, 
493                         ximage[current_ringbuffer], 
494                         source_x, 
495                         source_y, 
496                         dest_x, 
497                         dest_y, 
498                         dest_w, 
499                         dest_h);
500         }
502 //printf("BC_Bitmap %d\n", current_ringbuffer);
503         current_ringbuffer++;
504         if(current_ringbuffer >= ring_buffers) current_ringbuffer = 0;
505 //printf("BC_Bitmap::write_drawable 2\n");fflush(stdout);
506         return 0;
512 // the bitmap must be wholly contained in the source during a GetImage
513 int BC_Bitmap::read_drawable(Drawable &pixmap, int source_x, int source_y)
515         if(use_shm)
516                 XShmGetImage(top_level->display, pixmap, ximage[current_ringbuffer], source_x, source_y, 0xffffffff);
517         else
518                 XGetSubImage(top_level->display, pixmap, source_x, source_y, w, h, 0xffffffff, ZPixmap, ximage[current_ringbuffer], 0, 0);
519         return 0;
522 // ============================ Decoding VFrames
524 int BC_Bitmap::read_frame(VFrame *frame, 
525         int x1, 
526         int y1, 
527         int x2, 
528         int y2)
530         return read_frame(frame, 
531                 0, 0, frame->get_w(), frame->get_h(),
532                 x1, y1, x2 - x1, y2 - y1);
536 int BC_Bitmap::read_frame(VFrame *frame, 
537         int in_x, 
538         int in_y, 
539         int in_w, 
540         int in_h,
541         int out_x, 
542         int out_y, 
543         int out_w, 
544         int out_h)
546         switch(color_model)
547         {
548 // Hardware accelerated bitmap
549                 case BC_YUV420P:
550                         if(frame->get_color_model() == color_model)
551                         {
552                                 memcpy(get_y_plane(), frame->get_y(), w * h);
553                                 memcpy(get_u_plane(), frame->get_u(), w * h / 4);
554                                 memcpy(get_v_plane(), frame->get_v(), w * h / 4);
555                                 break;
556                         }
558                 case BC_YUV422P:
559                         if(frame->get_color_model() == color_model)
560                         {
561                                 memcpy(get_y_plane(), frame->get_y(), w * h);
562                                 memcpy(get_u_plane(), frame->get_u(), w * h / 2);
563                                 memcpy(get_v_plane(), frame->get_v(), w * h / 2);
564                                 break;
565                         }
567                 case BC_YUV422:
568                         if(frame->get_color_model() == color_model)
569                         {
570                                 memcpy(get_data(), frame->get_data(), w * h + w * h);
571                                 break;
572                         }
574 // Software only
575                 default:
576 // printf("BC_Bitmap::read_frame %d -> %d %d %d %d %d -> %d %d %d %d\n",
577 //                              frame->get_color_model(), 
578 //                              color_model,
579 //                              in_x, 
580 //                              in_y, 
581 //                              in_w, 
582 //                              in_h,
583 //                              out_x, 
584 //                              out_y, 
585 //                              out_w, 
586 //                              out_h);
587 //if(color_model == 6 && frame->get_color_model() == 19)
588 //printf("BC_Bitmap::read_frame 1 %d %d %d %d\n", frame->get_w(), frame->get_h(), get_w(), get_h());
589                         cmodel_transfer(row_data[current_ringbuffer], 
590                                 frame->get_rows(),
591                                 get_y_plane(),
592                                 get_u_plane(),
593                                 get_v_plane(),
594                                 frame->get_y(),
595                                 frame->get_u(),
596                                 frame->get_v(),
597                                 in_x, 
598                                 in_y, 
599                                 in_w, 
600                                 in_h,
601                                 out_x, 
602                                 out_y, 
603                                 out_w, 
604                                 out_h,
605                                 frame->get_color_model(), 
606                                 color_model,
607                                 bg_color,
608                                 frame->get_w(),
609                                 w);
610 // color model transfer_*_to_TRANSPARENCY don't care about endianness
611 // so buffer bitswaped here if needed.
612                                 if ((color_model == BC_TRANSPARENCY) && (!top_level->server_byte_order))
613                                         transparency_bitswap();
616 //if(color_model == 6 && frame->get_color_model() == 19)
617 //printf("BC_Bitmap::read_frame 2\n");
618                         break;
619         }
622         return 0;
625 long BC_Bitmap::get_shm_id()
627         return shm_info.shmid;
630 long BC_Bitmap::get_shm_size()
632         if(xv_image[0])
633                 return xv_image[0]->data_size * ring_buffers;
634         else
635                 return h * ximage[0]->bytes_per_line;
638 long BC_Bitmap::get_shm_offset()
640         if(xv_image[0])
641                 return xv_image[0]->data_size * current_ringbuffer;
642         else
643         if(ximage[0])
644                 return h * ximage[0]->bytes_per_line * current_ringbuffer;
645         else
646                 return 0;
649 long BC_Bitmap::get_y_shm_offset()
651         if(xv_image[0])
652                 return get_shm_offset() + xv_image[current_ringbuffer]->offsets[0];
653         else
654                 return 0;
657 long BC_Bitmap::get_u_shm_offset()
659         if(xv_image[0])
660                 return get_shm_offset() + xv_image[current_ringbuffer]->offsets[2];
661         else
662                 return 0;
665 long BC_Bitmap::get_v_shm_offset()
667         if(xv_image[0])
668                 return get_shm_offset() + xv_image[current_ringbuffer]->offsets[1];
669         else
670                 return 0;
673 long BC_Bitmap::get_y_offset()
675         if(xv_image[0])
676                 return xv_image[current_ringbuffer]->offsets[0];
677         else
678                 return 0;
681 long BC_Bitmap::get_u_offset()
683         if(xv_image[0] && xv_image[current_ringbuffer]->num_planes > 1)
684                 return xv_image[current_ringbuffer]->offsets[2];
685         else
686                 return 0;
689 long BC_Bitmap::get_v_offset()
691         if(xv_image[0] && xv_image[current_ringbuffer]->num_planes > 1)
692                 return xv_image[current_ringbuffer]->offsets[1];
693         else
694                 return 0;
698 unsigned char** BC_Bitmap::get_row_pointers()
700         return row_data[current_ringbuffer];
703 int BC_Bitmap::get_bytes_per_line()
705         return bytes_per_line;
707 unsigned char* BC_Bitmap::get_data()
709 //printf("BC_Bitmap::get_data %d %p\n",current_ringbuffer , data[current_ringbuffer]);
710         return data[current_ringbuffer];
713 unsigned char* BC_Bitmap::get_y_plane()
715         if(color_model == BC_YUV420P ||
716                 color_model == BC_YUV422P)
717                 return data[current_ringbuffer] + xv_image[current_ringbuffer]->offsets[0];
718         else
719                 return 0;
722 unsigned char* BC_Bitmap::get_v_plane()
724         if(color_model == BC_YUV420P ||
725                 color_model == BC_YUV422P)
726                 return data[current_ringbuffer] + xv_image[current_ringbuffer]->offsets[1];
727         else
728                 return 0;
731 unsigned char* BC_Bitmap::get_u_plane()
733         if(color_model == BC_YUV420P ||
734                 color_model == BC_YUV422P)
735                 return data[current_ringbuffer] + xv_image[current_ringbuffer]->offsets[2];
736         else
737                 return 0;
740 void BC_Bitmap::rewind_ringbuffer()
742         current_ringbuffer--;
743         if(current_ringbuffer < 0) current_ringbuffer = ring_buffers - 1;
746 int BC_Bitmap::hardware_scaling()
748         return (get_color_model() == BC_YUV420P || 
749                 get_color_model() == BC_YUV422P || 
750                 get_color_model() == BC_YUV422);
753 int BC_Bitmap::get_w() { return w; }
755 int BC_Bitmap::get_h() { return h; }
757 char BC_Bitmap::byte_bitswap(char src) {
758         int i;
759         char dst;
761         dst = 0;
762         if (src & 1) dst |= ((unsigned char)1 << 7);
763         src = src >> 1;
764         if (src & 1) dst |= ((unsigned char)1 << 6);
765         src = src >> 1;
766         if (src & 1) dst |= ((unsigned char)1 << 5);
767         src = src >> 1;
768         if (src & 1) dst |= ((unsigned char)1 << 4);
769         src = src >> 1;
770         if (src & 1) dst |= ((unsigned char)1 << 3);
771         src = src >> 1;
772         if (src & 1) dst |= ((unsigned char)1 << 2);
773         src = src >> 1;
774         if (src & 1) dst |= ((unsigned char)1 << 1);
775         src = src >> 1;
776         if (src & 1) dst |= ((unsigned char)1 << 0);
778         return(dst);
781 void BC_Bitmap::transparency_bitswap() {
782         unsigned char *buf;
783         int i, width, height;
784         int len;
786         buf = *row_data[current_ringbuffer];
788         width = w;
789         height = h;
790         if (width % 8)
791                 width = width + 8 - (width % 8);
792         len = width * height / 8;
794         for(i=0 ; i+8<=len ; i+=8){
795                 buf[i+0] = byte_bitswap(buf[i+0]);
796                 buf[i+1] = byte_bitswap(buf[i+1]);
797                 buf[i+2] = byte_bitswap(buf[i+2]);
798                 buf[i+3] = byte_bitswap(buf[i+3]);
799                 buf[i+4] = byte_bitswap(buf[i+4]);
800                 buf[i+5] = byte_bitswap(buf[i+5]);
801                 buf[i+6] = byte_bitswap(buf[i+6]);
802                 buf[i+7] = byte_bitswap(buf[i+7]);
803         }
804         for( ; i<len ; i++){
805                 buf[i+0] = byte_bitswap(buf[i+0]);
806         }
809 int BC_Bitmap::get_color_model() { return color_model; }