www.pudn.com > bp_cpp.zip > bmp.cpp
/* * public/bmp.c * 2004-01-13 by ShanLanshan */ #include#include #include #include #include static int align(int n, int a); namespace pub { /////////////////////////////////////////////////////////////////////// // class BmpFileHeader /////////////////////////////////////////////////////////////////////// const char *BmpFileHeader::M_BMPFILE_FLAG = "BM"; BmpFileHeader::BmpFileHeader() { memcpy(m_flag, M_BMPFILE_FLAG, M_BMPFILE_FLAG_LEN); m_size = 0; m_reserved = 0; m_off = 0; } BmpFileHeader::~BmpFileHeader() {} bool BmpFileHeader::check_valid() { if (memcmp(m_flag, M_BMPFILE_FLAG, M_BMPFILE_FLAG_LEN) != 0) return false; if (m_reserved != 0) return false; return true; } /////////////////////////////////////////////////////////////////////// // class BmpInfoHeader /////////////////////////////////////////////////////////////////////// BmpInfoHeader::BmpInfoHeader(int width, int height, short bitcount) { m_size = sizeof(*this); m_planes = 1; m_compression = 0; m_perlspermeterx = 0x0ec4; m_perlspermetery = 0x0ec4; m_color_used = 0; m_color_important = 0; set_info(width, height, bitcount); } BmpInfoHeader::~BmpInfoHeader(){} bool BmpInfoHeader::check_valid() { if (m_size != sizeof(*this)) return false; if (m_compression != 0) return false; if (m_bitcount != 1 && m_bitcount != 24) return false; return true; } void BmpInfoHeader::set_info(int width, int height, short bitcount) { m_width = width; m_height = height; m_bitcount = bitcount; m_imagesize = height * get_line_bytes(); } int BmpInfoHeader::get_line_bytes() { int line_bytes; line_bytes = m_width * m_bitcount; line_bytes = align(line_bytes, 32); line_bytes /= 8; return line_bytes; } /////////////////////////////////////////////////////////////////////// // class BmpPaletteSlot /////////////////////////////////////////////////////////////////////// BmpPaletteSlot::BmpPaletteSlot(unsigned char r, unsigned char g, unsigned char b) { set_rgb(r, g, b); } BmpPaletteSlot::~BmpPaletteSlot(){} void BmpPaletteSlot::set_rgb(unsigned char r, unsigned char g, unsigned char b) { m_red = r; m_green = g; m_blue = b; m_reserved = 0; } /////////////////////////////////////////////////////////////////////// // class BmpPalette /////////////////////////////////////////////////////////////////////// BmpPalette::BmpPalette() { m_slots = 0; m_palette_slot = NULL; } BmpPalette::~BmpPalette() { clear(); } void BmpPalette::clear() { if (m_palette_slot == NULL) return; delete[] m_palette_slot; m_palette_slot = NULL; } void BmpPalette::set_bit(int bit, const unsigned char *data /* = NULL */) { clear(); if (bit >= 24) { m_slots = 0; return; } m_slots = 1 << bit; m_palette_slot = new BmpPaletteSlot[m_slots]; if (bit == 1) { if (data == NULL) { m_palette_slot[0].set_rgb(0, 0, 0); m_palette_slot[1].set_rgb(0xff, 0xff, 0xff); } } if (data != NULL && bit < 24) memcpy(m_palette_slot, data, sizeof(BmpPaletteSlot) * m_slots); } unsigned char *BmpPalette::get_data() { return reinterpret_cast (m_palette_slot); } unsigned int BmpPalette::get_data_len() { return m_slots * sizeof(BmpPaletteSlot); } /////////////////////////////////////////////////////////////////////// // class Bitmap /////////////////////////////////////////////////////////////////////// Bitmap::Bitmap() { m_data = NULL; } Bitmap::~Bitmap() { if (m_data == NULL) return; delete[] m_data; m_data = NULL; } bool Bitmap::create(int w, int h, short bit) { m_infoheader.set_info(w, h, bit); m_line_bytes = m_infoheader.get_line_bytes(); m_palette.set_bit(bit); m_fileheader.m_off = sizeof(m_fileheader) + sizeof(m_infoheader) + m_palette.get_data_len(); m_fileheader.m_size = m_fileheader.m_off + m_infoheader.m_imagesize; m_data = new char[m_infoheader.m_imagesize]; if (m_data == NULL) return false; return true; } bool Bitmap::load_from_file(const char *filename) { FILE *fp; size_t reads; bool ret = false; fp = fopen(filename, "rb"); if (fp == NULL) return false; /* 读取位图文件头部 */ reads = fread(&m_fileheader, sizeof(m_fileheader), 1, fp); if (reads != 1) { goto lbl_ret; } if (!m_fileheader.check_valid()) { goto lbl_ret; } /* 读取位图文件信息部 */ reads = fread(&m_infoheader, sizeof(m_infoheader), 1, fp); if (reads != 1) { goto lbl_ret; } if (!m_infoheader.check_valid()) { goto lbl_ret; } /* 读取调色板 */ if (m_infoheader.m_bitcount < 24) { unsigned char buf[1024]; int len; len = sizeof(BmpPaletteSlot) * (1 << m_infoheader.m_bitcount); if (len > sizeof(buf)) goto lbl_ret; reads = fread(buf, 1, sizeof(buf), fp); if (reads != sizeof(buf)) goto lbl_ret; m_palette.set_bit(m_infoheader.m_bitcount, buf); } /* 读取图形数据 */ m_data = new char[m_infoheader.m_imagesize]; if (m_data == NULL) goto lbl_ret; reads = fread(m_data, 1, m_infoheader.m_imagesize, fp); if (reads != m_infoheader.m_imagesize) goto lbl_ret; /* 成功! */ m_line_bytes = m_infoheader.get_line_bytes(); ret = true; lbl_ret: fclose(fp); return ret; } bool Bitmap::save_to_file(const char *filename) { FILE *fp; bool ret = false; fp = fopen(filename, "wb"); if (fp == NULL) return false; /* 写位图文件头部 */ if (!m_fileheader.check_valid()) { goto lbl_ret; } if (fwrite(&m_fileheader, sizeof(m_fileheader), 1, fp) != 1) { goto lbl_ret; } /* 写取位图文件信息部 */ if (!m_infoheader.check_valid()) { goto lbl_ret; } if (fwrite(&m_infoheader, sizeof(m_infoheader), 1, fp) != 1) { goto lbl_ret; } /* 写调色板 */ if (m_infoheader.m_bitcount < 24) { if (fwrite(m_palette.get_data(), 1, m_palette.get_data_len(), fp) != m_palette.get_data_len()) goto lbl_ret; } /* 写取图形数据 */ if (m_data == NULL) goto lbl_ret; if (fwrite(m_data, 1, m_infoheader.m_imagesize, fp) != m_infoheader.m_imagesize) goto lbl_ret; /* 成功! */ ret = true; lbl_ret: fclose(fp); return ret; } unsigned long Bitmap::get_pixel(int x, int y, int ci) { unsigned long c, d[3]; c = get_pixel(x, y); if (get_bitcount() == 1) return c; assert(ci > 0 && ci < 4); if (ci == 3) { return sqrt(static_cast (d[0] * d[0] + d[1] * d[1] + d[2] * d[2])); } get_rgb(c, d, d + 1, d + 2); return d[ci]; } unsigned long Bitmap::get_pixel(int x, int y) { int bytex, bitx; unsigned long ret = 0; int bc, off; assert(x >= 0); assert(y >= 0); assert(x < get_width()); assert(y < get_height()); bc = get_bitcount(); bytex = bc * x; bitx = (7 - (bytex % 8)); bytex /= 8; off = m_line_bytes * y + bytex; if (bc == 24) { memcpy(&ret, m_data + off, 3); } else if (bc == 1) { ret = m_data[off]; ret >>= bitx; ret &= 0x00000001; } return ret; } void Bitmap::set_pixel(int x, int y, unsigned long c) { int bytex, bitx; int bc, off; assert(x >= 0); assert(y >= 0); assert(x < get_width()); assert(y < get_height()); bc = get_bitcount(); bytex = bc * x; bitx = (7 - (bytex % 8)); bytex /= 8; off = m_line_bytes * y + bytex; if (bc == 24) { memcpy(m_data + off, &c, 3); } else if (bc == 1) { m_data[off] &= ~(1< (&c); if (b != NULL) *b = p[2]; if (g != NULL) *g = p[1]; if (r != NULL) *r = p[0]; } extern unsigned long gen_rgb(unsigned long r, unsigned long g, unsigned long b) { unsigned long c; unsigned char *p; p = reinterpret_cast (&c); p[0] = r; p[1] = g; p[2] = b; p[3] = 0; return c; } } // namespace pub static int align(int n, int a) { if (n % a) { n -= n % a; n += a; } return n; }