cdrom: try some different seek times
[pcsx_rearmed.git] / deps / libretro-common / formats / bmp / rbmp.c
1 /* Copyright  (C) 2010-2020 The RetroArch team
2  *
3  * ---------------------------------------------------------------------------------------
4  * The following license statement only applies to this file (rbmp.c).
5  * ---------------------------------------------------------------------------------------
6  *
7  * Permission is hereby granted, free of charge,
8  * to any person obtaining a copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation the rights to
10  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
11  * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
16  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  */
22
23 /* Modified version of stb_image's BMP sources. */
24
25 #include <stdio.h>
26 #include <stdint.h>
27 #include <stdarg.h>
28 #include <stddef.h> /* ptrdiff_t on osx */
29 #include <stdlib.h>
30 #include <string.h>
31
32 #include <retro_inline.h>
33
34 #include <formats/image.h>
35 #include <formats/rbmp.h>
36
37 /* truncate int to byte without warnings */
38 #define RBMP_BYTECAST(x)  ((unsigned char) ((x) & 255))
39
40 #define RBMP_COMPUTE_Y(r, g, b) ((unsigned char) ((((r) * 77) + ((g) * 150) +  (29 * (b))) >> 8))
41
42 typedef struct
43 {
44    unsigned char *img_buffer;
45    unsigned char *img_buffer_end;
46    unsigned char *img_buffer_original;
47    int img_n;
48    int img_out_n;
49    int buflen;
50    uint32_t img_x;
51    uint32_t img_y;
52    unsigned char buffer_start[128];
53 } rbmp_context;
54
55 struct rbmp
56 {
57    uint8_t *buff_data;
58    uint32_t *output_image;
59 };
60
61 static INLINE unsigned char rbmp_get8(rbmp_context *s)
62 {
63    if (s->img_buffer < s->img_buffer_end)
64       return *s->img_buffer++;
65
66    return 0;
67 }
68
69 static void rbmp_skip(rbmp_context *s, int n)
70 {
71    if (n < 0)
72    {
73       s->img_buffer = s->img_buffer_end;
74       return;
75    }
76
77    s->img_buffer += n;
78 }
79
80 static int rbmp_get16le(rbmp_context *s)
81 {
82    return rbmp_get8(s) + (rbmp_get8(s) << 8);
83 }
84
85 #define RBMP_GET32LE(s) (rbmp_get16le(s) + (rbmp_get16le(s) << 16))
86
87 static unsigned char *rbmp_convert_format(
88       unsigned char *data,
89       int img_n,
90       int req_comp,
91       unsigned int x,
92       unsigned int y)
93 {
94    int i,j;
95    unsigned char *good = (unsigned char *)malloc(req_comp * x * y);
96
97    if (!good)
98       return NULL;
99
100    for (j=0; j < (int) y; ++j)
101    {
102       unsigned char *src  = data + j * x * img_n   ;
103       unsigned char *dest = good + j * x * req_comp;
104
105       switch (((img_n)*8+(req_comp)))
106       {
107          case 10:
108             for (i = x-1; i >= 0; --i, src += 1, dest += 2)
109             {
110                dest[0]=src[0];
111                dest[1]=255;
112             }
113             break;
114          case 11:
115             for (i = x-1; i >= 0; --i, src += 1, dest += 3)
116                dest[0]=dest[1]=dest[2]=src[0];
117             break;
118          case 12:
119             for (i = x-1; i >= 0; --i, src += 1, dest += 4)
120             {
121                dest[0]=dest[1]=dest[2]=src[0];
122                dest[3]=255;
123             }
124             break;
125          case 17:
126             for (i = x-1; i >= 0; --i, src += 2, dest += 1)
127                dest[0]=src[0];
128             break;
129          case 19:
130             for (i = x-1; i >= 0; --i, src += 2, dest += 3)
131                dest[0]=dest[1]=dest[2]=src[0];
132             break;
133          case 20:
134             for (i = x-1; i >= 0; --i, src += 2, dest += 4)
135             {
136                dest[0]=dest[1]=dest[2]=src[0];
137                dest[3]=src[1];
138             }
139             break;
140          case 28:
141             for (i = x-1; i >= 0; --i, src += 3, dest += 4)
142             {
143                dest[0]=src[0];
144                dest[1]=src[1];
145                dest[2]=src[2];
146                dest[3]=255;
147             }
148             break;
149          case 25:
150             for (i = x-1; i >= 0; --i, src += 3, dest += 1)
151                dest[0] = RBMP_COMPUTE_Y(src[0],src[1],src[2]);
152             break;
153          case 26:
154             for (i = x-1; i >= 0; --i, src += 3, dest += 2)
155             {
156                dest[0] = RBMP_COMPUTE_Y(src[0],src[1],src[2]);
157                dest[1] = 255;
158             }
159             break;
160          case 33:
161             for (i = x-1; i >= 0; --i, src += 4, dest += 1)
162                dest[0] = RBMP_COMPUTE_Y(src[0],src[1],src[2]);
163             break;
164          case 34:
165             for (i = x-1; i >= 0; --i, src += 4, dest += 2)
166             {
167                dest[0] = RBMP_COMPUTE_Y(src[0],src[1],src[2]);
168                dest[1] = src[3];
169             }
170             break;
171          case 35:
172             for (i = x-1; i >= 0; --i, src += 4, dest += 3)
173             {
174                dest[0]=src[0];
175                dest[1]=src[1];
176                dest[2]=src[2];
177             }
178             break;
179          default:
180             break;
181       }
182
183    }
184
185    return good;
186 }
187
188 /* Microsoft/Windows BMP image */
189
190 /* returns 0..31 for the highest set bit */
191 static int rbmp_high_bit(unsigned int z)
192 {
193    int n=0;
194    if (z == 0)
195       return -1;
196
197    if (z >= 0x10000)
198    {
199       n  += 16;
200       z >>= 16;
201    }
202    if (z >= 0x00100)
203    {
204       n  +=  8;
205       z >>=  8;
206    }
207    if (z >= 0x00010)
208    {
209       n  +=  4;
210       z >>=  4;
211    }
212    if (z >= 0x00004)
213    {
214       n  +=  2;
215       z >>=  2;
216    }
217    if (z >= 0x00002)
218       n +=  1;
219    return n;
220 }
221
222 static int rbmp_bitcount(unsigned int a)
223 {
224    a = (a & 0x55555555) + ((a >>  1) & 0x55555555); /* max 2 */
225    a = (a & 0x33333333) + ((a >>  2) & 0x33333333); /* max 4 */
226    a = (a + (a >> 4)) & 0x0f0f0f0f; /* max 8 per 4, now 8 bits */
227    a = (a + (a >> 8));              /* max 16 per 8 bits */
228    a = (a + (a >> 16));             /* max 32 per 8 bits */
229    return a & 0xff;
230 }
231
232 static int rbmp_shiftsigned(int v, int shift, int bits)
233 {
234    int result;
235    int z = bits;
236
237    if (shift < 0)
238       v <<= -shift;
239    else
240       v >>= shift;
241
242    result = v;
243
244    while (z < 8)
245    {
246       result += v >> z;
247       z      += bits;
248    }
249    return result;
250 }
251
252 static unsigned char *rbmp_bmp_load(rbmp_context *s, unsigned *x, unsigned *y,
253       int *comp, int req_comp)
254 {
255    unsigned char *out;
256    int bpp, flip_vertically, pad, target, offset, hsz;
257    int psize=0,i,j,width;
258    unsigned int mr=0,mg=0,mb=0,ma=0;
259
260    /* Corrupt BMP? */
261    if (rbmp_get8(s) != 'B' || rbmp_get8(s) != 'M')
262       return 0;
263
264    /* discard filesize */
265    rbmp_get16le(s);
266    rbmp_get16le(s);
267    /* discard reserved */
268    rbmp_get16le(s);
269    rbmp_get16le(s);
270
271    offset = (uint32_t)RBMP_GET32LE(s);
272    hsz    = (uint32_t)RBMP_GET32LE(s);
273
274    /* BMP type not supported? */
275    if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124)
276       return 0;
277
278    if (hsz == 12)
279    {
280       s->img_x = rbmp_get16le(s);
281       s->img_y = rbmp_get16le(s);
282    }
283    else
284    {
285       s->img_x = (uint32_t)RBMP_GET32LE(s);
286       s->img_y = (uint32_t)RBMP_GET32LE(s);
287    }
288
289    /* Bad BMP? */
290    if (rbmp_get16le(s) != 1)
291       return 0;
292
293    bpp = rbmp_get16le(s);
294
295    /* BMP 1-bit type not supported? */
296    if (bpp == 1)
297       return 0;
298
299    flip_vertically = ((int) s->img_y) > 0;
300    s->img_y        = abs((int) s->img_y);
301
302    if (hsz == 12)
303    {
304       if (bpp < 24)
305          psize = (offset - 14 - 24) / 3;
306    }
307    else
308    {
309       int compress = (uint32_t)RBMP_GET32LE(s);
310
311       /* BMP RLE type not supported? */
312       if (compress == 1 || compress == 2)
313          return 0;
314
315       /* discard sizeof */
316       rbmp_get16le(s);
317       rbmp_get16le(s);
318       /* discard hres */
319       rbmp_get16le(s);
320       rbmp_get16le(s);
321       /* discard vres */
322       rbmp_get16le(s);
323       rbmp_get16le(s);
324       /* discard colors used */
325       rbmp_get16le(s);
326       rbmp_get16le(s);
327       /* discard max important */
328       rbmp_get16le(s);
329       rbmp_get16le(s);
330
331       if (hsz == 40 || hsz == 56)
332       {
333          if (hsz == 56)
334          {
335             rbmp_get16le(s);
336             rbmp_get16le(s);
337             rbmp_get16le(s);
338             rbmp_get16le(s);
339             rbmp_get16le(s);
340             rbmp_get16le(s);
341             rbmp_get16le(s);
342             rbmp_get16le(s);
343          }
344          if (bpp == 16 || bpp == 32)
345          {
346             switch (compress)
347             {
348                case 0:
349 #if 0
350                   if (bpp == 32)
351                   {
352                      mr = 0xffu << 16;
353                      mg = 0xffu <<  8;
354                      mb = 0xffu <<  0;
355                      ma = 0xffu << 24;
356                   }
357                   else
358                   {
359                      mr = 31u << 10;
360                      mg = 31u <<  5;
361                      mb = 31u <<  0;
362                   }
363 #endif
364                   break;
365                case 3:
366                   mr = (uint32_t)RBMP_GET32LE(s);
367                   mg = (uint32_t)RBMP_GET32LE(s);
368                   mb = (uint32_t)RBMP_GET32LE(s);
369                   /* not documented, but generated by
370                    * Photoshop and handled by MS Paint */
371                   /* Bad BMP ?*/
372                   if (mr == mg && mg == mb)
373                      return 0;
374                   break;
375                default:
376 #if 0
377                   mr = mg = mb = 0;
378 #endif
379                   break;
380             }
381
382             /* Bad BMP? */
383             return 0;
384          }
385       }
386       else
387       {
388          mr = (uint32_t)RBMP_GET32LE(s);
389          mg = (uint32_t)RBMP_GET32LE(s);
390          mb = (uint32_t)RBMP_GET32LE(s);
391          ma = (uint32_t)RBMP_GET32LE(s);
392          /* Discard color space */
393          rbmp_get16le(s);
394          rbmp_get16le(s);
395          for (i = 0; i < 12; ++i)
396          {
397             /* Discard color space parameters */
398             rbmp_get16le(s);
399             rbmp_get16le(s);
400          }
401          if (hsz == 124)
402          {
403             /* Discard rendering intent */
404             rbmp_get16le(s);
405             rbmp_get16le(s);
406             /* Discard offset of profile data */
407             rbmp_get16le(s);
408             rbmp_get16le(s);
409             /* Discard size of profile data */
410             rbmp_get16le(s);
411             rbmp_get16le(s);
412             /* Discard reserved */
413             rbmp_get16le(s);
414             rbmp_get16le(s);
415          }
416       }
417       if (bpp < 16)
418          psize = (offset - 14 - hsz) >> 2;
419    }
420    s->img_n = ma ? 4 : 3;
421    if (req_comp && req_comp >= 3) /* We can directly decode 3 or 4 */
422       target = req_comp;
423    else
424       target = s->img_n; /* If they want monochrome, we'll post-convert */
425
426    out = (unsigned char *) malloc(target * s->img_x * s->img_y);
427
428    if (!out)
429       return 0;
430
431    if (bpp < 16)
432    {
433       unsigned char pal[256][4];
434       int z=0;
435
436       /* Corrupt BMP? */
437       if (psize == 0 || psize > 256)
438       {
439          free(out);
440          return 0;
441       }
442
443       for (i = 0; i < psize; ++i)
444       {
445          pal[i][2] = rbmp_get8(s);
446          pal[i][1] = rbmp_get8(s);
447          pal[i][0] = rbmp_get8(s);
448          if (hsz != 12)
449             rbmp_get8(s);
450          pal[i][3] = 255;
451       }
452
453       rbmp_skip(s, offset - 14 - hsz - psize * (hsz == 12 ? 3 : 4));
454       if (bpp == 4)
455          width = (s->img_x + 1) >> 1;
456       else if (bpp == 8)
457          width = s->img_x;
458       else
459       {
460          /* Corrupt BMP */
461          free(out);
462          return 0;
463       }
464
465       pad = (-width)&3;
466       for (j=0; j < (int) s->img_y; ++j)
467       {
468          for (i = 0; i < (int) s->img_x; i += 2)
469          {
470             int v  = rbmp_get8(s);
471             int v2 = 0;
472             if (bpp == 4)
473             {
474                v2  = v & 15;
475                v >>= 4;
476             }
477             out[z++] = pal[v][0];
478             out[z++] = pal[v][1];
479             out[z++] = pal[v][2];
480             if (target == 4)
481                out[z++] = 255;
482
483             if (i+1 == (int)s->img_x)
484                break;
485
486             v        = (bpp == 8) ? rbmp_get8(s) : v2;
487             out[z++] = pal[v][0];
488             out[z++] = pal[v][1];
489             out[z++] = pal[v][2];
490
491             if (target == 4)
492                out[z++] = 255;
493          }
494          rbmp_skip(s, pad);
495       }
496    }
497    else
498    {
499       int rshift = 0;
500       int gshift = 0;
501       int bshift = 0;
502       int ashift = 0;
503       int rcount = 0;
504       int gcount = 0;
505       int bcount = 0;
506       int acount = 0;
507       int z      = 0;
508       int easy   = 0;
509
510       rbmp_skip(s, offset - 14 - hsz);
511
512       if (bpp == 24)
513          width = 3 * s->img_x;
514       else if (bpp == 16)
515          width = 2*s->img_x;
516       else /* bpp = 32 and pad = 0 */
517          width=0;
518
519       pad = (-width) & 3;
520
521       switch (bpp)
522       {
523          case 24:
524             easy = 1;
525             break;
526          case 32:
527             if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000)
528                easy = 2;
529             break;
530          default:
531             break;
532       }
533
534       if (!easy)
535       {
536          /* Corrupt BMP? */
537          if (!mr || !mg || !mb)
538          {
539             free(out);
540             return 0;
541          }
542
543          /* right shift amt to put high bit in position #7 */
544          rshift = rbmp_high_bit(mr)-7;
545          rcount = rbmp_bitcount(mr);
546          gshift = rbmp_high_bit(mg)-7;
547          gcount = rbmp_bitcount(mg);
548          bshift = rbmp_high_bit(mb)-7;
549          bcount = rbmp_bitcount(mb);
550          ashift = rbmp_high_bit(ma)-7;
551          acount = rbmp_bitcount(ma);
552       }
553
554       for (j=0; j < (int) s->img_y; ++j)
555       {
556          if (easy)
557          {
558             if (target == 4)
559             {
560                /* Need to apply alpha channel as well */
561                if (easy == 2)
562                {
563                   for (i = 0; i < (int) s->img_x; ++i)
564                   {
565                      out[z+2]        = rbmp_get8(s);
566                      out[z+1]        = rbmp_get8(s);
567                      out[z+0]        = rbmp_get8(s);
568                      z              += 3;
569                      out[z++]        = rbmp_get8(s);
570                   }
571                }
572                else
573                {
574                   for (i = 0; i < (int) s->img_x; ++i)
575                   {
576                      out[z+2]        = rbmp_get8(s);
577                      out[z+1]        = rbmp_get8(s);
578                      out[z+0]        = rbmp_get8(s);
579                      z              += 3;
580                      out[z++]        = 255;
581                   }
582                }
583             }
584             else
585             {
586                for (i = 0; i < (int) s->img_x; ++i)
587                {
588                   out[z+2]        = rbmp_get8(s);
589                   out[z+1]        = rbmp_get8(s);
590                   out[z+0]        = rbmp_get8(s);
591                   z              += 3;
592                }
593             }
594          }
595          else
596          {
597             if (target == 4)
598             {
599                /* Need to apply alpha channel as well */
600                if (ma)
601                {
602                   if (bpp == 16)
603                   {
604                      for (i = 0; i < (int) s->img_x; ++i)
605                      {
606                         uint32_t v  = (uint32_t)rbmp_get16le(s);
607                         out[z++]    = RBMP_BYTECAST(rbmp_shiftsigned(v & mr, rshift, rcount));
608                         out[z++]    = RBMP_BYTECAST(rbmp_shiftsigned(v & mg, gshift, gcount));
609                         out[z++]    = RBMP_BYTECAST(rbmp_shiftsigned(v & mb, bshift, bcount));
610                         out[z++]    = RBMP_BYTECAST(rbmp_shiftsigned(v & ma, ashift, acount));
611                      }
612                   }
613                   else
614                   {
615                      for (i = 0; i < (int) s->img_x; ++i)
616                      {
617                         uint32_t v  = (uint32_t)RBMP_GET32LE(s);
618                         out[z++]    = RBMP_BYTECAST(rbmp_shiftsigned(v & mr, rshift, rcount));
619                         out[z++]    = RBMP_BYTECAST(rbmp_shiftsigned(v & mg, gshift, gcount));
620                         out[z++]    = RBMP_BYTECAST(rbmp_shiftsigned(v & mb, bshift, bcount));
621                         out[z++]    = RBMP_BYTECAST(rbmp_shiftsigned(v & ma, ashift, acount));
622                      }
623                   }
624                }
625                else
626                {
627                   if (bpp == 16)
628                   {
629                      for (i = 0; i < (int) s->img_x; ++i)
630                      {
631                         uint32_t v  = (uint32_t)rbmp_get16le(s);
632                         out[z++]    = RBMP_BYTECAST(rbmp_shiftsigned(v & mr, rshift, rcount));
633                         out[z++]    = RBMP_BYTECAST(rbmp_shiftsigned(v & mg, gshift, gcount));
634                         out[z++]    = RBMP_BYTECAST(rbmp_shiftsigned(v & mb, bshift, bcount));
635                         out[z++]    = RBMP_BYTECAST(255);
636                      }
637                   }
638                   else
639                   {
640                      for (i = 0; i < (int) s->img_x; ++i)
641                      {
642                         uint32_t v  = (uint32_t)RBMP_GET32LE(s);
643                         out[z++]    = RBMP_BYTECAST(rbmp_shiftsigned(v & mr, rshift, rcount));
644                         out[z++]    = RBMP_BYTECAST(rbmp_shiftsigned(v & mg, gshift, gcount));
645                         out[z++]    = RBMP_BYTECAST(rbmp_shiftsigned(v & mb, bshift, bcount));
646                         out[z++]    = RBMP_BYTECAST(255);
647                      }
648                   }
649                }
650             }
651             else
652             {
653                if (bpp == 16)
654                {
655                   for (i = 0; i < (int) s->img_x; ++i)
656                   {
657                      uint32_t v  = (uint32_t)rbmp_get16le(s);
658                      out[z++]    = RBMP_BYTECAST(rbmp_shiftsigned(v & mr, rshift, rcount));
659                      out[z++]    = RBMP_BYTECAST(rbmp_shiftsigned(v & mg, gshift, gcount));
660                      out[z++]    = RBMP_BYTECAST(rbmp_shiftsigned(v & mb, bshift, bcount));
661                   }
662                }
663                else
664                {
665                   for (i = 0; i < (int) s->img_x; ++i)
666                   {
667                      uint32_t v  = (uint32_t)RBMP_GET32LE(s);
668                      out[z++]    = RBMP_BYTECAST(rbmp_shiftsigned(v & mr, rshift, rcount));
669                      out[z++]    = RBMP_BYTECAST(rbmp_shiftsigned(v & mg, gshift, gcount));
670                      out[z++]    = RBMP_BYTECAST(rbmp_shiftsigned(v & mb, bshift, bcount));
671                   }
672                }
673             }
674          }
675          rbmp_skip(s, pad);
676       }
677    }
678
679    if (flip_vertically)
680    {
681       unsigned char t;
682       for (j=0; j < (int) s->img_y>>1; ++j)
683       {
684          unsigned char *p1 = out +      j     *s->img_x*target;
685          unsigned char *p2 = out + (s->img_y-1-j)*s->img_x*target;
686          for (i = 0; i < (int) s->img_x*target; ++i)
687          {
688             t     = p1[i];
689             p1[i] = p2[i];
690             p2[i] = t;
691          }
692       }
693    }
694
695    if (
696             req_comp
697          && (req_comp >= 1 && req_comp <= 4)
698          && (req_comp != target))
699    {
700       unsigned char *tmp = rbmp_convert_format(out, target, req_comp, s->img_x, s->img_y);
701
702       free(out);
703       out = NULL;
704
705       if (!tmp)
706          return NULL;
707
708       out = tmp;
709    }
710
711    *x = s->img_x;
712    *y = s->img_y;
713
714    if (comp)
715       *comp = s->img_n;
716
717    return out;
718 }
719
720 static unsigned char *rbmp_load_from_memory(unsigned char const *buffer, int len,
721       unsigned *x, unsigned *y, int *comp, int req_comp)
722 {
723    rbmp_context s;
724
725    s.img_buffer          = (unsigned char*)buffer;
726    s.img_buffer_original = (unsigned char*)buffer;
727    s.img_buffer_end      = (unsigned char*)buffer+len;
728
729    return rbmp_bmp_load(&s,x,y,comp,req_comp);
730 }
731
732 static void rbmp_convert_frame(uint32_t *frame, unsigned width, unsigned height)
733 {
734    uint32_t *end = frame + (width * height * sizeof(uint32_t))/4;
735
736    while (frame < end)
737    {
738       uint32_t pixel = *frame;
739       *frame = (pixel & 0xff00ff00) | ((pixel << 16) & 0x00ff0000) | ((pixel >> 16) & 0xff);
740       frame++;
741    }
742 }
743
744 int rbmp_process_image(rbmp_t *rbmp, void **buf_data,
745       size_t size, unsigned *width, unsigned *height)
746 {
747    int comp;
748
749    if (!rbmp)
750       return IMAGE_PROCESS_ERROR;
751
752    rbmp->output_image   = (uint32_t*)rbmp_load_from_memory(rbmp->buff_data,
753                            (int)size, width, height, &comp, 4);
754    *buf_data             = rbmp->output_image;
755
756    rbmp_convert_frame(rbmp->output_image, *width, *height);
757
758    return IMAGE_PROCESS_END;
759 }
760
761 bool rbmp_set_buf_ptr(rbmp_t *rbmp, void *data)
762 {
763    if (!rbmp)
764       return false;
765
766    rbmp->buff_data = (uint8_t*)data;
767
768    return true;
769 }
770
771 void rbmp_free(rbmp_t *rbmp)
772 {
773    if (!rbmp)
774       return;
775
776    free(rbmp);
777 }
778
779 rbmp_t *rbmp_alloc(void)
780 {
781    rbmp_t *rbmp = (rbmp_t*)calloc(1, sizeof(*rbmp));
782    if (!rbmp)
783       return NULL;
784    return rbmp;
785 }