pebble/tests/fw/graphics/util_pbi.h

133 lines
4 KiB
C
Raw Permalink Normal View History

/*
* Copyright 2024 Google LLC
*
* 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.
*/
#pragma once
#include "applib/graphics/gtypes.h"
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
#define PATH_STRING_LENGTH 512
extern GBitmapDataRowInfo prv_gbitmap_get_data_row_info(const GBitmap *bitmap, uint16_t y);
bool write_gbitmap_to_pbi(GBitmap *bmp, const char *filepath, const char *pbi2png_path) {
char pbi_path[PATH_STRING_LENGTH];
char png_path[PATH_STRING_LENGTH];
char *ext = NULL;
strncpy(pbi_path, filepath, sizeof(pbi_path));
ext = strrchr(pbi_path, '.');
strncpy(ext + 1, "pbi", 3);
strncpy(png_path, filepath, sizeof(png_path));
ext = strrchr(png_path, '.');
strncpy(ext + 1, "png", 3);
FILE *file = fopen(pbi_path, "w");
if (!file) {
printf("Unable to open file: %s\n", pbi_path);
return false;
}
// Just in case this output bitmap was created by hand.
bmp->info.version = GBITMAP_VERSION_CURRENT;
// PBL-24228 Support Circular PBIs
uint16_t info_flags = bmp->info_flags;
#ifdef PLATFORM_SPALDING
if(bmp->info.format == GBitmapFormat8BitCircular) {
// Have to force output format to 8Bit;
((BitmapInfo*)&info_flags)->format = GBitmapFormat8Bit;
}
#endif
// use entire bounds to include entire image
GRect entire_bounds = GRect(0, 0,
bmp->bounds.origin.x + bmp->bounds.size.w,
bmp->bounds.origin.y + bmp->bounds.size.h);
fwrite(&bmp->row_size_bytes, sizeof(bmp->row_size_bytes), 1, file);
fwrite(&info_flags, 2, 1, file);
fwrite(&entire_bounds, sizeof(GRect), 1, file);
#ifdef PLATFORM_SPALDING
if(bmp->info.format == GBitmapFormat8BitCircular) {
for (int y = 0; y < entire_bounds.size.h; ++y) {
// 8-Bit circular buffer is centered in padded rows, so just grab row and write DISP_COLS
const GBitmapDataRowInfo dest_row_info = prv_gbitmap_get_data_row_info(bmp, y);
uint8_t *bmp_row = dest_row_info.data;
int x = 0;
const uint8_t blank = 0;
// PBL-24229 missing mask: data outside of circle is garbage from previous and next rows
// Pad with blanks before min_x
while (x < dest_row_info.min_x) {
fwrite(&blank, 1, 1, file);
x++;
}
if (x <= dest_row_info.max_x) {
int length = dest_row_info.max_x - x + 1;
fwrite(&bmp_row[dest_row_info.min_x], 1, length, file);
x += length;
}
// Pad with blanks after max_x
while (x < entire_bounds.size.w) {
fwrite(&blank, 1, 1, file);
x++;
}
}
} else {
#endif
size_t data_size = bmp->row_size_bytes * (entire_bounds.size.h);
fwrite(bmp->addr, 1, data_size, file);
#ifdef PLATFORM_SPALDING
}
#endif
uint8_t palette_size = gbitmap_get_palette_size(gbitmap_get_format(bmp));
if (palette_size > 0) {
fwrite(bmp->palette, 1, palette_size * sizeof(*bmp->palette), file);
}
fclose(file);
printf("PBI file written to: %s\n", pbi_path);
int pid = fork();
if (pid == 0) {
char *args[] = {
"python",
(char *)pbi2png_path,
(char *)pbi_path,
(char *)png_path,
NULL,
};
execvp("python", args);
perror("execv"); // Error internal to execve
exit(EXIT_FAILURE);
}
int status;
if (wait(&status) >= 0 && !WIFEXITED(status)) {
printf("FAILURE: pbi2png.py process exited with %d status. PNG file not written\n",
WEXITSTATUS(status));
} else {
printf("PNG file written to: %s\n", png_path);
}
return true;
}