Berkeley DB 与内存数据的映射

Table of Contents

1 绪论

在把内存数据写入到 Berkeley DB 时,需要解决内存数据如何映射到 Berkeley DB 的问题,尤其是对于一些比较复杂的数据结构,如何高效写入是一门值得深入研究的学问。

下面就以 OpenCV 的 IplImage 为例,探讨一下我对这一问题的解决思路。

2 把 OpenCV IplImage 写入 Berkeley DB

在存储 IplImage 数据的时候,需要注意以下几点:

  1. IplImage 本身是一个结构体,需要把这个结构体一股脑地存储到 DB 里;
  2. IplImage 结构体里,还包含了一个指向 char* 类型的 IplImage::imageData 指针,这个指针指向的数据,也需要存储到数据库里,才有可能把 IplImage 的数据保存下来。

可以采用下面的解决办法,流程图如下图所示:

./images/BerkeleyDB-IplImage.png

详细的解释如下:

  1. 把 IplImage 及其 IplImage::imageData 数据,拷贝到一个内存块里,然后再把这个内存块保存到 DB 里;
/**
 * 把 IplImage 数据导出为方便写入 Berkeley DB 的数据
 * @param img, IplImage 图像指针
 * @param my_data, 存储即将写入 Berkeley DB 的数据
 * @author WaterLin1999@gmail.com
 * @date  2011年9月1日
 */
void DumpIplImageToData(const IplImage* img, img_struct& my_data)
{
    const int IplSize = sizeof(IplImage);
    const int imgSize = img->imageSize;
    const int ROISize = sizeof( _IplROI);
    
    int size  = IplSize + imgSize;
    char* temp = new char[size];//分配一个临时存储区
    my_data.data = temp;
    my_data.size = size;

    //复制 IplImage 数据
    memcpy(temp,img,IplSize);
    temp = temp + IplSize;//指针跳转

    //复制 IplImage::imageData 数据
    memcpy(temp,img->imageData,imgSize);
}
  1. 读取数据时,先从 DB 里把这个数据块读到内存里,然后再把这个内存块的数据,强制拷贝及转化为 IplImage 及 IplImage::imageData 数据,代码如下:
/**
 * 把读出的 Berkeley DB 数据转为 IplImage* 数据
 * @param data, 从 Berkeley DB 读出来的数据
 * @param size, 从 Berkeley DB 读出来的数据大小
 * @author WaterLin1999@gmail.com
 * @date  2011年9月1日
 */
IplImage* DumpDataToIplImage(const void* data, int size)
{
    char* imgData  = new char[size];//存储解析出来的 IplImage 数据

    //导出 IplImage 结构体数据
    const int IplSize = sizeof(IplImage);
    const char* IplSrc  = (char*)data;
    memcpy(imgData,IplSrc,IplSize);
    IplImage* img = (IplImage*)imgData;
    
    char* temp = imgData;
    temp += IplSize;

    //导出 IplImage::imageData 数据
    const int imgSize = img->imageSize;
    const char* imgSrc = IplSrc + IplSize;
    memcpy(temp,imgSrc,img->imageSize);
    img->imageData = temp;
    img->imageDataOrigin = temp;

    //需要采用这种方法来重新生成一个图像,否则在外面用 cvReleaseImage 会导致程序中断
    IplImage* result = cvCloneImage(img);
    delete [] imgData;

    return result;
}

通过以上两个步骤,就可以完美地完成 IplImage 与 Berkeley DB 的写入与读取操作。

Author: Water Lin <WaterLin.org@gmail.com>

Date: 2011-09-08 14:17:02

HTML generated by org-mode 6.33x in emacs 23