OpenCV中文网站

 找回密码
 立即注册
搜索
热搜: 安装 配置
查看: 6180|回复: 5

EmCV增加efs_cvSaveImage函数

[复制链接]
发表于 2008-7-4 10:35:20 | 显示全部楼层 |阅读模式
未了兼容OpenCV,同时也方便调试,EmCV提供cvSaveImage函数。
cvSaveImage函数可以将IplImage图像保存到磁盘上,目前只支持BMP格式。

在DM642的网络包中,还抽象了一种嵌入式文件系统(Embedded File System)。
所有的文件都是RAM中分配空间,但是文件的操作和普通文件类似,例如efs_fopen/efs_fread等。

每个函数都以efs_为前缀,宏以EFS_为前缀,具体的定义可以查看<osif.h>文件。

EmCV目前新增加了efs_cvSaveImage函数,除了数据是保存在RAM中,其他属性和cvSaveImage类似。
具体的代码如下:
  1. #ifdef DM64X_NETWORK
  2. #include <netmain.h>
  3. // save as Embedded file
  4. CV_IMPL int
  5. efs_cvSaveImage( const char* filename, const IplImage * image )
  6. {
  7.     int channels;
  8.     EFS_FILE * p;
  9.     BmpFileHead bmpfilehead;
  10.     BmpInfoHead bmpinfohead;
  11.     RGBA rgba;
  12.     int step, modbytes, idx;
  13.        
  14.     int imageLength;
  15.     char *pData;
  16.     CV_FUNCNAME( &quot;cvSaveImageEfs&quot; );
  17.     __BEGIN__;
  18.     channels = image->nChannels;
  19.     if( channels != 3 && channels != 1)
  20.         CV_ERROR( CV_BadNumChannels, &quot;Only 1 or 3-channel image is supported&quot; );
  21.     if( !filename || strlen(filename) == 0 ||
  22.             strlen(filename) >= EFS_FILENAME_MAX)
  23.     {
  24.         CV_ERROR( CV_StsNullPtr, &quot;null filename&quot; );
  25.     }
  26.         
  27.     //
  28.    
  29.     modbytes = (image->width*channels)%4;
  30.     step = modbytes ? ((image->width*channels)-modbytes+4)  : (image->width*channels);
  31.        
  32.     // image size
  33.    
  34.     imageLength = 0;
  35.     {
  36.             // header
  37.            
  38.             imageLength += sizeof(BmpFileHead);
  39.             imageLength += sizeof(BmpInfoHead);
  40.    
  41.             // color table
  42.         if(channels==1)
  43.         {
  44.             imageLength += sizeof(RGBA)*256;
  45.         }
  46.         // data
  47.                
  48.         imageLength += step*image->height;
  49.     }
  50.    
  51.     // alloc memory
  52.    
  53.     pData = (char*)cvAlloc(imageLength);
  54.    
  55.     // create embedded file
  56.    
  57.     efs_createfilecb((char*)filename, imageLength, (UINT8*)pData,
  58.                              (EFSFUN)cvFree_, (UINT32)pData );
  59.         
  60.     // open file
  61.     p = efs_fopen((char*)filename, &quot;wb&quot;);
  62.     if(!p)
  63.         CV_ERROR( CV_StsNullPtr, &quot;Can not create file&quot; );
  64.        
  65.     //bmpfilehead = (BmpFileHead *)cvAlloc(sizeof(BmpFileHead));
  66.     //bmpinfohead = (BmpInfoHead *)cvAlloc(sizeof(BmpInfoHead));
  67.        
  68.     memset(&bmpfilehead, 0, sizeof(BmpFileHead));
  69.     memset(&bmpinfohead, 0, sizeof(BmpInfoHead));
  70.     memset(&rgba, 0, sizeof(RGBA));
  71.        
  72.     bmpfilehead.type1='B';
  73.     bmpfilehead.type2='M';
  74.        
  75.     bmpinfohead.imageSize = ( 2+sizeof(BmpInfoHead)+image->height*step );
  76.     bmpinfohead.startPosition = (channels==3) ? (2+sizeof(BmpInfoHead)) : (2+sizeof(BmpInfoHead)+1024);
  77.     bmpinfohead.length = 40;
  78.     bmpinfohead.width = (image->width);
  79.     bmpinfohead.height = (image->height);
  80.     bmpinfohead.colorPlane = (1);
  81.     bmpinfohead.bitColor = (channels==3) ?(24) : 8;
  82.     bmpinfohead.realSize = (image->height*step);
  83.     //write header
  84.     efs_fwrite(&bmpfilehead, sizeof(BmpFileHead), 1, p);
  85.     efs_fwrite(&bmpinfohead, sizeof(BmpInfoHead), 1, p);
  86.     //write
  87.     if(channels==1)
  88.     {
  89.         for(idx =0; idx<256; idx++)
  90.         {
  91.             rgba.R=idx;
  92.             rgba.G=idx;
  93.             rgba.B=idx;
  94.             rgba.A = 0;
  95.             efs_fwrite(&rgba, sizeof(RGBA), 1, p);
  96.         }
  97.     }
  98.        
  99.     for(idx = image->height-1; idx >=0 ; idx--)
  100.         efs_fwrite(image->imageData+image->widthStep*idx, step, 1, p);
  101.        
  102.     efs_fclose(p);
  103.     __END__;
  104.    
  105.     return 0;
  106. }
  107. #endif        // DM64X_NETWORK
复制代码

由于efs函数要依赖<netmain.h>文件,应此默认是没有被编译的。
如果要编译该函数,需要包含网络相关的库,同时定义DM64X_NETWORK宏。
回复

使用道具 举报

发表于 2008-7-4 10:56:25 | 显示全部楼层

EmCV增加efs_cvSaveImage函数

已经将efs_cvSaveImage添加到svn中
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-7-4 15:57:14 | 显示全部楼层

EmCV增加efs_cvSaveImage函数

刚发现efs不支持efs_fwrite,ti的文章说明如下:

This function writes to the indicated stream from the array ptr, up to nobj objects of a
length specified by size. It returns the number of objects written; this may be less than
the number of objects requested on an error. It is functionally equivalent to fwrite().

Nothing in the stack package requires write capability, thus this function always returns
zero.


查看对应的代码(ti\\c6000\\ndk\\src\\os\\efs.c):
  1. //--------------------------------------------------------------------
  2. // efs_fopen
  3. //
  4. // Opens a file and returns file pointer (or NULL on error)
  5. //--------------------------------------------------------------------
  6. EFS_FILE *efs_fopen( char *name, char *mode )
  7. {
  8.     FILEHEADER *pfh;
  9.     FILEPTR    *pf;
  10.     // Verify the read mode
  11.     if( stricmp( mode, &quot;rb&quot; ) )
  12.         return(0);
  13.     ...
  14. }
  15. //--------------------------------------------------------------------
  16. // efs_fwrite
  17. //
  18. // Returns zero - we don\'t write
  19. //--------------------------------------------------------------------
  20. size_t efs_fwrite( void *ptr, size_t size, size_t nobj, EFS_FILE *stream )
  21. {
  22.     (void)ptr;
  23.     (void)size;
  24.     (void)nobj;
  25.     (void)stream;
  26.     return(0);
  27. }
复制代码

efs_fopen只支持&quot;rb&quot;读打开,efs_fwrite也没有任何实现。不过efs_fwrite是一个必要的函数。
因此,我自己尝试写一个类似的函数(如果要改写efs_fwrite的话,要重新编译库,比较麻烦)。
  1. int efs_fwrite_(void *ptr, int size, int nobj, EFS_FILE *stream, void *pData)
  2. {
  3.     int canread;
  4.    
  5.     // Check for null operation
  6.     if( size <= 0 || nobj <= 0 || !ptr || !pData)
  7.         return(0);
  8.     // Get number of bytes we can read
  9.     canread = efs_getfilesize(stream) - efs_ftell(stream);
  10.     // Get number of objects we can read
  11.     canread /= size;
  12.     // Check for max user request
  13.     if( canread > nobj ) canread = nobj;
  14.     // Copy what we can
  15.    
  16.     if( canread )
  17.     {
  18.         memcpy(pData+efs_ftell(stream), ptr, (size_t)canread*size);
  19.     }
  20.     // Bump file position
  21.     efs_fseek(stream, canread*(INT32)size, EFS_SEEK_CUR)
  22.     // return what we read
  23.     return( (size_t)canread * size );
  24. }
复制代码

参数void *pData对应文件的内存地址,可以通过efs_loadfunction函数获取。
回复 支持 反对

使用道具 举报

发表于 2008-7-4 16:30:59 | 显示全部楼层

EmCV增加efs_cvSaveImage函数

是一个复杂的过程啊

另外我问下 在cvCanny()中有这段代码:
if( icvCannyGetSize_p && icvCanny_16s8u_C1R_p && !(flags & CV_CANNY_L2_GRADIENT) )
    {
        int buf_size=  0;
        IPPI_CALL( icvCannyGetSize_p( size, &buf_size ));
        CV_CALL( buffer = cvAlloc( buf_size ));
        IPPI_CALL( icvCanny_16s8u_C1R_p( (short*)dx->data.ptr, dx->step,
                                     (short*)dy->data.ptr, dy->step,
                                     dst->data.ptr, dst->step,
                                     size, (float)low_thresh,
                                     (float)high_thresh, buffer ));
        EXIT;
    }

其中  IPPI_CALL( icvCanny_16s8u_C1R_p( (short*)dx->data.ptr, dx->step,
                                     (short*)dy->data.ptr, dy->step,
                                     dst->data.ptr, dst->step,
                                     size, (float)low_thresh,
                                     (float)high_thresh, buffer ));

是函数调用吗?怎么调用的?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-7-4 16:38:18 | 显示全部楼层

EmCV增加efs_cvSaveImage函数

修改后的efs_cvSaveImage:
  1. CV_IMPL int
  2. efs_cvSaveImage( const char* filename, const IplImage * image )
  3. {
  4.         int channels;
  5.         EFS_FILE * p;
  6.         BmpFileHead bmpfilehead;
  7.         BmpInfoHead bmpinfohead;
  8.         RGBA rgba;
  9.         int step, modbytes, idx;
  10.        
  11.         int imageLength;
  12.         char *pData;
  13.         CV_FUNCNAME( &quot;efs_cvSaveImage&quot; );
  14.     __BEGIN__;
  15.     channels = image->nChannels;
  16.     if( channels != 3 && channels != 1)
  17.         CV_ERROR( CV_BadNumChannels, &quot;Only 1 or 3-channel image is supported&quot; );
  18.     if( !filename || strlen(filename) == 0 ||
  19.             strlen(filename) >= EFS_FILENAME_MAX)
  20.     {
  21.         CV_ERROR( CV_StsNullPtr, &quot;null filename&quot; );
  22.     }
  23.         
  24.     //
  25.    
  26.         modbytes = (image->width*channels)%4;
  27.         step = modbytes ? ((image->width*channels)-modbytes+4)  : (image->width*channels);
  28.        
  29.     // image size
  30.    
  31.     imageLength = 0;
  32.     {
  33.             // header
  34.            
  35.             imageLength += sizeof(BmpFileHead);
  36.             imageLength += sizeof(BmpInfoHead);
  37.    
  38.             // color table
  39.                 if(channels==1)
  40.                 {
  41.                         imageLength += sizeof(RGBA)*256;
  42.                 }
  43.                
  44.                 // data
  45.                
  46.                 imageLength += step*image->height;
  47.     }
  48.    
  49.     // alloc memory
  50.    
  51.     pData = (char*)cvAlloc(imageLength);
  52.    
  53.     // create embedded file
  54.    
  55.     efs_createfilecb((char*)filename, imageLength, (UINT8*)pData,
  56.                                      (EFSFUN)cvFree_, (UINT32)pData );
  57.    
  58.         // open file (&quot;rb&quot;)
  59.         p = efs_fopen((char*)filename, &quot;rb&quot;);
  60.         if(!p)
  61.                 CV_ERROR( CV_StsNullPtr, &quot;Can not create file&quot; );
  62.        
  63.         //bmpfilehead = (BmpFileHead *)cvAlloc(sizeof(BmpFileHead));
  64.         //bmpinfohead = (BmpInfoHead *)cvAlloc(sizeof(BmpInfoHead));
  65.        
  66.         memset(&bmpfilehead, 0, sizeof(BmpFileHead));
  67.         memset(&bmpinfohead, 0, sizeof(BmpInfoHead));
  68.         memset(&rgba, 0, sizeof(RGBA));
  69.        
  70.         bmpfilehead.type1=\'B\';
  71.         bmpfilehead.type2=\'M\';
  72.        
  73.         bmpinfohead.imageSize = ( 2+sizeof(BmpInfoHead)+image->height*step );
  74.         bmpinfohead.startPosition = (channels==3) ? (2+sizeof(BmpInfoHead)) : (2+sizeof(BmpInfoHead)+1024);
  75.         bmpinfohead.length = 40;
  76.         bmpinfohead.width = (image->width);
  77.         bmpinfohead.height = (image->height);
  78.         bmpinfohead.colorPlane = (1);
  79.         bmpinfohead.bitColor = (channels==3) ?(24) : 8;
  80.         bmpinfohead.realSize = (image->height*step);
  81.         //write header
  82.         efs_fwrite_(&bmpfilehead, sizeof(BmpFileHead), 1, p, pData);
  83.         efs_fwrite_(&bmpinfohead, sizeof(BmpInfoHead), 1, p, pData);
  84.         //write
  85.         if(channels==1)
  86.         {
  87.                 for(idx =0; idx<256; idx++)
  88.                 {
  89.                         rgba.R=idx;
  90.                         rgba.G=idx;
  91.                         rgba.B=idx;
  92.                         rgba.A = 0;
  93.                         efs_fwrite_(&rgba, sizeof(RGBA), 1, p, pData);
  94.                 }
  95.         }
  96.        
  97.         for(idx = image->height-1; idx >=0 ; idx--)
  98.                 efs_fwrite_(image->imageData+image->widthStep*idx, step, 1, p, pData);
  99.        
  100.         efs_fclose(p);
  101.     __END__;
  102.    
  103.     return 0;
  104. }
复制代码

文件的打开方式依然为&quot;rb&quot;, 但是用efs_fwrite_代替efs_fwrite来写文件。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-7-4 17:54:48 | 显示全部楼层

EmCV增加efs_cvSaveImage函数

ti 提供的efs可以看作是一个文件堆栈,是一个单层目录结构,后创建的文件在堆栈的顶部。

其中efs_createfile在创建文件时有一个问题。如果已经存在重名的文件,那么原来的文件
依然存在,新创建的文件在栈的顶部。

efs_fopen和efs_destroyfile在查找文件的时候都是从栈顶开始,找到文件就返回。
因此,访问的文件是靠近栈顶的那个(如有有重名的文件将不能访问)。

现在对efs_cvSaveImage进行改进,如果图像已经存在,则覆盖原来的图像内容。
如果图像不存在,则重新创建,避免出现多个同名的文件同时存在于文件堆栈中。
  1. CV_IMPL int
  2. efs_cvSaveImage( const char* filename, const IplImage * image )
  3. {
  4.         int channels;
  5.         EFS_FILE * p;
  6.         BmpFileHead bmpfilehead;
  7.         BmpInfoHead bmpinfohead;
  8.         RGBA rgba;
  9.         int step, modbytes, idx;
  10.        
  11.         int imageLength;
  12.         char *pData;
  13.         CV_FUNCNAME( &quot;efs_cvSaveImage&quot; );
  14.     __BEGIN__;
  15.     channels = image->nChannels;
  16.     if( channels != 3 && channels != 1)
  17.         CV_ERROR( CV_BadNumChannels, &quot;Only 1 or 3-channel image is supported&quot; );
  18.     if( !filename || strlen(filename) == 0 ||
  19.             strlen(filename) >= EFS_FILENAME_MAX)
  20.     {
  21.         CV_ERROR( CV_StsNullPtr, &quot;null filename&quot; );
  22.     }
  23.         
  24.     //
  25.    
  26.         modbytes = (image->width*channels)%4;
  27.         step = modbytes ? ((image->width*channels)-modbytes+4)  : (image->width*channels);
  28.        
  29.     // image size
  30.    
  31.     imageLength = 0;
  32.     {
  33.             // header
  34.            
  35.             imageLength += sizeof(BmpFileHead);
  36.             imageLength += sizeof(BmpInfoHead);
  37.    
  38.             // color table
  39.                 if(channels==1)
  40.                 {
  41.                         imageLength += sizeof(RGBA)*256;
  42.                 }
  43.                
  44.                 // data
  45.                
  46.                 imageLength += step*image->height;
  47.     }
  48.    
  49.     // try open file
  50.    
  51.     p = efs_fopen((char*)filename, &quot;rb&quot;);
  52.    
  53.     if(p)
  54.     {
  55.             if(efs_getfilesize(p) != imageLength)
  56.             {
  57.                     // destroy file
  58.                    
  59.                     efs_fclose(p);
  60.                     efs_destroyfile((char*)filename);
  61.            
  62.                         // create a new file
  63.    
  64.                     pData = (char*)cvAlloc(imageLength);
  65.                     efs_createfilecb((char*)filename, imageLength, (UINT8*)pData,
  66.                                                       (EFSFUN)cvFree_, (UINT32)pData );
  67.                                                       
  68.                     // open file again
  69.                    
  70.                     p = efs_fopen((char*)filename, &quot;rb&quot;);
  71.             }
  72.     }
  73.     else
  74.     {
  75.                 // create a new file
  76.    
  77.             pData = (char*)cvAlloc(imageLength);
  78.             efs_createfilecb((char*)filename, imageLength, (UINT8*)pData,
  79.                                               (EFSFUN)cvFree_, (UINT32)pData );
  80.            
  81.             // open file again
  82.                    
  83.             p = efs_fopen((char*)filename, &quot;rb&quot;);
  84.     }
  85.    
  86.         if(!p)
  87.                 CV_ERROR( CV_StsNullPtr, &quot;Can not create file&quot; );
  88.     // data point
  89.    
  90.     pData = (char*)efs_loadfunction((char*)filename);
  91.        
  92.         //bmpfilehead = (BmpFileHead *)cvAlloc(sizeof(BmpFileHead));
  93.         //bmpinfohead = (BmpInfoHead *)cvAlloc(sizeof(BmpInfoHead));
  94.        
  95.         memset(&bmpfilehead, 0, sizeof(BmpFileHead));
  96.         memset(&bmpinfohead, 0, sizeof(BmpInfoHead));
  97.         memset(&rgba, 0, sizeof(RGBA));
  98.        
  99.         bmpfilehead.type1=\'B\';
  100.         bmpfilehead.type2=\'M\';
  101.        
  102.         bmpinfohead.imageSize = ( 2+sizeof(BmpInfoHead)+image->height*step );
  103.         bmpinfohead.startPosition = (channels==3) ? (2+sizeof(BmpInfoHead)) : (2+sizeof(BmpInfoHead)+1024);
  104.         bmpinfohead.length = 40;
  105.         bmpinfohead.width = (image->width);
  106.         bmpinfohead.height = (image->height);
  107.         bmpinfohead.colorPlane = (1);
  108.         bmpinfohead.bitColor = (channels==3) ?(24) : 8;
  109.         bmpinfohead.realSize = (image->height*step);
  110.         //write header
  111.         efs_fwrite_(&bmpfilehead, sizeof(BmpFileHead), 1, p, pData);
  112.         efs_fwrite_(&bmpinfohead, sizeof(BmpInfoHead), 1, p, pData);
  113.         //write
  114.         if(channels==1)
  115.         {
  116.                 for(idx =0; idx<256; idx++)
  117.                 {
  118.                         rgba.R=idx;
  119.                         rgba.G=idx;
  120.                         rgba.B=idx;
  121.                         rgba.A = 0;
  122.                         efs_fwrite_(&rgba, sizeof(RGBA), 1, p, pData);
  123.                 }
  124.         }
  125.        
  126.         for(idx = image->height-1; idx >=0 ; idx--)
  127.                 efs_fwrite_(image->imageData+image->widthStep*idx, step, 1, p, pData);
  128.        
  129.         efs_fclose(p);
  130.     __END__;
  131.    
  132.     return 0;
  133. }
复制代码
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|OpenCV中文网站

GMT+8, 2024-4-19 20:41 , Processed in 0.009574 second(s), 15 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表