⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 openbmp.cpp

📁 这个刚才那个的源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    memset(pixels, 0, h.width * h.height);

    // we read the image from the bottom down, and then flip it when
    // we're done
    int x = 0;
    int y = 0;

    const byte* in = raster_data;
    while (in - raster_data < h.image_size - 1) {
      byte n = *in++;
      byte c = *in++;

      if (n == 0) {  // escape code

        if (c == 0) {         // end of line
          x = 0;

          //++y;  // XXXaegis uhhh...  uhhh...  :)  it works this way...

          if (y >= h.height) {
            // did we go too far?
            break;
          }
        } else if (c == 1) {  // end of bitmap
          break;
        } else if (c == 2) {  // delta

          // do we have enough space?
          if (in - raster_data >= h.image_size - 1) {
            break;
          }

          // I have no idea how I'm supposed to do this...
          // Let's take a guess!
          int dx = *in++;
          int dy = *in++;
          x = (x + dx) % h.width;
          y += dy + (x + dx) / h.width;
          if (y >= h.height) {
            // if we went too far, stop now
            break;
          }

        } else {              // read uncompressed

          // the input raster data is padded on DWORD boundaries
          // c == num_pixels
          int num_bytes = (c + 3) / 4 * 2;
          
          // make sure we have enough space
          if (in - raster_data > h.image_size - num_bytes) {
            break;
          }

          // nasty decoding loop...
          int i = 0;
          int j = 0;
          while (true) {
            byte l = (in[j] & 0xF0) >> 4;
            byte r = (in[j] & 0x0F);
            ++j;

            pixels[y * h.width + x] = l;
            if (!advance(x, y, h) || ++i >= c) {
              break;
            }

            pixels[y * h.width + x] = r;
            if (!advance(x, y, h) || ++i >= c) {
              break;
            }
          }
          // make SURE we move forward the right number of bytes
          in += num_bytes;
        }

      } else {

        // a less nasty decoding loop...
        byte lc = (c & 0xF0) >> 4;
        byte rc = c & 0x0F;

        int i = 0;
        while (true) {
          pixels[y * h.width + x] = lc;
          if (!advance(x, y, h) || ++i >= n) {
            break;
          }

          pixels[y * h.width + x] = rc;
          if (!advance(x, y, h) || ++i >= n) {
            break;
          }
        }

      } // end if
    } // end while

    // flippy flippy!
    int pitch = h.width;
    auto_array<byte> row(new byte[pitch]);
    for (int i = 0; i < h.height / 2; ++i) {
      int j = h.height - i - 1;
      memcpy((byte*)row,         pixels + i * pitch, pitch);
      memcpy(pixels + i * pitch, pixels + j * pitch, pitch);
      memcpy(pixels + j * pitch, (byte*)row,         pitch);
    }

    return new SimpleImage(h.width, h.height, PF_I8, pixels.release(),
                           (byte*)palette.release(), 256, PF_B8G8R8);
  }

  Image* ReadBitmap8(const byte* raster_data, const Header& h) {
    auto_array<byte> pixels(new byte[h.width * h.height]);
    
    auto_array<BGR> palette(new BGR[256]);
    memset(palette, 0, 256 * sizeof(BGR));
    memcpy(palette, h.palette, h.palette_size * sizeof(BGR));

    for (int i = 0; i < h.height; ++i) {
      const byte* in = raster_data + i * h.pitch;
      byte* out = pixels + (h.height - i - 1) * h.width;

      for (int j = 0; j < h.width; ++j) {
        *out++ = *in++;
      }
    }

    return new SimpleImage(h.width, h.height, PF_I8, pixels.release(),
                           (byte*)palette.release(), 256, PF_B8G8R8);
  }

  Image* ReadBitmapRLE8(const byte* raster_data, const Header& h) {
    auto_array<byte> pixels(new byte[h.width * h.height]);
    
    auto_array<BGR> palette(new BGR[256]);
    memset(palette, 0, 256 * sizeof(BGR));
    memcpy(palette, h.palette, h.palette_size * sizeof(BGR));

    // by default, we have an empty bitmap
    memset(pixels, 0, h.width * h.height);

    // we read the image from the bottom down, and then flip it when
    // we're done
    int x = 0;
    int y = 0;

    const byte* in = raster_data;
    while (in - raster_data < h.image_size - 1) {
      byte n = *in++;
      byte c = *in++;

      if (n == 0) {  // escape code

        if (c == 0) {         // end of line
          x = 0;

          //++y;  // XXXaegis uhhh...  uhhh...  :)  it works this way...

          if (y >= h.height) {
            // did we go too far?
            break;
          }
        } else if (c == 1) {  // end of bitmap
          break;
        } else if (c == 2) {  // delta

          // do we have enough space?
          if (in - raster_data >= h.image_size - 1) {
            break;
          }

          // I have no idea how I'm supposed to do this...
          // Let's take a guess!
          int dx = *in++;
          int dy = *in++;
          x = (x + dx) % h.width;
          y += dy + (x + dx) / h.width;
          if (y >= h.height) {
            // if we went too far, stop now
            break;
          }

        } else {              // read uncompressed

          // c == num_pixels
          int num_bytes = (c + 1) / 2 * 2;
          
          // make sure we have enough space
          if (in - raster_data > h.image_size - num_bytes) {
            break;
          }

          // decoding loop...
          int i = 0;
          int j = 0;
          while (true) {
            pixels[y * h.width + x] = in[j++];
            if (!advance(x, y, h) || ++i >= c) {
              break;
            }
          }
          // make SURE we move forward the right number of bytes
          in += num_bytes;
        }

      } else {

        int i = 0;
        while (true) {
          pixels[y * h.width + x] = c;
          if (!advance(x, y, h) || ++i >= n) {
            break;
          }
        }

      } // end if
    } // end while

    // flippy flippy!
    int pitch = h.width;
    auto_array<byte> row(new byte[pitch]);
    for (int i = 0; i < h.height / 2; ++i) {
      int j = h.height - i - 1;
      memcpy((byte*)row,         pixels + i * pitch, pitch);
      memcpy(pixels + i * pitch, pixels + j * pitch, pitch);
      memcpy(pixels + j * pitch, (byte*)row,         pitch);
    }

    return new SimpleImage(h.width, h.height, PF_I8, pixels.release(),
                           (byte*)palette.release(), 256, PF_B8G8R8);
  }
  
  Image* ReadBitmap16(const byte* raster_data, const Header& h) {
    auto_array<RGB> pixels(new RGB[h.width * h.height]);

    for (int i = 0; i < h.height; ++i) {
      const byte* in = raster_data + i * h.pitch;
      RGB* out = pixels + (h.height - i - 1) * h.width;

      for (int j = 0; j < h.width; ++j) {
        int clr = read16_le(in);
        in += 2;

#define C16(C) \
  (byte)( ((clr & h.bf_##C##_mask) >> h.bf_##C##_shift) << h.bf_##C##_rshift);

        out->red   = C16(red);
        out->green = C16(green);
        out->blue  = C16(blue);
        ++out;

#undef C16
      }
    }

    return new SimpleImage(h.width, h.height, PF_R8G8B8,
                           (byte*)pixels.release());
  }

  Image* ReadBitmap24(const byte* raster_data, const Header& h) {
    auto_array<BGR> pixels(new BGR[h.width * h.height]);

    for (int i = 0; i < h.height; ++i) {
      const byte* in = raster_data + i * h.pitch;
      BGR* out = pixels + (h.height - i - 1) * h.width;

      for (int j = 0; j < h.width; ++j) {
        out->blue  = *in++;
        out->green = *in++;
        out->red   = *in++;
        ++out;
      }
    }

    return new SimpleImage(h.width, h.height, PF_B8G8R8,
                           (byte*)pixels.release());
  }

  Image* ReadBitmap32(const byte* raster_data, const Header& h) {
    auto_array<RGB> pixels(new RGB[h.width * h.height]);

    for (int i = 0; i < h.height; ++i) {
      const byte* in = raster_data + i * h.pitch;
      RGB* out = pixels + (h.height - i - 1) * h.width;

      for (int j = 0; j < h.width; ++j) {
        u32 pixel = read32_le(in);
        in += 4;
        out->red   = (byte)((pixel & h.bf_red_mask)   >> h.bf_red_shift);
        out->green = (byte)((pixel & h.bf_green_mask) >> h.bf_green_shift);
        out->blue  = (byte)((pixel & h.bf_blue_mask)  >> h.bf_blue_shift);
        ++out;
      }
    }

    return new SimpleImage(h.width, h.height, PF_R8G8B8,
                           (byte*)pixels.release());
  }

  Image* DecodeBitmap(File* file, const Header& h) {

    if (!file->seek(h.data_offset, File::BEGIN)) {
      return 0;
    }

    // the raster data stored in the file
    auto_array<byte> raster_data(new byte[h.image_size]);
    if (file->read(raster_data, h.image_size) != h.image_size) {
      return 0;
    }

    // the output pixel buffer (parameter to new SimpleImage)
    auto_array<byte> pixels(new byte[h.width * h.height * 3]);

    typedef Image* (*Decoder)(const byte* raster_data, const Header& h);

    Decoder decoder = 0;

    if      (h.bpp == 1  &&  h.compression == 0)  { decoder = ReadBitmap1;    }
    else if (h.bpp == 4  &&  h.compression == 0)  { decoder = ReadBitmap4;    }
    else if (h.bpp == 4  &&  h.compression == 2)  { decoder = ReadBitmapRLE4; }
    else if (h.bpp == 8  &&  h.compression == 0)  { decoder = ReadBitmap8;    }
    else if (h.bpp == 8  &&  h.compression == 1)  { decoder = ReadBitmapRLE8; }
    else if (h.bpp == 16 && (h.compression == 0 ||
                             h.compression == 3)) { decoder = ReadBitmap16;   }
    else if (h.bpp == 24 &&  h.compression == 0)  { decoder = ReadBitmap24;   }
    else if (h.bpp == 32 && (h.compression == 0 ||
                             h.compression == 3)) { decoder = ReadBitmap32;   }

    if (decoder) {
      return decoder(raster_data.get(), h);
    } else {
      return 0;
    }
  }

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -