OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3575|回复: 6

BMP直接编码,不通过显示屏截屏,保存的图片有问题

[复制链接]

2

主题

11

帖子

0

精华

初级会员

Rank: 2

积分
124
金钱
124
注册时间
2015-4-21
在线时间
23 小时
发表于 2016-1-3 19:57:04 | 显示全部楼层 |阅读模式
5金钱
本帖最后由 易星 于 2016-1-6 12:19 编辑

[size=10.5000pt]本人想要直接用摄像头的数据,进行bmp编码,不过最后保存的图片有问
               
[size=10.5000pt]图片上方显示的不对,显示的是下方的一部分,而且还分成两块,搞不清楚什么情况,求大神指教。

但是我用屏幕截屏的方法没有问题。
用的是OV7725,对比度没调好,只有英文的数据手册,没敢调,用的别人的配置,照片显示的不好。
部分程序如下:
int main(void)
{
        u8 buf = 0;
        u8 *p = &buf;
        u8 i = 0;
        u8 res, key;
        u8 *pname;        //带路径的文件名
        u16 *p_show;
        u8 sd_ok = 1;        //0,sd卡不正常;1,SD卡正常
        
        u32 j;
         u16 color;
        
        hardware_init();  //初始化
        
        LCD_Scan_Dir(DIR_DULR);                        //从下到上,从左到右,横屏显示
        LCD_Clear(BLUE2);
        LCD_SetColors(WHITE, GREEN);
        
//        while(font_init())        //检查字库
//                Show_StringChar(60, 50, (u8 *)"Font Error!",   2, 1);
        Show_StringChar(30, 0,  (u8 *)"Camera Test",      2, 1);
        res = f_mkdir("0:/PHOTO");        //创建PHOTO文件夹
        if((res != FR_EXIST) && (res != FR_OK))        //发生了错误
        {
                Show_StringChar(30, 40, (u8 *)"SD_Card Error", 2, 1);
                delay_ms(200);
                Show_StringChar(30, 60, (u8 *)"Camera Error", 2, 1);
                sd_ok = 0;
        }
        else
        {
                Show_StringChar(30, 40, (u8 *)"SD_Card OK", 2, 1);
                delay_ms(200);
                Show_StringChar(30, 60, (u8 *)"USERhotograph", 2, 1);
                sd_ok = 1;
        }
        pname = mymalloc(SRAMIN, 30);        //为带路径的文件名分配30个字节的内存
        while(pname == NULL)        //内存分配出错
         {
                Show_StringChar(30, 80, (u8 *)"Malloc Error!", 2, 1);
                delay_ms(200);
        }
        buf = OV7725_Init();
        while(buf)        //初始化OV7725
        {
                Show_StringChar(30, 80, (u8 *)"OV7725 Error!!", 2, 1);
                i = buf;
                sprintf((char*)p, "Error Code:%d", i);
                Show_StringChar(30, 100, p, 2, 1);
                delay_ms(200);
        }
        Show_StringChar(30, 80, (u8 *)"OV7725 OK", 2, 1);
        delay_ms(1000);
        LCD_Clear(BLACK);
        
        EXTI_Config(GPIO_C, 3, RISING);        //任意边沿触发
        NVIC_Init(2, 0, 0, EXTI3_IRQn);        //抢占0,子优先级0,组2
        LCD_Set_Window(0, 0, 320, 240);
        
        while(1)
        {
                key = Get_KeyState();
                if(key == Key_User)
                {
                        p_show = (u16*)mymalloc(SRAMEX, 190000);
                        while(p_show == NULL)        //内存分配出错
                        {
                                Show_StringChar(30, 0, (u8 *)"Malloc Error!", 2, 1);
                                delay_ms(200);
                        }
                        LCD_SetCursor(0x00, 0x0000);        //设置光标位置
                        LCD_WriteRAM_Prepare();                        //开始写入GRAM
                        if(ov_sta == 2)
                        {
                                FIFO_RRST_L();                //开始复位读指针
                                FIFO_RCLK_L();
                                FIFO_RCLK_H();
                                FIFO_RCLK_L();
                                FIFO_RRST_H();                //复位读指针结束
                                FIFO_RCLK_H();
                                for(j = 0; j < 76800; j ++)                //320*240
                                {
                                        FIFO_RCLK_L();
                                        color = GPIOC->IDR & 0XFF00;        //读数据
                                        FIFO_RCLK_H();
                                        FIFO_RCLK_L();
                                        color |= (GPIOC->IDR >> 8) & 0X00FF;        //读数据
                                        FIFO_RCLK_H();
                                        LCD->LCD_RAM = color;     //从这里显示的图片是正常的
                                        p_show[j] = color;
                                }
                                EXTI->R = 1 << 8;        //清除LINE8上的中断标志位
                                ov_sta = 0;                        //开始下一次采集
                                ov_frame ++;
                        }
                        delay_ms(1800);
                        delay_ms(1800);
                        LCD_Clear(BLACK);
                        if(sd_ok)
                        {
                                camera_new_pathname(pname);        //得到文件名
                                res = bmp_encode_direct(pname, p_show, 0, 0, 320, 240, 0);
                                if(res)        //拍照有误
                                {
                                        Show_StringChar(30, 20, (u8 *)"Write File Error", 2, 1);
                                        sprintf((char*)p, "Error Code:0X%x", res);
                                        Show_StringChar(30, 100, p, 2, 1);
                                }
                                else
                                {
                                        Show_StringChar(30, 20, (u8 *)"photograph succeed", 2, 1);
                                        sprintf((char*)p, "Save:%s", pname);
                                        Show_StringChar(30, 40, p, 2, 1);
                                        delay_ms(100);
                                 }
                        }
                        else //提示SD卡错误
                        {
                                Show_StringChar(30, 40, (u8 *)"SD_Card Error", 2, 1);
                                 Show_StringChar(30, 60, (u8 *)"Camera Error", 2, 1);
                         }
                        myfree(SRAMEX, p_show);
                }
                else
                        delay_ms(10);
                i ++;
                if(i >= 50)
                {
                        i = 0;
                        led1_negation();
                 }
        }
}


u8 bmp_encode_direct(u8 *filename, u16 *buf, u16 x, u16 y, u16 width, u16 height, u8 mode)
{
        FIL* f_bmp;
        u16 bmpheadsize;        //bmp头大小
         BITMAPINFO hbmp;        //bmp头
        u8 res = 0;
        u16 tx, ty;                        //图像尺寸
        u16 *databuf;                //数据缓存区地址
        u16 pixcnt;                        //像素计数器
        u16 bi4width;                //水平像素字节数
        if((width == 0) || (height == 0))
                return PIC_WINDOW_ERR;        //区域错误
        if((x + width - 1) > lcddev.width)
                return PIC_WINDOW_ERR;        //区域错误
        if((y + height - 1) > lcddev.height)
                return PIC_WINDOW_ERR;        //区域错误
        
#if BMP_USE_MALLOC == 1                //使用malloc
        databuf = (u16*)mymalloc(SRAMIN, 1024);                //开辟至少bi4width大小的字节的内存区域 ,对240宽的屏,480个字节就够了
        if(databuf == NULL)
                return PIC_MEM_ERR;        //内存申请失败.
        f_bmp = (FIL *)mymalloc(SRAMIN, sizeof(FIL));        //开辟FIL字节的内存区域
        if(f_bmp == NULL)                //内存申请失败
        {
                myfree(SRAMIN, databuf);
                return PIC_MEM_ERR;
        }
#else
        databuf = (u16*)bmpreadbuf;
        f_bmp = &f_bfile;
#endif
        bmpheadsize = sizeof(hbmp);                //得到bmp文件头的大小
        mymemset((u8*)&hbmp, 0, sizeof(hbmp));        //置零空申请到的内存
        hbmp.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);        //信息头大小
        hbmp.bmiHeader.biWidth = width;                 //bmp的宽度
        hbmp.bmiHeader.biHeight = height;         //bmp的高度
        hbmp.bmiHeader.biPlanes = 1;                //恒为1
        hbmp.bmiHeader.biBitCount = 16;                 //bmp为16位色bmp
        hbmp.bmiHeader.biCompression = BI_BITFIELDS;        //每个象素的比特由指定的掩码决定
         hbmp.bmiHeader.biSizeImage = ((hbmp.bmiHeader.biHeight * hbmp.bmiHeader.biWidth) * hbmp.bmiHeader.biBitCount) / 8;        //bmp数据区大小
        
        hbmp.bmfHeader.bfType = ((u16)'M' << 8)+ 'B';        //BM格式标志
        hbmp.bmfHeader.bfSize = bmpheadsize + hbmp.bmiHeader.biSizeImage;        //整个bmp的大小
           hbmp.bmfHeader.bfOffBits = bmpheadsize;        //到数据区的偏移
        
        hbmp.RGB_MASK[0] = 0X00F800;        //红色掩码
        hbmp.RGB_MASK[1] = 0X0007E0;        //绿色掩码
        hbmp.RGB_MASK[2] = 0X00001F;        //蓝色掩码
        
        if(mode == 1)
                res = f_open(f_bmp, (const TCHAR*)filename, FA_READ | FA_WRITE);        //尝试打开之前的文件
         if((mode == 0) || (res == 0x04))
                res = f_open(f_bmp, (const TCHAR*)filename, FA_WRITE | FA_CREATE_NEW);        //模式0,或者尝试打开失败,则创建新文件
         if((hbmp.bmiHeader.biWidth * 2) % 4)        //水平像素(字节)不为4的倍数
                bi4width = ((hbmp.bmiHeader.biWidth * 2) / 4 + 1) * 4;        //实际要写入的宽度像素,必须为4的倍数
        else
                bi4width = hbmp.bmiHeader.biWidth * 2;        //刚好为4的倍数
         if(res == FR_OK)        //创建成功
        {
                res = f_write(f_bmp, (u8*)&hbmp, bmpheadsize, &bw);        //写入BMP首部
                for(ty = y + height - 1; hbmp.bmiHeader.biHeight; ty--)
                {
                        pixcnt = 0;
                         for(tx = x; pixcnt != (bi4width / 2);)
                        {
                                if(pixcnt < hbmp.bmiHeader.biWidth)
                                {
                                        LCD_Fast_DrawPoint(tx, ty, buf[ty * 320 + tx]);     //这里显示的图片不正常,就是图片上显示的那种
                                        databuf[pixcnt] = buf[ty * 320 + tx];
                                }
                                else
                                        databuf[pixcnt] = 0Xffff;        //补充白色的像素
                                pixcnt ++;
                                tx ++;
                        }
                        LCD_ShowNum(0, 0, pixcnt, 2, 1);
                        hbmp.bmiHeader.biHeight --;
                        res = f_write(f_bmp, (u8*)databuf, bi4width, &bw);        //写入数据
                }
                f_close(f_bmp);
        }
#if BMP_USE_MALLOC == 1                //使用malloc
        myfree(SRAMIN, databuf);
        myfree(SRAMIN, f_bmp);
#endif
        return res;
}

其余的程序与原子哥的差不多

图片1.jpg
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2016-1-3 20:58:29 | 显示全部楼层
先完成直接编码屏幕的吧
回复

使用道具 举报

2

主题

11

帖子

0

精华

初级会员

Rank: 2

积分
124
金钱
124
注册时间
2015-4-21
在线时间
23 小时
 楼主| 发表于 2016-1-4 09:50:22 | 显示全部楼层
正点原子 发表于 2016-1-3 20:58
先完成直接编码屏幕的吧

直接编码屏幕的早弄好了
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2016-1-4 23:32:46 | 显示全部楼层
易星 发表于 2016-1-4 09:50
直接编码屏幕的早弄好了

那么问题可能出在你的数据写入上面,数据写入可能耗时超过摄像头的输出速度,导致这个情况.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

2

主题

11

帖子

0

精华

初级会员

Rank: 2

积分
124
金钱
124
注册时间
2015-4-21
在线时间
23 小时
 楼主| 发表于 2016-1-6 12:03:00 | 显示全部楼层
本帖最后由 易星 于 2016-1-6 12:04 编辑
正点原子 发表于 2016-1-4 23:32
那么问题可能出在你的数据写入上面,数据写入可能耗时超过摄像头的输出速度,导致这个情况.

不是,我试过,一边读数据一边显示没问题,写完数据之后再显示就有问题,显示的跟图片一样,应该是中间数据读取有问题。 因为需要150K内存,所以我是用的外部SRAM,数据读取在204行以内没有问题,之后显示正常,超出204行数据就被篡改了,后面的数据还在写入,前面的数据不知道为什么被改动了,导致显示出来的图片上边一部分是图片本来的下边的一部分。但是我SRAM留的余量够呀,为什么数据被篡改了,是不是因为用SRAM的原因啊。
实验的程序如下:
                        if(ov_sta == 2)
                        {
                                LCD_SetCursor(0x00, 0x0000);        //设置光标位置
                                LCD_WriteRAM_Prepare();                        //开始写入GRAM
                                FIFO_RRST_L();                //开始复位读指针
                                FIFO_RCLK_L();
                                FIFO_RCLK_H();
                                FIFO_RCLK_L();
                                FIFO_RRST_H();                //复位读指针结束
                                FIFO_RCLK_H();
                                for(j = 0; j < 76800; j ++)                //320*240
                                {
                                        FIFO_RCLK_L();
                                        color = GPIOC->IDR & 0XFF00;        //读数据
                                        FIFO_RCLK_H();
                                        FIFO_RCLK_L();
                                        color |= (GPIOC->IDR >> 8) & 0X00FF;        //读数据
                                        FIFO_RCLK_H();
                                        p_show[j] = color;
                                        LCD->LCD_RAM = p_show[j];        //这里显示的没有问题!!!
//                                        if(j > 65280)//65280,204
//                                                break;
                                }
//                                for(j = 0; j < 65280; j ++)                //320*240
//                                {
//                                        LCD->LCD_RAM = p_show[j];        //这个范围里数据是正常的,再超就出错
//                                }
                                delay_ms(1800);
                                delay_ms(1800);
                                LCD_Clear(BLACK);
                                delay_ms(1800);
                                LCD_SetCursor(0x00, 0x0000);        //设置光标位置
                                LCD_WriteRAM_Prepare();                        //开始写入GRAM
                                for(j = 0; j < 76800; j ++)                //320*240
                                {
                                        LCD->LCD_RAM = p_show[j];        //这里显示的就有问题!!!下面编码就跟着有问题,编码本身并没有错
                                }
                                EXTI->PR = 1 << 8;        //清除LINE8上的中断标志位
                                ov_sta = 0;                        //开始下一次采集
                        }
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2016-1-7 23:29:15 | 显示全部楼层
帮顶
回复

使用道具 举报

2

主题

11

帖子

0

精华

初级会员

Rank: 2

积分
124
金钱
124
注册时间
2015-4-21
在线时间
23 小时
 楼主| 发表于 2016-1-8 11:43:45 | 显示全部楼层
别老是顶啊,帮我解决问题吧
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-22 06:52

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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