当前位置:   article > 正文

MIPIRaw转UnpackRaw_mipi raw

mipi raw

Mipiraw和unpackraw区别 

传感器采集的RAW数据通常为10bit,存储RAW数据需要两个Byte,而其中有6个bit位是空着的,这样就有存储空间浪费。MIPI RAW数据充分利用了这个特性,采用5个Byte,共40bit存储4个RAW数据。大部分UnpackRaw图都是以小端模式存储,MipiRaw则是大端存储。Raw图只有数据,没有其他属性信息。

下面依次详细解释raw图存储格式 和 MSB、LSB的排列方式 以及 转换方法。

上图:

一、10Bit转换

1、大小端和MSB、LSB解释

1.1、十六进制示意图

.对应MiPiRaw的十六进制

.对应UnpackRaw的十六进制

1.2、大小端判断

UnpackRaw:

从UnpackRaw的十六进制看,前两个字节为 5D 00,像素值为93,而十六进制0x5D对应的十进制就是93。从结果推理前两个字节标识的像素字节为单位排列应该是 00 5D,从而判断是小端模式存储。

小端模式:高有效位在高地址,低有效在低地址,从右向左读就是正确的数据排列。

大端模式:高有效位在低地址,低有效位在高地址,从左向右都就是正确的数据排列。

注意大小端模式以字节为单位。

MIpiRaw:

从上面MipiRaw的十六进制来看是大端模式,将两个最低有效位存储到公共字节中,如下图:

0x17 << 2 + 0x39 & 0x03 = 0x0001011101,即0x00 5D,即93

1.3、MSB和LSB的判断

首先看一张图片:

大端模式和小端模式字节内均有两种存储方式。

UnpackRaw:

从1.3的图中可以看出

UnpackRaw是小端模式 + 字节内MSB优先的存储方式

MipiRaw是大端模式 + 字节内MSB优先的存储方式

结论:UnpackRaw是小端模式 + 字节内MSB优先的存储方式。

MipiRaw是大端模式 + 字节内MSB优先的存储方式。

2、转换方法

2.1、存储示意图

10 Bpp:

Unpackraw

4个像素占用8个字节。灰色是空置未使用的bit位。

MipiRaw

4个像素占用5个字节

2.2、代码实现

代码实现将MipiRaw的排列改为UnpackRaw的排列,代码实现如下:

参数:

pIn:指源文件指针

pOut:指输出文件指针

number:指MipiRaw的像素个数,即宽*高

代码实现将MipiRaw的排列改为UnpackRaw的排列,代码实现如下:

1.0版本

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <iostream>
  5. typedef unsigned char BYTE; // 定义BYTE类型,占1个字节
  6. void MipiRaw10ToP10(BYTE* pIn, BYTE* pOut, long number)
  7. {
  8. printf("enter MipiRaw10ToP10\n");
  9. int index = 0;
  10. // 5个字节4个像素
  11. // 前面4个字节都是对应像素的高8位,最后一个字(第五个)每个像素的低2位
  12. // MIPIRaw 大端模式
  13. // BYTE0 :P1[0:7]
  14. // BYTE1 :P2[0:7]
  15. // BYTE2 :P3[0:7]
  16. // BYTE3 :P4[0:7]
  17. // BYTE4 :P4[8:9]P3[8:9]P2[8:9]P1[8:9]
  18. // UnpackRaw 小端模式
  19. // Pix1: BYTE0:[2:9], BYTE1:[0:1] == BYTE0:(P1[0:7]<< 2 + P1[8:9]), BYTE1:(P1[0:7] >> 6)
  20. // Pix2: 上同
  21. // Pix3: 上同
  22. // Pix4: 上同
  23. // Big endian
  24. for (long i = 0; i < (number * 5) / 4; i = i + 5)
  25. {
  26. pOut[index++] = ((pIn[i] << 2) & 0xfc) | (pIn[i + 4] & 0x03);
  27. pOut[index++] = (pIn[i] >> 6) & 0x03;
  28. //pIn[i+4] >>= 2;
  29. pOut[index++] = ((pIn[i + 1] << 2) & 0xfc) | ((pIn[i + 4] >> 2) & 0x03);
  30. pOut[index++] = (pIn[i + 1] >> 6) & 0x03;
  31. //pIn[i+4] >>= 2;
  32. pOut[index++] = ((pIn[i + 2] << 2) & 0xfc) | ((pIn[i + 4] >> 4) & 0x03);
  33. pOut[index++] = (pIn[i + 2] >> 6) & 0x03;
  34. //pIn[i+4] >>= 2;
  35. pOut[index++] = ((pIn[i + 3] << 2) & 0xfc) | ((pIn[i + 4] >> 6) & 0x03);
  36. pOut[index++] = (pIn[i + 3] >> 6) & 0x03;
  37. }
  38. printf("MipiRaw10ToP10 over\n");
  39. }

二、12Bit转换

一个像素占用12个bit,两个字节空置4个bit未使用。MipiRaw则是3个字节存储两个像素,最后一个字节保留两个像素最低四位的有效位数据。

1、大小端、MSB和LSB

1.1、十六进制示意图

MipiRaw:

Unpackraw:

1.2、大小端及MSB和LSB的判断

根据十六进制上示意图:

根据像素值,然后从十六进制就可以看出Unpack是小端模式。根据如上示意图,看出字节内是MSB优先。

从示意图看出,MipiRaw是大端存储方式,最低四位有效位放在公共字节。

结论:UnpackRaw是小端模式 + 字节内MSB优先的存储方式。

MipiRaw是大端模式 + 字节内MSB优先的存储方式。

2、转换方法

2.1、存储示意图

12Bpp

UnpackRaw

2个像素占用4个字节

MipiRaw

2个像素占用3个字节

2.2代码实现

1.0版本

代码实现:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <iostream>
  5. typedef unsigned char BYTE; // 定义BYTE类型,占1个字节
  6. void MipiRaw12ToP12(BYTE* pIn, BYTE* pOut, long number)
  7. {
  8. printf("enter MipiRaw12ToP12\n");
  9. int index = 0;
  10. // 3个字节2个像素
  11. // 前面2个字节都是对应像素的高8位,最后一个字(第3个)每个像素的低4位
  12. // MIPIRaw 大端模式
  13. // BYTE0 :P1[0:7]
  14. // BYTE1 :P2[0:7]
  15. // BYTE2 :P2[8:11]P1[8:11]
  16. // UnpackRaw 小端模式
  17. // Pix1: BYTE0:[4:11], BYTE1:[0:3] == BYTE0:(P1[0:7]<< 4 + P1[8:11]), BYTE1:(P1[0:7] >> 4)
  18. // Pix2: 上同
  19. // Big endian
  20. for (long i = 0; i < (number * 3) / 2; i = i + 3)
  21. {
  22. pOut[index++] = ((pIn[i] << 4) & 0xf0) | (pIn[i + 2] & 0x0f);
  23. pOut[index++] = (pIn[i] >> 4) & 0x0f;
  24. //pIn[i+2] >>= 4;
  25. pOut[index++] = ((pIn[i + 1] << 4) & 0xf0) | ((pIn[i + 2] >> 4) & 0x0f);
  26. pOut[index++] = (pIn[i + 1] >> 4) & 0x0f;
  27. }
  28. printf("MipiRaw12ToP12 over\n");
  29. }

三、14Bit转换

一个像素占用14个bit,两个字节空置2个bit未使用。MipiRaw则是7个字节存储4个像素,最后3个字节保留四个像素最低6位的有效位数据。

1、大小端、MSB和LSB

1.1、十六进制示意图

MipiRaw

UnpackRaw

1.2、大小端及MGS和LSB的判断

根据像素值,然后从十六进制就可以看出Unpack是小端模式。根据如上示意图,看出字节内是MSB优先。

从示意图看出,MipiRaw是大端存储方式,最低6位有效位放在公共字节。

结论:UnpackRaw是小端模式 + 字节内MSB优先的存储方式。

MipiRaw是大端模式 + 字节内MSB优先的存储方式。

2、代码实现

1.0版本

  1. void MipiRaw14ToP14(BYTE* pIn, BYTE* pOut, long number)
  2. {
  3. printf("enter MipiRaw14ToP14\n");
  4. int index = 0;
  5. // 7个字节4个像素
  6. // 前面4个字节都是对应像素的高8位,最后3个字对应每个像素的低6位
  7. // BYTE0 :P1[0:7]
  8. // BYTE1 :P2[0:7]
  9. // BYTE2 :P3[0:7]
  10. // BYTE3 :P4[0:7]
  11. // BYTE4 :P1[8:13]P2[8:9]
  12. // BYTE5 :P2[10:13]P3[8:11]
  13. // BYTE6 :P3[12:13]P4[8:13]
  14. // Big endian
  15. for (long i = 0; i < (number * 7) / 4; i = i + 7)
  16. {
  17. // Pix1
  18. pOut[index++] = ((pIn[i] << 6) & 0xc0) | ((pIn[i + 4] >> 2) & 0xcf);
  19. pOut[index++] = (pIn[i] >> 2) & 0x3f;
  20. // Pix2
  21. pOut[index++] = ((pIn[i + 1] << 6) & 0xc0) | ((pIn[i + 4] << 4) & 0x30) + ((pIn[i + 5] >> 4) & 0x0f);
  22. pOut[index++] = (pIn[i + 1] >> 2) & 0x3f;
  23. // Pix3
  24. pOut[index++] = ((pIn[i + 2] << 6) & 0xc0) | ((pIn[i + 5] << 2) & 0x3c) + ((pIn[i + 6] >> 6) & 0x03);
  25. pOut[index++] = (pIn[i + 2] >> 2) & 0x3f;
  26. // Pix4
  27. pOut[index++] = ((pIn[i + 3] << 6) & 0xc0) | ((pIn[i + 6]) & 0x3f);
  28. pOut[index++] = (pIn[i + 3] >> 2) & 0x3f;
  29. }
  30. printf("MipiRaw14ToP14 over\n");
  31. }

四、整体代码

1、1.0

这里是单纯的转换,需要输入正确的宽高。

10bit计算公式

文件大小 = width * height * 5 / 4

12bit

文件大小 = width * height * 3 / 2

14bit

文件大小 = width * height * 7 / 4

如果dump出来的文件大小比算出来的大小大,那应该是stride和width不一致,这是如果使用1.0的话,那么输入的width就是stride的大小了,不然转化可能会有问题。14bit的除外,14bit转化1.0和2.0一致,输入width即width不是stride,其余照旧。

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <iostream>
  5. typedef unsigned char BYTE; // 定义BYTE类型,占1个字节
  6. void MipiRaw10ToP10(BYTE* pIn, BYTE* pOut, long number)
  7. {
  8. printf("enter MipiRaw10ToP10\n");
  9. int index = 0;
  10. // 5个字节4个像素
  11. // 前面4个字节都是对应像素的高8位,最后一个字(第五个)每个像素的低2位
  12. // MIPIRaw 大端模式
  13. // BYTE0 :P1[0:7]
  14. // BYTE1 :P2[0:7]
  15. // BYTE2 :P3[0:7]
  16. // BYTE3 :P4[0:7]
  17. // BYTE4 :P4[8:9]P3[8:9]P2[8:9]P1[8:9]
  18. // UnpackRaw 小端模式
  19. // Pix1: BYTE0:[2:9], BYTE1:[0:1] == BYTE0:(P1[0:7]<< 2 + P1[8:9]), BYTE1:(P1[0:7] >> 6)
  20. // Pix2: 上同
  21. // Pix3: 上同
  22. // Pix4: 上同
  23. // Big endian
  24. for (long i = 0; i < (number * 5) / 4; i = i + 5)
  25. {
  26. pOut[index++] = ((pIn[i] << 2) & 0xfc) | (pIn[i + 4] & 0x03);
  27. pOut[index++] = (pIn[i] >> 6) & 0x03;
  28. //pIn[i+4] >>= 2;
  29. pOut[index++] = ((pIn[i + 1] << 2) & 0xfc) | ((pIn[i + 4] >> 2) & 0x03);
  30. pOut[index++] = (pIn[i + 1] >> 6) & 0x03;
  31. //pIn[i+4] >>= 2;
  32. pOut[index++] = ((pIn[i + 2] << 2) & 0xfc) | ((pIn[i + 4] >> 4) & 0x03);
  33. pOut[index++] = (pIn[i + 2] >> 6) & 0x03;
  34. //pIn[i+4] >>= 2;
  35. pOut[index++] = ((pIn[i + 3] << 2) & 0xfc) | ((pIn[i + 4] >> 6) & 0x03);
  36. pOut[index++] = (pIn[i + 3] >> 6) & 0x03;
  37. }
  38. printf("MipiRaw10ToP10 over\n");
  39. }
  40. void MipiRaw12ToP12(BYTE* pIn, BYTE* pOut, long number)
  41. {
  42. printf("enter MipiRaw12ToP12\n");
  43. int index = 0;
  44. // 3个字节2个像素
  45. // 前面2个字节都是对应像素的高8位,最后一个字(第3个)每个像素的低4位
  46. // MIPIRaw 大端模式
  47. // BYTE0 :P1[0:7]
  48. // BYTE1 :P2[0:7]
  49. // BYTE2 :P2[8:11]P1[8:11]
  50. // UnpackRaw 小端模式
  51. // Pix1: BYTE0:[4:11], BYTE1:[0:3] == BYTE0:(P1[0:7]<< 4 + P1[8:11]), BYTE1:(P1[0:7] >> 4)
  52. // Pix2: 上同
  53. // Big endian
  54. for (long i = 0; i < (number * 3) / 2; i = i + 3)
  55. {
  56. pOut[index++] = ((pIn[i] << 4) & 0xf0) | (pIn[i + 2] & 0x0f);
  57. pOut[index++] = (pIn[i] >> 4) & 0x0f;
  58. //pIn[i+2] >>= 4;
  59. pOut[index++] = ((pIn[i + 1] << 4) & 0xf0) | ((pIn[i + 2] >> 4) & 0x0f);
  60. pOut[index++] = (pIn[i + 1] >> 4) & 0x0f;
  61. }
  62. printf("MipiRaw12ToP12 over\n");
  63. }
  64. void MipiRaw14ToP14(BYTE* pIn, BYTE* pOut, long number)
  65. {
  66. printf("enter MipiRaw14ToP14\n");
  67. int index = 0;
  68. // 7个字节4个像素
  69. // 前面4个字节都是对应像素的高8位,最后3个字对应每个像素的低6位
  70. // BYTE0 :P1[0:7]
  71. // BYTE1 :P2[0:7]
  72. // BYTE2 :P3[0:7]
  73. // BYTE3 :P4[0:7]
  74. // BYTE4 :P1[8:13]P2[8:9]
  75. // BYTE5 :P2[10:13]P3[8:11]
  76. // BYTE6 :P3[12:13]P4[8:13]
  77. // Big endian
  78. for (long i = 0; i < (number * 7) / 4; i = i + 7)
  79. {
  80. // Pix1
  81. pOut[index++] = ((pIn[i] << 6) & 0xc0) | ((pIn[i + 4] >> 2) & 0xcf);
  82. pOut[index++] = (pIn[i] >> 2) & 0x3f;
  83. // Pix2
  84. pOut[index++] = ((pIn[i + 1] << 6) & 0xc0) | ((pIn[i + 4] << 4) & 0x30) + ((pIn[i + 5] >> 4) & 0x0f);
  85. pOut[index++] = (pIn[i + 1] >> 2) & 0x3f;
  86. // Pix3
  87. pOut[index++] = ((pIn[i + 2] << 6) & 0xc0) | ((pIn[i + 5] << 2) & 0x3c) + ((pIn[i + 6] >> 6) & 0x03);
  88. pOut[index++] = (pIn[i + 2] >> 2) & 0x3f;
  89. // Pix4
  90. pOut[index++] = ((pIn[i + 3] << 6) & 0xc0) | ((pIn[i + 6]) & 0x3f);
  91. pOut[index++] = (pIn[i + 3] >> 2) & 0x3f;
  92. }
  93. printf("MipiRaw14ToP14 over\n");
  94. }
  95. int main(int argc, char* argv[])
  96. {
  97. FILE* fp = NULL;
  98. BYTE* ptr;
  99. BYTE* outptr = NULL;
  100. int err = 0;
  101. if (argc < 6) {
  102. return -1;
  103. }
  104. const char* filepath = argv[1];
  105. const char* height_str = argv[2];
  106. const char* width_str = argv[3];
  107. const char* bpp_str = argv[4];
  108. const char* outfilepath = argv[5];
  109. int width = 0;
  110. int height = 0;
  111. int bpp = 0;
  112. width = atoi(width_str);
  113. height = atoi(height_str);
  114. bpp = atoi(bpp_str);
  115. printf("width: %d, height: %d, bpp: %d\n", width, height, bpp);
  116. // 输入源路径并打开raw图像文件
  117. printf("=======raw image process===========\n");
  118. err = fopen_s(&fp, filepath, "rb");
  119. if (NULL == fp)
  120. {
  121. printf("can not open the raw image ");
  122. return 0;
  123. }
  124. else
  125. {
  126. printf("read OK\n");
  127. }
  128. //Sleep(1000); /* windows 使用Sleep,参数为毫秒 */
  129. // 分配内存并将图像读到二维数组中
  130. fseek(fp, 0, SEEK_END);
  131. unsigned long fsize = ftell(fp);
  132. rewind(fp);
  133. ptr = (BYTE*)malloc(fsize * sizeof(BYTE));
  134. if (ptr == NULL) {
  135. printf("ptr malloc fail\n");
  136. return -2;
  137. }
  138. if (fread(ptr, 1, fsize, fp) != fsize) {
  139. printf("read file error.\n");
  140. return -1;
  141. }
  142. fclose(fp);
  143. unsigned long outsize = width * height * 2;
  144. outptr = (BYTE*)malloc(outsize * sizeof(BYTE));
  145. if (outptr == NULL) {
  146. printf("outptr malloc fail\n");
  147. return -2;
  148. }
  149. if (10 == bpp) {
  150. MipiRaw10ToP10(ptr, outptr, (width * height));
  151. }
  152. else if (12 == bpp) {
  153. MipiRaw12ToP12(ptr, outptr, (width * height));
  154. }
  155. else if (14 == bpp) {
  156. MipiRaw14ToP14(ptr, outptr, (width * height));
  157. }
  158. free(ptr);
  159. ptr = NULL;
  160. // 将处理后的图像数据保存
  161. printf("Input the raw_image path for save: \n");
  162. FILE* outfp = NULL;
  163. err = fopen_s(&outfp, outfilepath, "wb");
  164. if (outfp == NULL) {
  165. printf("can not create the raw_image\n");
  166. return 0;
  167. }
  168. else {
  169. printf("fopen OK\n");
  170. }
  171. printf("creat file OK\n");
  172. if (fwrite(outptr, 1, outsize, outfp) != outsize) {
  173. printf("outptr write fail");
  174. return -3;
  175. }
  176. printf("write OK\n");
  177. fclose(outfp);
  178. free(outptr);
  179. outptr = NULL;
  180. return 0;
  181. }

2、2.0

加了一个升级版的,可以兼顾stride和width不同时,把stride和width之间的像素裁剪掉,防止出现绿边的情况。

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <iostream>
  5. typedef unsigned char BYTE; // 定义BYTE类型,占1个字节
  6. void MipiRaw10ToP10(BYTE* pIn, unsigned long fsize, BYTE* pOut, unsigned long outsize, int width, int height, int stride)
  7. {
  8. printf("enter MipiRaw10ToP10\n");
  9. int index = 0;
  10. // 5个字节4个像素
  11. // 前面4个字节都是对应像素的高8位,最后一个字(第五个)每个像素的低2位
  12. // MIPIRaw 大端模式
  13. // BYTE0 :P1[0:7]
  14. // BYTE1 :P2[0:7]
  15. // BYTE2 :P3[0:7]
  16. // BYTE3 :P4[0:7]
  17. // BYTE4 :P4[8:9]P3[8:9]P2[8:9]P1[8:9]
  18. // UnpackRaw 小端模式
  19. // Pix1: BYTE0:[2:9], BYTE1:[0:1] == BYTE0:(P1[0:7]<< 2 + P1[8:9]), BYTE1:(P1[0:7] >> 6)
  20. // Pix2: 上同
  21. // Pix3: 上同
  22. // Pix4: 上同
  23. // Big endian
  24. int count = 0;
  25. bool unjustified = false;
  26. if (stride - width > 0) {
  27. unjustified = true;
  28. }
  29. for (long i = 0; i < fsize; i = i + 5)
  30. {
  31. if (unjustified) {
  32. // 一次转化4个像素,需要5个字节,转化后为8个字节
  33. if (count > width - 1) {
  34. // 偏移时按照stride和width的差值 * 1.25,即width和stride差的像素实际占用的字节数
  35. i = i + int((stride - width) * 1.25);
  36. count = 0;
  37. }
  38. }
  39. if (i > fsize || index > outsize) {
  40. break;
  41. }
  42. pOut[index++] = ((pIn[i] << 2) & 0xfc) | (pIn[i + 4] & 0x03);
  43. pOut[index++] = (pIn[i] >> 6) & 0x03;
  44. //pIn[i+4] >>= 2;
  45. pOut[index++] = ((pIn[i + 1] << 2) & 0xfc) | ((pIn[i + 4] >> 2) & 0x03);
  46. pOut[index++] = (pIn[i + 1] >> 6) & 0x03;
  47. //pIn[i+4] >>= 2;
  48. pOut[index++] = ((pIn[i + 2] << 2) & 0xfc) | ((pIn[i + 4] >> 4) & 0x03);
  49. pOut[index++] = (pIn[i + 2] >> 6) & 0x03;
  50. //pIn[i+4] >>= 2;
  51. pOut[index++] = ((pIn[i + 3] << 2) & 0xfc) | ((pIn[i + 4] >> 6) & 0x03);
  52. pOut[index++] = (pIn[i + 3] >> 6) & 0x03;
  53. count = count + 4;
  54. }
  55. printf("MipiRaw10ToP10 over\n");
  56. }
  57. void MipiRaw12ToP12(BYTE* pIn, unsigned long fsize, BYTE* pOut, unsigned long outsize, int width, int height, int stride)
  58. {
  59. printf("enter MipiRaw12ToP12\n");
  60. int index = 0;
  61. int count = 0;
  62. bool unjustified = false;
  63. if (stride - width > 0) {
  64. unjustified = true;
  65. }
  66. // 3个字节2个像素
  67. // 前面2个字节都是对应像素的高8位,最后一个字(第3个)每个像素的低4位
  68. // MIPIRaw 大端模式
  69. // BYTE0 :P1[0:7]
  70. // BYTE1 :P2[0:7]
  71. // BYTE2 :P2[8:11]P1[8:11]
  72. // UnpackRaw 小端模式
  73. // Pix1: BYTE0:[4:11], BYTE1:[0:3] == BYTE0:(P1[0:7]<< 4 + P1[8:11]), BYTE1:(P1[0:7] >> 4)
  74. // Pix2: 上同
  75. // Big endian
  76. for (long i = 0; i < fsize; i = i + 3)
  77. {
  78. if (unjustified) {
  79. // 一次转化2个像素,需要3个字节,转化后为4个字节
  80. if (count > width - 1) {
  81. // 偏移时按照stride和width的差值 * 1.5,即width和stride差的像素实际占用的字节数
  82. i = i + int((stride - width) * 1.5);
  83. count = 0;
  84. }
  85. }
  86. if (i > fsize || index > outsize) {
  87. break;
  88. }
  89. pOut[index++] = ((pIn[i] << 4) & 0xf0) | (pIn[i + 2] & 0x0f);
  90. pOut[index++] = (pIn[i] >> 4) & 0x0f;
  91. //pIn[i+2] >>= 4;
  92. pOut[index++] = ((pIn[i + 1] << 4) & 0xf0) | ((pIn[i + 2] >> 4) & 0x0f);
  93. pOut[index++] = (pIn[i + 1] >> 4) & 0x0f;
  94. count = count + 2;
  95. }
  96. printf("MipiRaw12ToP12 over\n");
  97. }
  98. void MipiRaw14ToP14(BYTE* pIn, BYTE* pOut, long number)
  99. {
  100. printf("enter MipiRaw14ToP14\n");
  101. int index = 0;
  102. // 7个字节4个像素
  103. // 前面4个字节都是对应像素的高8位,最后3个字对应每个像素的低6位
  104. // BYTE0 :P1[0:7]
  105. // BYTE1 :P2[0:7]
  106. // BYTE2 :P3[0:7]
  107. // BYTE3 :P4[0:7]
  108. // BYTE4 :P1[8:13]P2[8:9]
  109. // BYTE5 :P2[10:13]P3[8:11]
  110. // BYTE6 :P3[12:13]P4[8:13]
  111. // Big endian
  112. for (long i = 0; i < (number * 7) / 4; i = i + 7)
  113. {
  114. // Pix1
  115. pOut[index++] = ((pIn[i] << 6) & 0xc0) | ((pIn[i + 4] >> 2) & 0xcf);
  116. pOut[index++] = (pIn[i] >> 2) & 0x3f;
  117. // Pix2
  118. pOut[index++] = ((pIn[i + 1] << 6) & 0xc0) | ((pIn[i + 4] << 4) & 0x30) + ((pIn[i + 5] >> 4) & 0x0f);
  119. pOut[index++] = (pIn[i + 1] >> 2) & 0x3f;
  120. // Pix3
  121. pOut[index++] = ((pIn[i + 2] << 6) & 0xc0) | ((pIn[i + 5] << 2) & 0x3c) + ((pIn[i + 6] >> 6) & 0x03);
  122. pOut[index++] = (pIn[i + 2] >> 2) & 0x3f;
  123. // Pix4
  124. pOut[index++] = ((pIn[i + 3] << 6) & 0xc0) | ((pIn[i + 6]) & 0x3f);
  125. pOut[index++] = (pIn[i + 3] >> 2) & 0x3f;
  126. }
  127. printf("MipiRaw14ToP14 over\n");
  128. }
  129. int main(int argc, char* argv[])
  130. {
  131. FILE* fp = NULL;
  132. BYTE* ptr;
  133. BYTE* outptr = NULL;
  134. int err = 0;
  135. if (argc < 6) {
  136. return -1;
  137. }
  138. const char* filepath = argv[1];
  139. const char* height_str = argv[2];
  140. const char* width_str = argv[3];
  141. //const char* stride_str = argv[4];
  142. const char* bpp_str = argv[4];
  143. const char* outfilepath = argv[5];
  144. int width = 0;
  145. int height = 0;
  146. int stride = 0;
  147. int bpp = 0;
  148. width = atoi(width_str);
  149. height = atoi(height_str);
  150. bpp = atoi(bpp_str);
  151. //stride = atoi(stride_str);
  152. printf("width: %d, height: %d, bpp: %d, stride: %d\n", width, height, bpp, stride);
  153. // 输入源路径并打开raw图像文件
  154. printf("=======raw image process===========\n");
  155. err = fopen_s(&fp, filepath, "rb");
  156. if (NULL == fp)
  157. {
  158. printf("can not open the raw image ");
  159. return 0;
  160. }
  161. else
  162. {
  163. printf("read OK\n");
  164. }
  165. //Sleep(1000); /* windows 使用Sleep,参数为毫秒 */
  166. // 分配内存并将图像读到二维数组中
  167. fseek(fp, 0, SEEK_END);
  168. unsigned long fsize = ftell(fp);
  169. rewind(fp);
  170. // 根据raw图实际大小,计算raw的stride
  171. if (10 == bpp) {
  172. stride = int(fsize * 4 / 5 / height);
  173. if (stride % 64 > 0) {
  174. stride = 0;
  175. }
  176. } else if (12 == bpp) {
  177. stride = int(fsize * 2 / 3 / height);
  178. if (stride % 64 > 0) {
  179. stride = 0;
  180. }
  181. } else if (14 == bpp) {
  182. stride = int(fsize * 4 / 7 / height);
  183. if (stride % 64 > 0) {
  184. stride = 0;
  185. }
  186. }
  187. ptr = (BYTE*)malloc(fsize * sizeof(BYTE));
  188. if (ptr == NULL) {
  189. printf("ptr malloc fail\n");
  190. return -2;
  191. }
  192. if (fread(ptr, 1, fsize, fp) != fsize) {
  193. printf("read file error.\n");
  194. return -1;
  195. }
  196. fclose(fp);
  197. unsigned long outsize = width * height * 2;
  198. outptr = (BYTE*)malloc(outsize * sizeof(BYTE));
  199. if (outptr == NULL) {
  200. printf("outptr malloc fail\n");
  201. return -2;
  202. }
  203. if (10 == bpp) {
  204. MipiRaw10ToP10(ptr, fsize, outptr, outsize, width, height, stride);
  205. }
  206. else if (12 == bpp) {
  207. MipiRaw12ToP12(ptr, fsize, outptr, outsize, width, height, stride);
  208. }
  209. else if (14 == bpp) {
  210. MipiRaw14ToP14(ptr, outptr, width * height);
  211. }
  212. free(ptr);
  213. ptr = NULL;
  214. // 这里可以对二维数组中的图像数据进行处理
  215. // 将处理后的图像数据输出至文件
  216. printf("Input the raw_image path for save: \n");
  217. //scanf("%s",outpath);
  218. FILE* outfp = NULL;
  219. err = fopen_s(&outfp, outfilepath, "wb");
  220. if (outfp == NULL) {
  221. printf("can not create the raw_image\n");
  222. return 0;
  223. }
  224. else {
  225. printf("fopen OK\n");
  226. }
  227. printf("creat file OK\n");
  228. if (fwrite(outptr, 1, outsize, outfp) != outsize) {
  229. printf("outptr write fail");
  230. return -3;
  231. }
  232. printf("write OK\n");
  233. fclose(outfp);
  234. free(outptr);
  235. outptr = NULL;
  236. return 0;
  237. }

注意:这里的存储方式是UnpackRaw是小端模式 + MSB优先的存储方式,MipiRaw是大端模式 + MSB优先的存储方式。可能还有别的存储方式,大家在转换的时候,先搞明白UnpackRaw和MipiRaw的存储方式再写具体代码。共勉!!!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/寸_铁/article/detail/959059
推荐阅读
相关标签
  

闽ICP备14008679号