Merge pull request #2239 from socram8888/waveshare-gd

Add image cropping and scaling
This commit is contained in:
Iceman 2024-01-07 22:48:38 +01:00 committed by GitHub
commit e2a3aea75b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 77 additions and 16 deletions

View file

@ -9,6 +9,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
- Fixed `lf pyramid sim` - wrong parameter handling (@iceman1001)
- Fixed bootloader - Ignore jitters when pressing the button (@wh201906)
- Changed `hf waveshare` - image loading and processing is now done using [GDlib](https://github.com/libgd/libgd) (@socram8888)
- Changed `hf waveshare` - image is automatically scaled and cropped to match panel size (@socram8888)
## [Steamboat Willie.4.17768][2024-01-03]
- Changed `mem spiffs dump -t` - now supports downloading direct into trace buffer (@hazardousvoltage)

View file

@ -631,14 +631,13 @@ static int CmdHF14AWSLoad(const char *Cmd) {
return PM3_EFILE;
}
if (
gdImageSX(rgb_img) != models[model_nr].width ||
gdImageSY(rgb_img) != models[model_nr].height
) {
PrintAndLogEx(WARNING, "Image size does not match panel size");
gdImagePtr scaled_img = img_crop_to_fit(rgb_img, models[model_nr].width, models[model_nr].height);
if (scaled_img == NULL) {
PrintAndLogEx(WARNING, "Failed to scale input image");
gdImageDestroy(rgb_img);
return PM3_EFILE;
}
gdImageDestroy(rgb_img);
int pal_len = 2;
int pal[3];
@ -649,8 +648,8 @@ static int CmdHF14AWSLoad(const char *Cmd) {
pal[2] = gdTrueColorAlpha(0xFF, 0x00, 0x00, 0); // Red
}
gdImagePtr pal_img = img_palettize(rgb_img, pal, pal_len);
gdImageDestroy(rgb_img);
gdImagePtr pal_img = img_palettize(scaled_img, pal, pal_len);
gdImageDestroy(scaled_img);
if (!pal_img) {
PrintAndLogEx(WARNING, "Could not convert image");
@ -662,7 +661,7 @@ static int CmdHF14AWSLoad(const char *Cmd) {
PrintAndLogEx(INFO, "Save converted image to " _YELLOW_("%s"), outfile);
gdImageDestroy(pal_img);
return PM3_SUCCESS;
} else {
} else {
PrintAndLogEx(WARNING, "Could not save converted image", outfile);
gdImageDestroy(pal_img);
return PM3_EFILE;

View file

@ -33,14 +33,6 @@ static inline void cap_comp(int * x) {
}
}
/*
* The following function implements a Floyd-Steinberg in YCbCr color space.
*
* Using this colorspace, the Euclidean distance between colors is closer to human perception than
* in sRGB, which results in a more accurate color rendering.
*
* A comparison can be found at https://twitter.com/Socram4x8/status/1733157380097995205/photo/1.
*/
gdImagePtr img_palettize(gdImagePtr rgb, int * palette, int palette_size) {
assert(rgb != NULL);
assert(palette != NULL);
@ -157,3 +149,58 @@ gdImagePtr img_palettize(gdImagePtr rgb, int * palette, int palette_size) {
free(pal_ycbcr);
return res;
}
gdImagePtr img_crop_to_fit(gdImagePtr orig, int width, int height) {
assert(orig != NULL);
assert(width >= 1);
assert(height >= 1);
gdImagePtr res;
if (gdImageTrueColor(orig)) {
res = gdImageCreateTrueColor(width, height);
} else {
res = gdImageCreate(width, height);
}
if (!res) {
return NULL;
}
if (gdImageSY(orig) * width <= gdImageSX(orig) * height) {
// Image is wider than expected, so we will crop the left and right sides
int crop_width = gdImageSY(orig) * width / height;
int crop_sx = gdImageSX(orig) / 2 - crop_width / 2;
gdImageCopyResampled(
res, // Dest img
orig, // Src image
0, // Dest X
0, // Dest Y
crop_sx, // Src X
0, // Src Y
width, // Dest width
height, // Dest height
crop_width, // Src width
gdImageSY(orig) // Src height
);
} else {
// Image is taller than expected, so we will crop the top and bottom sides
int crop_height = gdImageSX(orig) * height / width;
int crop_sy = gdImageSY(orig) / 2 - crop_height / 2;
gdImageCopyResampled(
res, // Dest img
orig, // Src image
0, // Dest X
0, // Dest Y
0, // Src X
crop_sy, // Src Y
width, // Dest width
height, // Dest height
gdImageSX(orig), // Src width
crop_height // Src height
);
}
return res;
}

View file

@ -20,6 +20,20 @@
#include <gd.h>
/*
* Converts a true color image to a palette image, using Floyd-Steinberg dithering.
*
* For color matching, this function uses the Euclidean distance between colors in the
* YCbCr color space, which yields to better results than using sRGB directly.
*
* A comparison can be found at https://twitter.com/Socram4x8/status/1733157380097995205/photo/1.
*/
gdImagePtr img_palettize(gdImagePtr rgb, int * palette, int palette_size);
/*
* This function scales and crops the image to the given size.
* Think of "background-size: cover" in CSS.
*/
gdImagePtr img_crop_to_fit(gdImagePtr orig, int width, int height);
#endif