Created
August 10, 2019 17:31
-
-
Save czoido/8b829a285855e372ee8c039040355656 to your computer and use it in GitHub Desktop.
some code to load an opencv image on a raspberry pi using DispmanX. Using code from https://github.com/AndrewFromMelbourne/raspidmx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <assert.h> | |
#include <ctype.h> | |
#include <signal.h> | |
#include <stdbool.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include "../common/imageLayer.h" | |
#include "opencv2/opencv.hpp" | |
#include "bcm_host.h" | |
volatile bool run = true; | |
typedef struct | |
{ | |
int32_t layer; | |
DISPMANX_RESOURCE_HANDLE_T resource; | |
DISPMANX_ELEMENT_HANDLE_T element; | |
} BACKGROUND_LAYER_T; | |
#ifndef ALIGN_TO_16 | |
#define ALIGN_TO_16(x) ((x + 15) & ~15) | |
#endif | |
void setPixelRGB888( | |
IMAGE_T *image, | |
int32_t x, | |
int32_t y, | |
const RGBA8_T *rgba) | |
{ | |
uint8_t *line = (uint8_t *)(image->buffer) + (y * image->pitch) + (3 * x); | |
line[0] = rgba->red; | |
line[1] = rgba->green; | |
line[2] = rgba->blue; | |
} | |
void getPixelRGB888( | |
IMAGE_T *image, | |
int32_t x, | |
int32_t y, | |
RGBA8_T *rgba) | |
{ | |
uint8_t *line = (uint8_t *)(image->buffer) + (y * image->pitch) + (3 * x); | |
rgba->red = line[0]; | |
rgba->green = line[1]; | |
rgba->blue = line[2]; | |
rgba->alpha = 255; | |
} | |
bool initImage( | |
IMAGE_T *image, | |
int32_t width, | |
int32_t height) | |
{ | |
VC_IMAGE_TYPE_T type; | |
type = VC_IMAGE_RGB888; | |
image->bitsPerPixel = 24; | |
image->setPixelDirect = setPixelRGB888; | |
image->getPixelDirect = getPixelRGB888; | |
image->type = type; | |
image->width = width; | |
image->height = height; | |
image->pitch = width * 3; | |
image->alignedHeight = ALIGN_TO_16(height); | |
image->size = image->pitch * image->alignedHeight; | |
//image->buffer = calloc(1, image->size); | |
return true; | |
} | |
void destroyImage( | |
IMAGE_T *image) | |
{ | |
if (image->buffer) { | |
free(image->buffer); | |
} | |
image->type = VC_IMAGE_MIN; | |
image->width = 0; | |
image->height = 0; | |
image->pitch = 0; | |
image->alignedHeight = 0; | |
image->bitsPerPixel = 0; | |
image->size = 0; | |
image->buffer = NULL; | |
image->setPixelDirect = NULL; | |
image->getPixelDirect = NULL; | |
} | |
void addElementImageLayerOffset( | |
IMAGE_LAYER_T *il, | |
int32_t xOffset, | |
int32_t yOffset, | |
DISPMANX_DISPLAY_HANDLE_T display, | |
DISPMANX_UPDATE_HANDLE_T update) | |
{ | |
vc_dispmanx_rect_set(&(il->srcRect), | |
0 << 16, | |
0 << 16, | |
il->image.width << 16, | |
il->image.height << 16); | |
vc_dispmanx_rect_set(&(il->dstRect), | |
xOffset, | |
yOffset, | |
il->image.width, | |
il->image.height); | |
addElementImageLayer(il, display, update); | |
} | |
void addElementImageLayer( | |
IMAGE_LAYER_T *il, | |
DISPMANX_DISPLAY_HANDLE_T display, | |
DISPMANX_UPDATE_HANDLE_T update) | |
{ | |
VC_DISPMANX_ALPHA_T alpha = | |
{ | |
DISPMANX_FLAGS_ALPHA_FROM_SOURCE, | |
255, /*alpha 0->255*/ | |
0}; | |
il->element = | |
vc_dispmanx_element_add(update, | |
display, | |
il->layer, | |
&(il->dstRect), | |
il->resource, | |
&(il->srcRect), | |
DISPMANX_PROTECTION_NONE, | |
&alpha, | |
NULL, // clamp | |
DISPMANX_NO_ROTATE); | |
assert(il->element != 0); | |
} | |
void createResourceImageLayer( | |
IMAGE_LAYER_T *il, | |
int32_t layer) | |
{ | |
uint32_t vc_image_ptr; | |
int result = 0; | |
il->layer = layer; | |
il->resource = | |
vc_dispmanx_resource_create( | |
il->image.type, | |
il->image.width | (il->image.pitch << 16), | |
il->image.height | (il->image.alignedHeight << 16), | |
&vc_image_ptr); | |
assert(il->resource != 0); | |
vc_dispmanx_rect_set(&(il->bmpRect), | |
0, | |
0, | |
il->image.width, | |
il->image.height); | |
result = vc_dispmanx_resource_write_data(il->resource, | |
il->image.type, | |
il->image.pitch, | |
il->image.buffer, | |
&(il->bmpRect)); | |
//std::cout << il->image.pitch << std::endl; | |
assert(result == 0); | |
} | |
void initBackgroundLayer( | |
BACKGROUND_LAYER_T *bg, | |
uint16_t colour, | |
int32_t layer) | |
{ | |
int result = 0; | |
VC_IMAGE_TYPE_T type = VC_IMAGE_RGBA16; | |
uint32_t vc_image_ptr; | |
bg->resource = vc_dispmanx_resource_create(type, 1, 1, &vc_image_ptr); | |
assert(bg->resource != 0); | |
VC_RECT_T dst_rect; | |
vc_dispmanx_rect_set(&dst_rect, 0, 0, 1, 1); | |
bg->layer = layer; | |
result = vc_dispmanx_resource_write_data(bg->resource, | |
type, | |
sizeof(colour), | |
&colour, | |
&dst_rect); | |
assert(result == 0); | |
} | |
void destroyBackgroundLayer( | |
BACKGROUND_LAYER_T *bg) | |
{ | |
int result = 0; | |
DISPMANX_UPDATE_HANDLE_T update = vc_dispmanx_update_start(0); | |
assert(update != 0); | |
result = vc_dispmanx_element_remove(update, bg->element); | |
assert(result == 0); | |
result = vc_dispmanx_update_submit_sync(update); | |
assert(result == 0); | |
result = vc_dispmanx_resource_delete(bg->resource); | |
assert(result == 0); | |
} | |
void destroyImageLayer( | |
IMAGE_LAYER_T *il) | |
{ | |
int result = 0; | |
DISPMANX_UPDATE_HANDLE_T update = vc_dispmanx_update_start(0); | |
assert(update != 0); | |
result = vc_dispmanx_element_remove(update, il->element); | |
assert(result == 0); | |
result = vc_dispmanx_update_submit_sync(update); | |
assert(result == 0); | |
result = vc_dispmanx_resource_delete(il->resource); | |
assert(result == 0); | |
destroyImage(&(il->image)); | |
} | |
int main(int argc, char **argv) | |
{ | |
uint16_t background = 0x000F; | |
int32_t layer = 1; | |
uint32_t displayNumber = 0; | |
uint32_t timeout = 0; | |
cv::Mat opencv_image = cv::imread(argv[1]); | |
int w = opencv_image.cols; | |
int h = opencv_image.rows; | |
//std::cout << w << " " << h << std::endl; | |
IMAGE_LAYER_T imageLayer; | |
IMAGE_T *image = &(imageLayer.image); | |
VC_IMAGE_TYPE_T type = VC_IMAGE_RGB888; | |
initImage(image, w, h); | |
image->buffer = (uint8_t *)opencv_image.data; | |
bcm_host_init(); | |
DISPMANX_DISPLAY_HANDLE_T display = vc_dispmanx_display_open(displayNumber); | |
assert(display != 0); | |
DISPMANX_MODEINFO_T info; | |
int result = vc_dispmanx_display_get_info(display, &info); | |
assert(result == 0); | |
BACKGROUND_LAYER_T backgroundLayer; | |
if (background > 0) { | |
initBackgroundLayer(&backgroundLayer, background, 0); | |
} | |
createResourceImageLayer(&imageLayer, layer); | |
DISPMANX_UPDATE_HANDLE_T update = vc_dispmanx_update_start(0); | |
assert(update != 0); | |
addElementImageLayerOffset(&imageLayer, | |
0, | |
0, | |
display, | |
update); | |
result = vc_dispmanx_update_submit_sync(update); | |
assert(result == 0); | |
uint32_t currentTime = 0; | |
const int sleepMilliseconds = 10; | |
while (run) { | |
usleep(sleepMilliseconds * 1000); | |
currentTime += sleepMilliseconds; | |
if (timeout != 0 && currentTime >= timeout) { | |
run = false; | |
} | |
} | |
if (background > 0) { | |
destroyBackgroundLayer(&backgroundLayer); | |
} | |
destroyImageLayer(&imageLayer); | |
result = vc_dispmanx_display_close(display); | |
assert(result == 0); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment