summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugen Friedrich <efriedrich@de.adit-jv.com>2020-07-07 17:37:45 +0200
committerEugen Friedrich <efriedrich@de.adit-jv.com>2020-07-07 17:37:45 +0200
commit9bc63f152c48c5078bca8353c8d8f30293603257 (patch)
treeeb82f70dda622701dd5dd4134b3fd1df61a8551e
parent07930bf0248b4500484238d30a6b34cd0f471174 (diff)
parentee7626d9ceb4bc15ec0d27820b701dad4dd3be02 (diff)
downloadwayland-ivi-extension-9bc63f152c48c5078bca8353c8d8f30293603257.tar.gz
Merge remote-tracking branch 'upstream/pull/117'
* upstream/pull/117 ilmControl: add support for saving screenshot as png file Reviewed-by: Eugen Friedrich <efriedrich@de.adit-jv.com> Reviewed-by: Michael Rodin <mrodin@de.adit-jv.com> Tested-by: Eugen Friedrich <efriedrich@de.adit-jv.com>
-rw-r--r--ivi-layermanagement-api/ilmControl/CMakeLists.txt2
-rw-r--r--ivi-layermanagement-api/ilmControl/src/bitmap.c103
-rw-r--r--ivi-layermanagement-api/ilmControl/src/bitmap.h3
-rw-r--r--ivi-layermanagement-api/ilmControl/src/ilm_control_wayland_platform.c85
-rw-r--r--ivi-layermanagement-api/ilmControl/src/writepng.c218
-rw-r--r--ivi-layermanagement-api/ilmControl/src/writepng.h31
6 files changed, 364 insertions, 78 deletions
diff --git a/ivi-layermanagement-api/ilmControl/CMakeLists.txt b/ivi-layermanagement-api/ilmControl/CMakeLists.txt
index 4265ef9..f6bc551 100644
--- a/ivi-layermanagement-api/ilmControl/CMakeLists.txt
+++ b/ivi-layermanagement-api/ilmControl/CMakeLists.txt
@@ -76,6 +76,7 @@ link_directories(
add_library(${PROJECT_NAME} SHARED
src/ilm_control_wayland_platform.c
src/bitmap.c
+ src/writepng.c
ivi-wm-client-protocol.h
ivi-wm-protocol.c
ivi-input-client-protocol.h
@@ -90,6 +91,7 @@ set(LIBS
${LIBS}
rt
dl
+ png
${CMAKE_THREAD_LIBS_INIT}
${WAYLAND_CLIENT_LIBRARIES}
)
diff --git a/ivi-layermanagement-api/ilmControl/src/bitmap.c b/ivi-layermanagement-api/ilmControl/src/bitmap.c
index 2c7fdb5..79d2a5d 100644
--- a/ivi-layermanagement-api/ilmControl/src/bitmap.c
+++ b/ivi-layermanagement-api/ilmControl/src/bitmap.c
@@ -21,6 +21,11 @@
*/
#include "bitmap.h"
#include <stdio.h>
+#include <stdlib.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <arpa/inet.h>
+#include "ivi-wm-client-protocol.h"
struct __attribute__ ((__packed__)) BITMAPFILEHEADER {
char bfType[2];
@@ -49,22 +54,22 @@ create_file_header(struct BITMAPFILEHEADER *file_header, int32_t image_size)
{
file_header->bfType[0] = 'B';
file_header->bfType[1] = 'M';
- file_header->bfSize = sizeof(struct BITMAPFILEHEADER)
- + sizeof(struct BITMAPINFOHEADER)
- + image_size;
- file_header->bfOffBits = sizeof(struct BITMAPFILEHEADER)
- + sizeof(struct BITMAPINFOHEADER);
+ file_header->bfSize = htole32(sizeof(struct BITMAPFILEHEADER) +
+ sizeof(struct BITMAPINFOHEADER) +
+ image_size);
+ file_header->bfOffBits = htole32(sizeof(struct BITMAPFILEHEADER) +
+ sizeof(struct BITMAPINFOHEADER));
}
static void
create_info_header(struct BITMAPINFOHEADER *info_header, int32_t image_size, int32_t width, int32_t height, int16_t bpp)
{
- info_header->biSize = sizeof(struct BITMAPINFOHEADER);
- info_header->biWidth = width;
- info_header->biHeight = height;
- info_header->biPlanes = 1;
- info_header->biBitCount = bpp;
- info_header->biSizeImage = image_size;
+ info_header->biSize = htole32(sizeof(struct BITMAPINFOHEADER));
+ info_header->biWidth = htole32(width);
+ info_header->biHeight = htole32(height);
+ info_header->biPlanes = htole16(1);
+ info_header->biBitCount = htole16(bpp);
+ info_header->biSizeImage = htole32(image_size);
}
static int
@@ -89,19 +94,87 @@ write_bitmap(const char *filename,
int
save_as_bitmap(const char *filename,
const char *buffer,
- int32_t image_size,
int32_t width,
int32_t height,
- int16_t bpp)
+ uint32_t format)
{
+ int32_t image_stride = 0;
+ int32_t image_size = 0;
+ char *image_buffer = NULL;
+ int32_t row = 0;
+ int32_t col = 0;
+ int32_t image_offset = 0;
+ int32_t offset = 0;
+ int32_t i = 0;
+ int32_t j = 0;
+ int bytes_per_pixel;
+ bool flip_order;
+ bool has_alpha;
+
if ((filename == NULL) || (buffer == NULL)) {
return -1;
}
+ switch (format) {
+ case WL_SHM_FORMAT_ARGB8888:
+ flip_order = true;
+ has_alpha = true;
+ break;
+ case WL_SHM_FORMAT_XRGB8888:
+ flip_order = true;
+ has_alpha = false;
+ break;
+ case WL_SHM_FORMAT_ABGR8888:
+ flip_order = false;
+ has_alpha = true;
+ break;
+ case WL_SHM_FORMAT_XBGR8888:
+ flip_order = false;
+ has_alpha = false;
+ break;
+ default:
+ fprintf(stderr, "unsupported pixelformat 0x%x\n", format);
+ return -1;
+ }
+
+ bytes_per_pixel = has_alpha ? 4 : 3;
+ image_stride = (((width * bytes_per_pixel) + 3) & ~3);
+ image_size = image_stride * height;
+
+ image_buffer = malloc(image_size);
+ if (image_buffer == NULL) {
+ fprintf(stderr, "failed to allocate %d bytes for image buffer: %m\n",
+ image_size);
+ return -1;
+ }
+
+ // Store the image in image_buffer in the follwing order B, G, R, [A](B at the lowest address)
+ for (row = 0; row < height; ++row) {
+ for (col = 0; col < width; ++col) {
+ offset = (height - row - 1) * width + col;
+ uint32_t pixel = htonl(((uint32_t*)buffer)[offset]);
+ char * pixel_p = (char*) &pixel;
+ image_offset = row * image_stride + col * bytes_per_pixel;
+ for (i = 0; i < 3; ++i) {
+ j = flip_order ? 2 - i : i;
+ image_buffer[image_offset + i] = pixel_p[1 + j];
+ }
+ if (has_alpha) {
+ image_buffer[image_offset + 3] = pixel_p[0];
+ }
+ }
+ }
+
struct BITMAPFILEHEADER file_header = {};
struct BITMAPINFOHEADER info_header = {};
create_file_header(&file_header, image_size);
- create_info_header(&info_header, image_size, width, height, bpp);
- return write_bitmap(filename, &file_header, &info_header, buffer);
+ create_info_header(&info_header, image_size, width, height, bytes_per_pixel * 8);
+ if (write_bitmap(filename, &file_header, &info_header, image_buffer) != 0) {
+ free(image_buffer);
+ return -1;
+ }
+
+ free(image_buffer);
+ return 0;
}
diff --git a/ivi-layermanagement-api/ilmControl/src/bitmap.h b/ivi-layermanagement-api/ilmControl/src/bitmap.h
index 3cef52d..4b8520c 100644
--- a/ivi-layermanagement-api/ilmControl/src/bitmap.h
+++ b/ivi-layermanagement-api/ilmControl/src/bitmap.h
@@ -26,10 +26,9 @@
int save_as_bitmap(const char *filename,
const char *buffer,
- int32_t image_size,
int32_t width,
int32_t height,
- int16_t bpp
+ uint32_t format
);
#endif /* IVICONTROLLER_BITMAP_H_*/
diff --git a/ivi-layermanagement-api/ilmControl/src/ilm_control_wayland_platform.c b/ivi-layermanagement-api/ilmControl/src/ilm_control_wayland_platform.c
index a912e50..be7c5a3 100644
--- a/ivi-layermanagement-api/ilmControl/src/ilm_control_wayland_platform.c
+++ b/ivi-layermanagement-api/ilmControl/src/ilm_control_wayland_platform.c
@@ -30,6 +30,7 @@
#include <sys/mman.h>
#include <sys/eventfd.h>
+#include "writepng.h"
#include "bitmap.h"
#include "ilm_common.h"
#include "ilm_control_platform.h"
@@ -2061,43 +2062,16 @@ static void screenshot_done(void *data, struct ivi_screenshot *ivi_screenshot,
{
struct screenshot_context *ctx_scrshot = data;
char *buffer;
- int32_t image_stride = 0;
- int32_t image_size = 0;
- char *image_buffer = NULL;
- int32_t row = 0;
- int32_t col = 0;
- int32_t image_offset = 0;
- int32_t offset = 0;
- int32_t i = 0;
- int32_t j = 0;
size_t size = stride * height;
- int bytes_per_pixel;
- bool flip_order;
- bool has_alpha;
const char *filename = ctx_scrshot->filename;
+ char *filename_ext = NULL;
ctx_scrshot->filename = NULL;
ivi_screenshot_destroy(ivi_screenshot);
- switch (format) {
- case WL_SHM_FORMAT_ARGB8888:
- flip_order = false;
- has_alpha = true;
- break;
- case WL_SHM_FORMAT_XRGB8888:
- flip_order = false;
- has_alpha = false;
- break;
- case WL_SHM_FORMAT_ABGR8888:
- flip_order = true;
- has_alpha = true;
- break;
- case WL_SHM_FORMAT_XBGR8888:
- flip_order = true;
- has_alpha = false;
- break;
- default:
- fprintf(stderr, "unsupported pixelformat 0x%x\n", format);
+ if (filename == NULL) {
+ ctx_scrshot->result = ILM_FAILED;
+ fprintf(stderr, "screenshot file name not provided: %m\n");
return;
}
@@ -2105,45 +2079,34 @@ static void screenshot_done(void *data, struct ivi_screenshot *ivi_screenshot,
close(fd);
if (buffer == MAP_FAILED) {
+ ctx_scrshot->result = ILM_FAILED;
fprintf(stderr, "failed to mmap screenshot file: %m\n");
return;
}
- bytes_per_pixel = has_alpha ? 4 : 3;
- image_stride = (((width * bytes_per_pixel) + 3) & ~3);
- image_size = image_stride * height;
-
- image_buffer = malloc(image_size);
- if (image_buffer == NULL) {
- fprintf(stderr, "failed to allocate %d bytes for image buffer: %m\n",
- image_size);
- munmap(buffer, size);
- return;
- }
+ if ((filename_ext = strstr(filename, ".png")) && (strlen(filename_ext) == 4)) {
+ if (save_as_png(filename, (const char *)buffer,
+ width, height, format) == 0) {
+ ctx_scrshot->result = ILM_SUCCESS;
+ } else {
+ ctx_scrshot->result = ILM_FAILED;
+ fprintf(stderr, "failed to write screenshot as png file: %m\n");
+ }
+ } else {
+ if (!((filename_ext = strstr(filename, ".bmp")) && (strlen(filename_ext) == 4))) {
+ fprintf(stderr, "trying to write screenshot as bmp file, although file extension does not match: %m\n");
+ }
- for (row = 0; row < height; ++row) {
- for (col = 0; col < width; ++col) {
- offset = (height - row - 1) * width + col;
- image_offset = row * image_stride + col * bytes_per_pixel;
- for (i = 0; i < 3; ++i) {
- j = flip_order ? 2 - i : i;
- image_buffer[image_offset + i] = buffer[offset * 4 + j];
- }
- if (has_alpha)
- image_buffer[image_offset + 3] = buffer[offset * 4 + 3];
+ if (save_as_bitmap(filename, (const char *)buffer,
+ width, height, format) == 0) {
+ ctx_scrshot->result = ILM_SUCCESS;
+ } else {
+ ctx_scrshot->result = ILM_FAILED;
+ fprintf(stderr, "failed to write screenshot as bmp file: %m\n");
}
}
munmap(buffer, size);
-
- if (save_as_bitmap(filename, (const char *)image_buffer,
- image_size, width, height, bytes_per_pixel * 8) == 0) {
- ctx_scrshot->result = ILM_SUCCESS;
- } else {
- fprintf(stderr, "failed to write screenshot file: %m\n");
- }
-
- free(image_buffer);
}
static void screenshot_error(void *data, struct ivi_screenshot *ivi_screenshot,
diff --git a/ivi-layermanagement-api/ilmControl/src/writepng.c b/ivi-layermanagement-api/ilmControl/src/writepng.c
new file mode 100644
index 0000000..bf712b5
--- /dev/null
+++ b/ivi-layermanagement-api/ilmControl/src/writepng.c
@@ -0,0 +1,218 @@
+/***************************************************************************
+ *
+ * Copyright (C) 2020 Advanced Driver Information Technology Joint Venture GmbH
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <arpa/inet.h>
+#include "png.h"
+#include "ivi-wm-client-protocol.h"
+#include "writepng.h"
+
+typedef struct _image_info {
+ png_structp png_ptr;
+ png_infop info_ptr;
+ jmp_buf jmpbuf;
+ FILE *outfile;
+} image_info;
+
+
+static void
+writepng_error_handler(png_structp png_ptr,
+ png_const_charp msg)
+{
+ fprintf(stderr, "writepng libpng error: %s\n", msg);
+}
+
+static int
+create_png_header(image_info *info,
+ int32_t width,
+ int32_t height,
+ uint32_t format)
+{
+ int color_type = 0;
+ int sample_depth = 8;
+
+ info->info_ptr = png_create_info_struct(info->png_ptr);
+ if (!info->info_ptr) {
+ fprintf(stderr, "png_create_info_struct: failed, out of memory\n");
+ png_destroy_write_struct(&info->png_ptr, NULL);
+ return -1;
+ }
+
+ if (setjmp(info->jmpbuf)) {
+ fprintf(stderr, "setjmp: failed\n");
+ png_destroy_write_struct(&info->png_ptr, &info->info_ptr);
+ return -1;
+ }
+
+ png_init_io(info->png_ptr, info->outfile);
+
+ png_set_compression_level(info->png_ptr, PNG_Z_DEFAULT_COMPRESSION);
+
+ switch (format) {
+ case WL_SHM_FORMAT_ARGB8888:
+ color_type = PNG_COLOR_TYPE_RGB_ALPHA;
+ png_set_swap_alpha(info->png_ptr);
+ break;
+ case WL_SHM_FORMAT_XRGB8888:
+ color_type = PNG_COLOR_TYPE_RGB;
+ break;
+ case WL_SHM_FORMAT_ABGR8888:
+ color_type = PNG_COLOR_TYPE_RGB_ALPHA;
+ png_set_bgr(info->png_ptr);
+ png_set_swap_alpha(info->png_ptr);
+ break;
+ case WL_SHM_FORMAT_XBGR8888:
+ color_type = PNG_COLOR_TYPE_RGB;
+ png_set_bgr(info->png_ptr);
+ break;
+ default:
+ fprintf(stderr, "unsupported pixelformat 0x%x\n", format);
+ return -1;
+ }
+
+ png_set_IHDR(info->png_ptr, info->info_ptr, width, height,
+ sample_depth, color_type, PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
+
+ png_write_info(info->png_ptr, info->info_ptr);
+
+ return 0;
+}
+
+static int
+write_png_file(image_info *info,
+ const char *buffer,
+ int32_t width,
+ int32_t height,
+ uint32_t format,
+ int bytes_per_pixel)
+{
+ info->png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,
+ writepng_error_handler, NULL);
+ if (!info->png_ptr) {
+ fprintf(stderr, "png_create_write_struct: failed, out of memory\n");
+ return -1;
+ }
+
+ if (create_png_header(info, width, height, format) != 0) {
+ return -1;
+ }
+
+ for(int j = 0; j < height ; ++j) {
+ png_const_bytep pointer = (png_const_bytep)buffer;
+ pointer += j * width * bytes_per_pixel;
+
+ if (setjmp(info->jmpbuf)) {
+ fprintf(stderr, "setjmp: failed, j=%d\n", j);
+ png_destroy_write_struct(&info->png_ptr, &info->info_ptr);
+ info->png_ptr = NULL;
+ info->info_ptr = NULL;
+ return -1;
+ }
+
+ png_write_row(info->png_ptr, pointer);
+ }
+
+ if (setjmp(info->jmpbuf)) {
+ fprintf(stderr, "final setjmp failed\n");
+ png_destroy_write_struct(&info->png_ptr, &info->info_ptr);
+ info->png_ptr = NULL;
+ info->info_ptr = NULL;
+ return -1;
+ }
+
+ png_write_end(info->png_ptr, NULL);
+
+ if (info->png_ptr && info->info_ptr) {
+ png_destroy_write_struct(&info->png_ptr, &info->info_ptr);
+ }
+
+ return 0;
+}
+
+int
+save_as_png(const char *filename,
+ const char *buffer,
+ int32_t width,
+ int32_t height,
+ uint32_t format)
+{
+ int32_t image_stride = 0;
+ int32_t image_size = 0;
+ char *image_buffer = NULL;
+ int32_t row = 0;
+ int32_t col = 0;
+ int32_t image_offset = 0;
+ int32_t offset = 0;
+ int bytes_per_pixel = 0;
+ bool has_alpha = false;
+ image_info info;
+
+ if ((filename == NULL) || (buffer == NULL)) {
+ return -1;
+ }
+
+ info.outfile = fopen(filename, "wb");
+ if (!info.outfile) {
+ fprintf(stderr, "could not open the file %s\n", filename);
+ return -1;
+ }
+
+ switch (format) {
+ case WL_SHM_FORMAT_ARGB8888:
+ case WL_SHM_FORMAT_ABGR8888:
+ has_alpha = true;
+ break;
+ default:
+ has_alpha = false;
+ break;
+ }
+
+ bytes_per_pixel = has_alpha ? 4 : 3;
+ image_stride = (((width * bytes_per_pixel) + 3) & ~3);
+ image_size = image_stride * height;
+
+ image_buffer = malloc(image_size);
+ if (image_buffer == NULL) {
+ fprintf(stderr, "failed to allocate %d bytes for image buffer: %m\n",
+ image_size);
+ return -1;
+ }
+
+ for (row = 0; row < height; ++row) {
+ for (col = 0; col < width; ++col) {
+ offset = row * width + col;
+ uint32_t pixel = htonl(((uint32_t*)buffer)[offset]);
+ char * pixel_p = (char*) &pixel;
+ image_offset = row * image_stride + col * bytes_per_pixel;
+ for (int i=0; i<bytes_per_pixel; ++i){
+ image_buffer[image_offset + i] = pixel_p[i + (has_alpha ? 0 : 1)];
+ }
+ }
+ }
+
+ if (write_png_file(&info, image_buffer, width, height, format, bytes_per_pixel) != 0) {
+ free(image_buffer);
+ return -1;
+ }
+
+ free(image_buffer);
+ return 0;
+}
diff --git a/ivi-layermanagement-api/ilmControl/src/writepng.h b/ivi-layermanagement-api/ilmControl/src/writepng.h
new file mode 100644
index 0000000..0331a0a
--- /dev/null
+++ b/ivi-layermanagement-api/ilmControl/src/writepng.h
@@ -0,0 +1,31 @@
+/***************************************************************************
+ *
+ * Copyright (C) 2020 Advanced Driver Information Technology Joint Venture GmbH
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+#ifndef IVICONTROLLER_WRITEPNG_H_
+#define IVICONTROLLER_WRITEPNG_H_
+
+#include <stdint.h>
+
+int
+save_as_png(const char *filename,
+ const char *buffer,
+ int32_t width,
+ int32_t height,
+ uint32_t format);
+
+#endif /* IVICONTROLLER_WRITEPNG_H_ */