回 帖 发 新 帖 刷新版面

主题:[原创]做了一个动态连接库(DLL),读取JPEG图像文件(附件已上传)

上次在网上看到IJG,是一个用C语言写的、跨平台的、操作JPEG的开源函数库。但是这个库比较庞大,编译后有数百k。对于普通的应用来说,通常只希望读取JPEG图象,而不会保存JPEG图象,因此很多功能也用不上。
最近我把IJG封装了一下,做成了自己的DLL,现在发出来给大家分享。提供了两种风格的接口,C语言可以直接调用函数接口,C++则推荐使用封装后的类。大家看看这个封装是否合理?希望各位能提出好的建议[em2]。

头文件、编译好的DLL和LIB文件在附件里,另外还附带了测试图片和测试用的源代码(利用OpenGL的glDrawPixels把像素绘制到屏幕上)。

单独头文件贴出,其中有大量注释,就是对各函数、类的说明了。(因字数限制,分为两部分)


[code=c]#ifndef _jpeg_H_
#define _jpeg_H_

#ifdef __cplusplus
extern "C" {
#endif



//+===========================================================================+
//|                                                                           |
//| C风格的函数接口                                                           |
//|                                                                           |
//+===========================================================================+



// enum tagErrorCode
//
// 错误代码
typedef enum tagErrorCode{
    EC_NO_ERROR = 0,    // 正常
    EC_UNKNOWN_ERROR,   // 未知错误
    EC_OUT_OF_MEMORY,   // 内存不足
    EC_BAD_ALIGN,       // 错误的字节对齐数
    EC_BAD_FILE,        // 文件打开失败
    EC_BAD_FORCE_X,     // 强制设定宽度引起的失败
    EC_BAD_FORCE_Y      // 强制设定高度引起的失败
} ErrorCode;



// enum tagJpegImageStatusName
//
// 状态名称
typedef enum tagJpegImageStatusName {
    JISN_RESERVED = 0,      // 零是保留的名字
    JISN_LAST_ERROR,        // 错误代码,为零表示没有错误
    JISN_ALIGN_BYTES,       // 按字节对齐(1表示不对齐)
    JISN_IS_BUTTON_TO_TOP,  // 像素垂直保存方向(非零表示从上到下)
    JISN_FORCE_X,           // 强制指定的宽度(零表示不强制指定)
    JISN_FORCE_Y            // 强制指定的高度(零表示不强制指定)
} JpegImageStatusName;



// struct JpegImage
//
// 保存JPEG数据
typedef struct tagJpegImage {
    int         sizeX;              // 图象宽度(水平方向像素数量)
    int         sizeY;              // 图象高度(垂直方向像素数量)
    int         components;         // 图象的颜色分量数,例如:
                                    // RGB有红、绿、蓝三个分量
                                    // RGBA有红、绿、蓝、alpha四个分量
    int         bytesInLine;        // 每行像素数据所占的字节数
                                    // 这个值至少是sizeX * components,但是可能更多
                                    // 参见JpegImage_SetAlign函数
    int         isButtonToTop;      // 像素的垂直保存方式
                                    // 参见JpegImage_SetButtonToTop函数
    const void* bytes;              // 指向像素数据的指针
} JpegImage;



// function JpegImage_GetLastError
//
// 获得最后一次的出错信息
// 如果JpegImage_LoadXXX系列函数没有成功的读取到JPEG图象,则会设置一个错误信息
// 通过本函数可以获得该错误信息的描述文本
//
// 参数:没有
// 返回:一个错误信息文本
//
// 说明:文本数据放在静态存储区,不要调用free或delete来释放
//
const char* JpegImage_GetLastError();



// function JpegImage_SetAlignBytes
//
// 设置字节对齐
// 比如某图象宽度为30,使用RGB格式,因此一行像素总共需要30*3=90字节,
//   但是如果设置为四字节对齐,则一行像素使用92字节(92是4的倍数),
//   最后两字节闲置不使用
// 例如将JPEG转化为BMP,BMP要求四字节对齐,这里设置字节对齐后不必另行编写代码
// 注意本函数只能设置为单字节、双字节、四字节、八字节对齐
// 若设置为单字节对齐,实际上与不使用字节对齐是等效的
//
// 参数:int alignBytes -- 对齐的字节数,必须是1, 2, 4, 8这四者之一
// 返回:若成功返回非零值,若失败返回零
//       如果返回零,可以使用JpegImage_GetLastError取得错误信息
//
// 说明:如果没有使用本函数设置字节对齐,则默认为四字节对齐
//
int         JpegImage_SetAlignBytes(int alignBytes);



// function JpegImage_SetButtonToTop
//
// 设置像素的垂直保存方式
// 有两种保存方式可供选择
//   从上到下的保存,
//     首先保存最上一行像素,然后依次往下,直到最下一行
//   从下到上的保存,
//     首先保存最下一行像素,然后依次往上,直到最上一行
//
// 参数:int isButtonToTop -- 如果为非零值,表示从下到上的保存
//                            否则表示从上到下的保存
// 返回:没有
//
// 说明:如果没有使用本函数设置垂直保存方式,则默认为从上到下的保存
//       无论哪种方式,每一行像素都是从左到右保存的
//
void        JpegImage_SetButtonToTop(int isButtonToTop);



// function JpegImage_SetForceSize
//
// 强制性的设定JPEG图象的大小
// 如果JPEG文件头中没有包含正确的高度、宽度信息,则可以使用本函数强制设定
//
// 参数:int forceX -- 强制性的设定图象宽度
//                     如果这个值为零或者负数,则表示不强制性的设定
//       int forceY -- 强制性的设定图象高度
//                     如果这个值为零或者负数,则表示不强制性的设定
//
// 说明:某些情况下,多个JPEG图象共用一个文件头,只是文件体不同
//       (参见暴雪公司游戏《魔兽争霸3》中的BLP文件格式)
// 如果这些JPEG图象本身的大小是各不相同的,文件头无法一一指定各自的大小
// 此时可以通过本函数强制设定
//
// 注意:为了确保不出现运行时错误(Runtime Error),规定
//       当强制性设定的大小大于图象本身的大小时,读取直接失败,
//       而不是妄图读取大量的数据,导致下标越界
//
void        JpegImage_SetForceSize(int forceX, int forceY);



// function JpegImage_LoadFromFile
//
// 从文件读取一幅JPEG图象
//
// 参数:const char* filename -- 文件的名字
// 返回:若读取成功,返回图象数据的指针
//         当图象数据不再需要时,可以通过JpegImage_Unload函数销毁图象数据
//       若读取失败,返回NULL指针
//         此时可以使用JpegImage_GetLastError取得错误信息
//
JpegImage*  JpegImage_LoadFromFile(const char* filename);



// function JpegImage_LoadFromMemory
//
// 从内存中读取一幅JPEG图象
//
// 参数:const void* data -- 指向JPEG数据的指针
//       size_t      size -- JPEG数据的长度(按字节计算)
// 返回:若读取成功,返回图象数据的指针
//         当图象数据不再需要时,可以通过JpegImage_Unload函数销毁图象数据
//       若读取失败,返回NULL指针
//         此时可以使用JpegImage_GetLastError取得错误信息
//
// 说明:如果是从网络或其它位置获得JPEG数据,而不是从文件获得,则可以使用本函数
//
// 本函数相当于
// JpegImage_LoadFromMemorySegment(1, &data, &size);
// 参见JpegImage_LoadFromMemorySegment
//
JpegImage*  JpegImage_LoadFromMemory(const void* data, size_t size);



// function JpegImage_LoadFromMemorySegment
//
// 从内存中读取一幅JPEG图象
// 其中JPEG图象的数据并不是连续存放,而是被分为多段
//
// 参数:size_t      iSegments   -- 数据的段数
//       const void* segmentData -- 一个数组
//                                  数组的第i个元素是指向第i段数据的指针
//       size_t      segmentSize -- 一个数组
//                                  数组的第i个元素是第i段数据的长度
// 返回:若读取成功,返回图象数据的指针
//         当图象数据不再需要时,可以通过JpegImage_Unload函数销毁图象数据
//       若读取失败,返回NULL指针
//         此时可以使用JpegImage_GetLastError取得错误信息
//
// 说明:某些情况下,多个JPEG图象共用一个文件头,只是文件体不同
//       (参见暴雪公司游戏《魔兽争霸3》中的BLP文件格式)
//       这时一个JPEG图象被分为文件头和文件体两段,可以使用本函数来读取
// 例如:pHeader, iHeaderSize, pBody, iBodySize分别表示了
//         指向文件头数据的指针、文件头数据长度、
//         指向文件体数据的指针、文件体数据长度
//       则以下代码可以读取这个JPEG图象
//       const void* segmentData[] = {pHeader, pBody};
//       const size_t segmentSize[] = {iHeaderSize, iBodySize};
//       JpegImage* pJpegImage = JpegImage_LoadFromMemorySegment(
//           2, segmentData, segmentSize);
//
JpegImage*  JpegImage_LoadFromMemorySegment(
                    size_t iSegments,
                    const void* segmentData[],
                    const size_t size[]);



// function JpegImage_Unload
//
// 销毁JPEG图象数据
//
// 参数:JpegImage* pJpegImage -- 指向JPEG图象数据的指针
// 返回:没有
//
// 说明:仅当JPEG图象数据不再使用时,才应该进行销毁
//       销毁后的图象数据不再能使用
void        JpegImage_Unload(JpegImage* pJpegImage);



// function JpegImage_GetStatusInteger
//
// 查询当前的状态
//
// 参数:JpegImageStatusName statusName -- 要取得的状态的名字
// 返回:指定的状态的值
//       如果指定的不是一个状态,则默认返回0
//
int         JpegImage_GetStatusInteger(JpegImageStatusName statusName);[/code]

回复列表 (共11个回复)

11 楼

谢谢分享,学习了

我来回复

您尚未登录,请登录后再回复。点此登录或注册