20 void BmpInitializeBuffer(
BmpBuffer *buffer, FILE *file)
 
   25   buffer->real_pos = ftell(file);
 
   28 static inline void AdvanceBuffer(
BmpBuffer *buffer)
 
   30   if (buffer->read < 0) 
return;
 
   32   buffer->read = (int)fread(buffer->data, 1, BMP_BUFFER_SIZE, buffer->file);
 
   36 static inline bool EndOfBuffer(
BmpBuffer *buffer)
 
   38   if (buffer->read < 0) 
return false;
 
   40   if (buffer->pos == buffer->read || buffer->pos < 0) AdvanceBuffer(buffer);
 
   41   return buffer->pos == buffer->read;
 
   44 static inline byte ReadByte(
BmpBuffer *buffer)
 
   46   if (buffer->read < 0) 
return 0;
 
   48   if (buffer->pos == buffer->read || buffer->pos < 0) AdvanceBuffer(buffer);
 
   50   return buffer->data[buffer->pos++];
 
   53 static inline uint16 ReadWord(
BmpBuffer *buffer)
 
   55   uint16 var = ReadByte(buffer);
 
   56   return var | (ReadByte(buffer) << 8);
 
   59 static inline uint32 ReadDword(
BmpBuffer *buffer)
 
   61   uint32 var = ReadWord(buffer);
 
   62   return var | (ReadWord(buffer) << 16);
 
   65 static inline void SkipBytes(
BmpBuffer *buffer, 
int bytes)
 
   68   for (i = 0; i < bytes; i++) ReadByte(buffer);
 
   71 static inline void SetStreamOffset(
BmpBuffer *buffer, 
int offset)
 
   73   if (fseek(buffer->file, offset, SEEK_SET) < 0) {
 
   77   buffer->real_pos = offset;
 
   78   AdvanceBuffer(buffer);
 
   88   byte pad = 
GB(4 - info->
width / 8, 0, 2);
 
   91   for (y = info->
height; y > 0; y--) {
 
   93     pixel_row = &data->bitmap[(y - 1) * info->
width];
 
   94     while (x < info->width) {
 
   95       if (EndOfBuffer(buffer)) 
return false; 
 
   97       for (i = 8; i > 0; i--) {
 
   98         if (x < info->width) *pixel_row++ = 
GB(b, i - 1, 1);
 
  103     SkipBytes(buffer, pad);
 
  115   byte pad = 
GB(4 - info->
width / 2, 0, 2);
 
  118   for (y = info->
height; y > 0; y--) {
 
  120     pixel_row = &data->bitmap[(y - 1) * info->
width];
 
  121     while (x < info->width) {
 
  122       if (EndOfBuffer(buffer)) 
return false;  
 
  123       b = ReadByte(buffer);
 
  124       *pixel_row++ = 
GB(b, 4, 4);
 
  126       if (x < info->width) {
 
  127         *pixel_row++ = 
GB(b, 0, 4);
 
  132     SkipBytes(buffer, pad);
 
  144   uint y = info->
height - 1;
 
  145   byte *pixel = &data->bitmap[y * info->
width];
 
  146   while (y != 0 || x < info->width) {
 
  147     if (EndOfBuffer(buffer)) 
return false; 
 
  149     byte n = ReadByte(buffer);
 
  150     byte c = ReadByte(buffer);
 
  155           if (y == 0) 
return false;
 
  156           pixel = &data->bitmap[--y * info->
width];
 
  163           if (EndOfBuffer(buffer)) 
return false;
 
  164           byte dx = ReadByte(buffer);
 
  165           byte dy = ReadByte(buffer);
 
  168           if (x + dx >= info->
width || x + dx < x || dy > y) 
return false;
 
  172           pixel = &data->bitmap[y * info->
width + x];
 
  179             if (EndOfBuffer(buffer) || x >= info->
width) 
return false;
 
  180             byte b = ReadByte(buffer);
 
  181             *pixel++ = 
GB(b, 4, 4);
 
  184               if (x >= info->
width) 
return false;
 
  185               *pixel++ = 
GB(b, 0, 4);
 
  190           SkipBytes(buffer, ((c + 1) / 2) % 2);
 
  199       while (x < info->width && i++ < n) {
 
  200         *pixel++ = 
GB(c, 4, 4);
 
  202         if (x < info->width && i++ < n) {
 
  203           *pixel++ = 
GB(c, 0, 4);
 
  219   byte pad = 
GB(4 - info->
width, 0, 2);
 
  221   for (y = info->
height; y > 0; y--) {
 
  222     if (EndOfBuffer(buffer)) 
return false; 
 
  223     pixel = &data->bitmap[(y - 1) * info->
width];
 
  224     for (i = 0; i < info->
width; i++) *pixel++ = ReadByte(buffer);
 
  226     SkipBytes(buffer, pad);
 
  237   uint y = info->
height - 1;
 
  238   byte *pixel = &data->bitmap[y * info->
width];
 
  239   while (y != 0 || x < info->width) {
 
  240     if (EndOfBuffer(buffer)) 
return false; 
 
  242     byte n = ReadByte(buffer);
 
  243     byte c = ReadByte(buffer);
 
  248           if (y == 0) 
return false;
 
  249           pixel = &data->bitmap[--y * info->
width];
 
  256           if (EndOfBuffer(buffer)) 
return false;
 
  257           byte dx = ReadByte(buffer);
 
  258           byte dy = ReadByte(buffer);
 
  261           if (x + dx >= info->
width || x + dx < x || dy > y) 
return false;
 
  265           pixel = &data->bitmap[y * info->
width + x];
 
  270           for (uint i = 0; i < c; i++) {
 
  271             if (EndOfBuffer(buffer) || x >= info->
width) 
return false;
 
  272             *pixel++ = ReadByte(buffer);
 
  276           SkipBytes(buffer, c % 2);
 
  284       for (uint i = 0; x < info->
width && i < n; i++) {
 
  299   byte pad = 
GB(4 - info->
width * 3, 0, 2);
 
  301   for (y = info->
height; y > 0; y--) {
 
  302     pixel_row = &data->bitmap[(y - 1) * info->
width * 3];
 
  303     for (x = 0; x < info->
width; x++) {
 
  304       if (EndOfBuffer(buffer)) 
return false; 
 
  305       *(pixel_row + 2) = ReadByte(buffer); 
 
  306       *(pixel_row + 1) = ReadByte(buffer); 
 
  307       *pixel_row       = ReadByte(buffer); 
 
  311     SkipBytes(buffer, pad);
 
  322   assert(info != NULL);
 
  326   if (ReadWord(buffer) != 0x4D42) 
return false; 
 
  327   SkipBytes(buffer, 8); 
 
  328   info->
offset = ReadDword(buffer);
 
  331   header_size = ReadDword(buffer);
 
  332   if (header_size < 12) 
return false; 
 
  334   info->
os2_bmp = (header_size == 12); 
 
  337     info->
width = ReadWord(buffer);
 
  338     info->
height = ReadWord(buffer);
 
  341     info->
width = ReadDword(buffer);
 
  342     info->
height = ReadDword(buffer);
 
  346   if (ReadWord(buffer) != 1) 
return false; 
 
  348   info->
bpp = ReadWord(buffer);
 
  349   if (info->
bpp != 1 && info->
bpp != 4 && info->
bpp != 8 && info->
bpp != 24) {
 
  355   if ((header_size -= 4) >= 4) {
 
  363   if (info->
bpp <= 8) {
 
  367     if (header_size >= 16) {
 
  368       SkipBytes(buffer, 12);                  
 
  370       SkipBytes(buffer, header_size - 16);    
 
  377       data->palette[i].b = ReadByte(buffer);
 
  378       data->palette[i].g = ReadByte(buffer);
 
  379       data->palette[i].r = ReadByte(buffer);
 
  380       if (!info->
os2_bmp) SkipBytes(buffer, 1); 
 
  384   return buffer->real_pos <= info->
offset;
 
  393   assert(info != NULL && data != NULL);
 
  395   data->bitmap = CallocT<byte>(info->
width * info->
height * ((info->
bpp == 24) ? 3 : 1));
 
  398   SetStreamOffset(buffer, info->
offset);
 
  402     case 1:  
return BmpRead1(buffer, info, data);
 
  403     case 4:  
return BmpRead4(buffer, info, data);
 
  404     case 8:  
return BmpRead8(buffer, info, data);
 
  405     case 24: 
return BmpRead24(buffer, info, data);
 
  406     default: NOT_REACHED();
 
  410   default: NOT_REACHED();
 
  414 void BmpDestroyData(
BmpData *data)
 
  416   assert(data != NULL);