PikaCV_Image.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. #include "PikaCV_Image.h"
  2. #include "PikaCV_common.h"
  3. #include "PikaStdData_List.h"
  4. #include "dataStrs.h"
  5. void PikaCV_Image___init__(PikaObj* self) {
  6. if (NULL != obj_getStruct(self, "image")) {
  7. /* already initialized */
  8. return;
  9. }
  10. /* init */
  11. PikaCV_Image image = {
  12. .format = PikaCV_ImageFormat_Type_Empty,
  13. .width = 0,
  14. .height = 0,
  15. .size = 0,
  16. };
  17. obj_setStruct(self, "image", image);
  18. _image_setData(self, NULL, 0);
  19. }
  20. uint8_t* _image_getData(PikaObj* self) {
  21. PikaCV_Image* image = obj_getStruct(self, "image");
  22. if (NULL == image) {
  23. return NULL;
  24. }
  25. return obj_getBytes(self, "_data");
  26. }
  27. int _image_getDataSize(PikaObj* self) {
  28. PikaCV_Image* image = obj_getStruct(self, "image");
  29. if (NULL == image) {
  30. return 0;
  31. }
  32. return obj_getBytesSize(self, "_data");
  33. }
  34. PIKA_RES _image_setData(PikaObj* self, uint8_t* data, int size) {
  35. PikaCV_Image* image = obj_getStruct(self, "image");
  36. if (NULL == image) {
  37. return PIKA_RES_ERR_ARG_NO_FOUND;
  38. }
  39. obj_setBytes(self, "_data", data, size);
  40. image->size = size;
  41. return PIKA_RES_OK;
  42. }
  43. Arg* PikaCV_Image_data(PikaObj* self) {
  44. PikaCV_Image* image = obj_getStruct(self, "image");
  45. if (NULL == image) {
  46. return NULL;
  47. }
  48. return arg_copy(obj_getArg(self, "_data"));
  49. }
  50. int PikaCV_Image_format(PikaObj* self) {
  51. PikaCV_Image* image = obj_getStruct(self, "image");
  52. if (NULL == image) {
  53. return PikaCV_ImageFormat_Type_Empty;
  54. }
  55. return image->format;
  56. }
  57. int PikaCV_Image_hight(PikaObj* self) {
  58. PikaCV_Image* image = obj_getStruct(self, "image");
  59. if (NULL == image) {
  60. return 0;
  61. }
  62. return image->height;
  63. }
  64. void PikaCV_Image_loadJpeg(PikaObj* self, Arg* bytes) {
  65. obj_setArg(self, "_data", bytes);
  66. }
  67. void PikaCV_Image_loadRGB565(PikaObj* self,
  68. int width,
  69. int hight,
  70. uint8_t* bytes) {
  71. PikaCV_Image* image = obj_getStruct(self, "image");
  72. if (NULL == image) {
  73. return;
  74. }
  75. image->format = PikaCV_ImageFormat_Type_RGB565;
  76. image->height = hight;
  77. image->width = width;
  78. image->size = hight * width * 2;
  79. _image_setData(self, bytes, image->size);
  80. }
  81. void PikaCV_Image_loadRGB888(PikaObj* self,
  82. int width,
  83. int height,
  84. uint8_t* bytes) {
  85. PikaCV_Image* image = obj_getStruct(self, "image");
  86. if (NULL == image) {
  87. return;
  88. }
  89. image->format = PikaCV_ImageFormat_Type_RGB888;
  90. image->height = height;
  91. image->width = width;
  92. image->size = height * width * 3;
  93. _image_setData(self, bytes, image->size);
  94. }
  95. void PikaCV_Image_loadGray(PikaObj* self,
  96. int width,
  97. int hight,
  98. uint8_t* bytes) {
  99. PikaCV_Image* image = obj_getStruct(self, "image");
  100. if (NULL == image) {
  101. return;
  102. }
  103. image->format = PikaCV_ImageFormat_Type_GRAY;
  104. image->height = hight;
  105. image->width = width;
  106. image->size = hight * width;
  107. _image_setData(self, bytes, image->size);
  108. }
  109. void PikaCV_Image_read(PikaObj* self, char* path) {
  110. PikaCV_Image* image = obj_getStruct(self, "image");
  111. if (NULL == image) {
  112. return;
  113. }
  114. Arg* data_arg = arg_loadFile(NULL, path);
  115. if (NULL == data_arg) {
  116. pika_platform_printf("PikaCV_Image_read: failed to load file: %s\n",
  117. path);
  118. return;
  119. }
  120. Args buffs = {0};
  121. char* suffix = strsGetLastToken(&buffs, path, '.');
  122. if (suffix == NULL) {
  123. return;
  124. }
  125. if (strEqu(suffix, "jpg")) {
  126. image->format = PikaCV_ImageFormat_Type_JPEG;
  127. PikaCV_Image_loadJpeg(self, data_arg);
  128. } else {
  129. obj_setErrorCode(self, PIKA_RES_ERR_OPERATION_FAILED);
  130. obj_setSysOut(self, "PikaCV_Image_read: unsupported format: %s",
  131. suffix);
  132. }
  133. arg_deinit(data_arg);
  134. strsDeinit(&buffs);
  135. }
  136. void PikaCV_Image_setPixel(PikaObj* self,
  137. int channel,
  138. int value,
  139. int x,
  140. int y) {
  141. PikaCV_Image* image = obj_getStruct(self, "image");
  142. if (NULL == image) {
  143. return;
  144. }
  145. uint8_t* data = _image_getData(self);
  146. if (image->format == PikaCV_ImageFormat_Type_RGB565) {
  147. data[(y * image->width + x) * 2 + channel] = value;
  148. } else if (image->format == PikaCV_ImageFormat_Type_RGB888) {
  149. data[(y * image->width + x) * 3 + channel] = value;
  150. } else if (image->format == PikaCV_ImageFormat_Type_GRAY) {
  151. data[y * image->width + x] = value;
  152. } else {
  153. obj_setErrorCode(self, PIKA_RES_ERR_OPERATION_FAILED);
  154. obj_setSysOut(self, "PikaCV_Image_setPixel: unsupported format: %d",
  155. image->format);
  156. }
  157. }
  158. int PikaCV_Image_getPixel(PikaObj* self, int channel, int x, int y) {
  159. PikaCV_Image* image = obj_getStruct(self, "image");
  160. if (NULL == image) {
  161. return 0;
  162. }
  163. uint8_t* data = _image_getData(self);
  164. if (image->format == PikaCV_ImageFormat_Type_RGB565) {
  165. return data[(y * image->width + x) * 2 + channel];
  166. } else if (image->format == PikaCV_ImageFormat_Type_RGB888) {
  167. return data[(y * image->width + x) * 3 + channel];
  168. } else if (image->format == PikaCV_ImageFormat_Type_GRAY) {
  169. return data[y * image->width + x];
  170. } else {
  171. obj_setErrorCode(self, PIKA_RES_ERR_OPERATION_FAILED);
  172. obj_setSysOut(self, "PikaCV_Image_getPixel: unsupported format: %d",
  173. image->format);
  174. }
  175. return 0;
  176. }
  177. int PikaCV_Image_size(PikaObj* self) {
  178. PikaCV_Image* image = obj_getStruct(self, "image");
  179. if (NULL == image) {
  180. return 0;
  181. }
  182. return image->size;
  183. }
  184. int PikaCV_Image_width(PikaObj* self) {
  185. PikaCV_Image* image = obj_getStruct(self, "image");
  186. if (NULL == image) {
  187. return 0;
  188. }
  189. return image->width;
  190. }
  191. void PikaCV_Image_write(PikaObj* self, char* path) {
  192. uint8_t* data = _image_getData(self);
  193. int size = _image_getDataSize(self);
  194. if (NULL == data || size <= 0) {
  195. obj_setErrorCode(self, PIKA_RES_ERR_OPERATION_FAILED);
  196. obj_setSysOut(self, "PikaCV_Image_write: data is NULL or size is 0");
  197. return;
  198. }
  199. FILE* fp = __platform_fopen(path, "wb+");
  200. if (NULL == fp) {
  201. obj_setErrorCode(self, PIKA_RES_ERR_OPERATION_FAILED);
  202. obj_setSysOut(self, "PikaCV_Image_write: failed to open file: %s",
  203. path);
  204. return;
  205. }
  206. __platform_fwrite(data, 1, size, fp);
  207. __platform_fclose(fp);
  208. }
  209. #define MAX(a, b) ((a) > (b) ? (a) : (b))
  210. #define MIN(a, b) ((a) < (b) ? (a) : (b))
  211. void PikaCV_Image_add(PikaObj* self, PikaObj* image) {
  212. PikaCV_Image* src = obj_getStruct(self, "image");
  213. PikaCV_Image* img = obj_getStruct(image, "image");
  214. if (NULL == src || NULL == img) {
  215. pika_assert(0);
  216. return;
  217. }
  218. if (!PikaCV_Format_CheckTwo(self, image, PikaCV_Check_ReturnError)) {
  219. obj_setErrorCode(self, PIKA_RES_ERR_OPERATION_FAILED);
  220. obj_setSysOut(self, "unsupported image format");
  221. return;
  222. }
  223. if (!PikaCV_Size_Check(self, image, PikaCV_Check_SHW)) {
  224. obj_setErrorCode(self, PIKA_RES_ERR_OPERATION_FAILED);
  225. obj_setSysOut(self, "illegal image size");
  226. return;
  227. }
  228. uint8_t* src_data = _image_getData(self);
  229. uint8_t* img_data = _image_getData(image);
  230. int i;
  231. uint8_t result;
  232. /* add two images */
  233. for (i = 0; i < (src->size) / 3; i++) {
  234. result = src_data[i * 3] + img_data[i * 3];
  235. src_data[i * 3] =
  236. ((result < MAX(src_data[i * 3], img_data[i * 3])) ? 255 : result);
  237. result = src_data[i * 3 + 1] + img_data[i * 3 + 1];
  238. src_data[i * 3 + 1] =
  239. ((result < MAX(src_data[i * 3 + 1], img_data[i * 3 + 1])) ? 255
  240. : result);
  241. result = src_data[i * 3 + 2] + img_data[i * 3 + 2];
  242. src_data[i * 3 + 2] =
  243. ((result < MAX(src_data[i * 3 + 2], img_data[i * 3 + 2])) ? 255
  244. : result);
  245. }
  246. obj_setBytes(self, "_data", src_data, src->size);
  247. }
  248. void PikaCV_Image_minus(PikaObj* self, PikaObj* image) {
  249. PikaCV_Image* src = obj_getStruct(self, "image");
  250. PikaCV_Image* img = obj_getStruct(image, "image");
  251. if (NULL == src || NULL == img) {
  252. pika_assert(0);
  253. return;
  254. }
  255. if (!PikaCV_Format_CheckTwo(self, image, PikaCV_Check_ReturnError)) {
  256. obj_setErrorCode(self, PIKA_RES_ERR_OPERATION_FAILED);
  257. obj_setSysOut(self, "unsupported image format");
  258. return;
  259. }
  260. if (!PikaCV_Size_Check(self, image, PikaCV_Check_SHW)) {
  261. obj_setErrorCode(self, PIKA_RES_ERR_OPERATION_FAILED);
  262. obj_setSysOut(self, "illegal image size");
  263. return;
  264. }
  265. uint8_t* src_data = _image_getData(self);
  266. uint8_t* img_data = _image_getData(image);
  267. int i;
  268. uint8_t result;
  269. /* minus two images */
  270. for (i = 0; i < (src->size) / 3; i++) {
  271. result = src_data[i * 3] - img_data[i * 3];
  272. src_data[i * 3] =
  273. ((result < MIN(src_data[i * 3], img_data[i * 3])) ? 0 : result);
  274. result = src_data[i * 3 + 1] - img_data[i * 3 + 1];
  275. src_data[i * 3 + 1] =
  276. ((result > MIN(src_data[i * 3 + 1], img_data[i * 3 + 1])) ? 0
  277. : result);
  278. result = src_data[i * 3 + 2] - img_data[i * 3 + 2];
  279. src_data[i * 3 + 2] =
  280. ((result < MIN(src_data[i * 3 + 2], img_data[i * 3 + 2])) ? 0
  281. : result);
  282. }
  283. obj_setBytes(self, "_data", src_data, (src->size));
  284. }
  285. void PikaCV_Image_merge(PikaObj* self, PikaObj* B, PikaObj* G, PikaObj* R) {
  286. PikaCV_Image* src = obj_getStruct(self, "image");
  287. PikaCV_Image* Channel_B = obj_getStruct(B, "image");
  288. PikaCV_Image* Channel_G = obj_getStruct(G, "image");
  289. PikaCV_Image* Channel_R = obj_getStruct(R, "image");
  290. if (NULL == src || NULL == Channel_B || NULL == Channel_G ||
  291. NULL == Channel_R) {
  292. pika_assert(0);
  293. return;
  294. }
  295. if (!PikaCV_Format_Check(self, PikaCV_ImageFormat_Type_RGB888,
  296. PikaCV_Check_ReturnError)) {
  297. obj_setErrorCode(self, PIKA_RES_ERR_OPERATION_FAILED);
  298. obj_setSysOut(self, "unsupported image format");
  299. return;
  300. }
  301. if (!PikaCV_Format_Check(B, PikaCV_ImageFormat_Type_GRAY,
  302. PikaCV_Check_ReturnError) ||
  303. !PikaCV_Format_Check(G, PikaCV_ImageFormat_Type_GRAY,
  304. PikaCV_Check_ReturnError) ||
  305. !PikaCV_Format_Check(R, PikaCV_ImageFormat_Type_GRAY,
  306. PikaCV_Check_ReturnError)) {
  307. obj_setErrorCode(self, PIKA_RES_ERR_OPERATION_FAILED);
  308. obj_setSysOut(self, "unsupported image format");
  309. return;
  310. }
  311. if (!PikaCV_Size_Check(B, G, PikaCV_Check_SHW) ||
  312. !PikaCV_Size_Check(B, R, PikaCV_Check_SHW)) {
  313. obj_setErrorCode(self, PIKA_RES_ERR_OPERATION_FAILED);
  314. obj_setSysOut(self, "illegal image size");
  315. return;
  316. }
  317. src->size = Channel_B->size * 3;
  318. src->height = Channel_B->height;
  319. src->width = Channel_B->width;
  320. Arg* src_new_data_arg = arg_newBytes(NULL, src->size);
  321. uint8_t* src_data_new = arg_getBytes(src_new_data_arg);
  322. uint8_t* B_data = _image_getData(B);
  323. uint8_t* G_data = _image_getData(G);
  324. uint8_t* R_data = _image_getData(R);
  325. for (int i = 0; i < Channel_B->size; i++) {
  326. src_data_new[i * 3] = R_data[i];
  327. src_data_new[i * 3 + 1] = G_data[i];
  328. src_data_new[i * 3 + 2] = B_data[i];
  329. }
  330. obj_setBytes(self, "_data", src_data_new, (src->size));
  331. arg_deinit(src_new_data_arg);
  332. }
  333. PikaObj* PikaCV_Image_split(PikaObj* self) {
  334. PikaCV_Image* src = obj_getStruct(self, "image");
  335. if (NULL == src) {
  336. pika_assert(0);
  337. return NULL;
  338. }
  339. if (!PikaCV_Format_Check(self, PikaCV_ImageFormat_Type_RGB888,
  340. PikaCV_Check_ReturnError)) {
  341. obj_setErrorCode(self, PIKA_RES_ERR_OPERATION_FAILED);
  342. obj_setSysOut(self, "unsupported image format");
  343. return NULL;
  344. }
  345. uint8_t* src_data = _image_getData(self);
  346. Arg* arg_data_B = arg_newBytes(NULL, (src->size) / 3);
  347. Arg* arg_data_G = arg_newBytes(NULL, (src->size) / 3);
  348. Arg* arg_data_R = arg_newBytes(NULL, (src->size) / 3);
  349. uint8_t* data_B = arg_getBytes(arg_data_B);
  350. uint8_t* data_G = arg_getBytes(arg_data_G);
  351. uint8_t* data_R = arg_getBytes(arg_data_R);
  352. uint8_t* RGB[3] = {data_R, data_G, data_B};
  353. for (int i = 0; i < (src->size) / 3; i++) {
  354. RGB[0][i] = src_data[i * 3];
  355. RGB[1][i] = src_data[i * 3 + 1];
  356. RGB[2][i] = src_data[i * 3 + 2];
  357. }
  358. PikaObj* list = newNormalObj(New_PikaStdData_List);
  359. PikaStdData_List___init__(list);
  360. for (int i = 0; i < 3; i++) {
  361. PikaObj* img = newNormalObj(New_PikaCV_Image);
  362. PikaCV_Image___init__(img);
  363. PikaCV_Image_loadGray(img, src->width, src->height, RGB[i]);
  364. Arg* token_arg = arg_newObj(img);
  365. PikaStdData_List_append(list, token_arg);
  366. arg_deinit(token_arg);
  367. }
  368. arg_deinit(arg_data_B);
  369. arg_deinit(arg_data_G);
  370. arg_deinit(arg_data_R);
  371. return list;
  372. }
  373. #undef MAX
  374. #undef MIN