Skip to content

Instantly share code, notes, and snippets.

@czoido
Created August 10, 2019 17:31
Show Gist options
  • Save czoido/8b829a285855e372ee8c039040355656 to your computer and use it in GitHub Desktop.
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
#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