mirror of
https://github.com/LostArtefacts/TRX.git
synced 2025-05-08 11:38:16 +03:00
s/picture: use bilinear scaling
This commit is contained in:
parent
d3e28825fa
commit
0882d6371f
5 changed files with 138 additions and 24 deletions
|
@ -3,6 +3,8 @@
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "specific/s_picture.h"
|
#include "specific/s_picture.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
PICTURE *Picture_Create()
|
PICTURE *Picture_Create()
|
||||||
{
|
{
|
||||||
PICTURE *picture = Memory_Alloc(sizeof(picture));
|
PICTURE *picture = Memory_Alloc(sizeof(picture));
|
||||||
|
@ -25,6 +27,15 @@ PICTURE *Picture_CreateFromFile(const char *file_path)
|
||||||
return picture;
|
return picture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Picture_Scale(
|
||||||
|
PICTURE *target_pic, const PICTURE *source_pic, size_t target_width,
|
||||||
|
size_t target_height)
|
||||||
|
{
|
||||||
|
assert(target_pic);
|
||||||
|
assert(source_pic);
|
||||||
|
return S_Picture_Scale(target_pic, source_pic, target_width, target_height);
|
||||||
|
}
|
||||||
|
|
||||||
void Picture_Free(PICTURE *picture)
|
void Picture_Free(PICTURE *picture)
|
||||||
{
|
{
|
||||||
if (picture) {
|
if (picture) {
|
||||||
|
|
|
@ -9,4 +9,8 @@ PICTURE *Picture_Create();
|
||||||
PICTURE *Picture_CreateFromFile(const char *file_path);
|
PICTURE *Picture_CreateFromFile(const char *file_path);
|
||||||
void Picture_Free(PICTURE *picture);
|
void Picture_Free(PICTURE *picture);
|
||||||
|
|
||||||
|
bool Picture_Scale(
|
||||||
|
PICTURE *target_pic, const PICTURE *source_pic, size_t target_width,
|
||||||
|
size_t target_height);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -142,10 +142,17 @@ void S_AnimateTextures(int32_t ticks)
|
||||||
|
|
||||||
void S_DisplayPicture(const char *filename)
|
void S_DisplayPicture(const char *filename)
|
||||||
{
|
{
|
||||||
PICTURE *picture = Picture_CreateFromFile(filename);
|
PICTURE *orig_pic = Picture_CreateFromFile(filename);
|
||||||
if (picture) {
|
if (orig_pic) {
|
||||||
HWR_DownloadPicture(picture);
|
PICTURE *scaled_pic = Picture_Create();
|
||||||
Picture_Free(picture);
|
if (scaled_pic) {
|
||||||
|
Picture_Scale(
|
||||||
|
scaled_pic, orig_pic, g_DDrawSurfaceWidth,
|
||||||
|
g_DDrawSurfaceHeight);
|
||||||
|
HWR_DownloadPicture(scaled_pic);
|
||||||
|
Picture_Free(scaled_pic);
|
||||||
|
}
|
||||||
|
Picture_Free(orig_pic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,13 +4,17 @@
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <libavcodec/avcodec.h>
|
#include <libavcodec/avcodec.h>
|
||||||
#include <libavformat/avformat.h>
|
#include <libavformat/avformat.h>
|
||||||
#include <libavutil/imgutils.h>
|
#include <libavutil/imgutils.h>
|
||||||
#include <libswscale/swscale.h>
|
#include <libswscale/swscale.h>
|
||||||
|
|
||||||
bool S_Picture_LoadFromFile(PICTURE *picture, const char *file_path)
|
bool S_Picture_LoadFromFile(PICTURE *target_pic, const char *file_path)
|
||||||
{
|
{
|
||||||
|
assert(target_pic);
|
||||||
|
assert(!target_pic->data);
|
||||||
|
|
||||||
int32_t error_code;
|
int32_t error_code;
|
||||||
char *full_path = NULL;
|
char *full_path = NULL;
|
||||||
AVFormatContext *format_ctx = NULL;
|
AVFormatContext *format_ctx = NULL;
|
||||||
|
@ -20,9 +24,9 @@ bool S_Picture_LoadFromFile(PICTURE *picture, const char *file_path)
|
||||||
struct SwsContext *sws_ctx = NULL;
|
struct SwsContext *sws_ctx = NULL;
|
||||||
AVPacket *packet = NULL;
|
AVPacket *packet = NULL;
|
||||||
|
|
||||||
picture->width = 0;
|
target_pic->width = 0;
|
||||||
picture->height = 0;
|
target_pic->height = 0;
|
||||||
picture->data = NULL;
|
target_pic->data = NULL;
|
||||||
|
|
||||||
File_GetFullPath(file_path, &full_path);
|
File_GetFullPath(file_path, &full_path);
|
||||||
|
|
||||||
|
@ -95,12 +99,13 @@ bool S_Picture_LoadFromFile(PICTURE *picture, const char *file_path)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
picture->width = frame->width;
|
target_pic->width = frame->width;
|
||||||
picture->height = frame->height;
|
target_pic->height = frame->height;
|
||||||
|
|
||||||
sws_ctx = sws_getContext(
|
sws_ctx = sws_getContext(
|
||||||
codec_ctx->width, codec_ctx->height, codec_ctx->pix_fmt, picture->width,
|
codec_ctx->width, codec_ctx->height, codec_ctx->pix_fmt,
|
||||||
picture->height, AV_PIX_FMT_RGB24, SWS_BILINEAR, NULL, NULL, NULL);
|
target_pic->width, target_pic->height, AV_PIX_FMT_RGB24, SWS_BILINEAR,
|
||||||
|
NULL, NULL, NULL);
|
||||||
|
|
||||||
if (!sws_ctx) {
|
if (!sws_ctx) {
|
||||||
LOG_ERROR("Failed to get SWS context");
|
LOG_ERROR("Failed to get SWS context");
|
||||||
|
@ -111,7 +116,7 @@ bool S_Picture_LoadFromFile(PICTURE *picture, const char *file_path)
|
||||||
uint8_t *dst_data[4];
|
uint8_t *dst_data[4];
|
||||||
int dst_linesize[4];
|
int dst_linesize[4];
|
||||||
error_code = av_image_alloc(
|
error_code = av_image_alloc(
|
||||||
dst_data, dst_linesize, picture->width, picture->height,
|
dst_data, dst_linesize, target_pic->width, target_pic->height,
|
||||||
AV_PIX_FMT_RGB24, 1);
|
AV_PIX_FMT_RGB24, 1);
|
||||||
if (error_code < 0) {
|
if (error_code < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -121,14 +126,14 @@ bool S_Picture_LoadFromFile(PICTURE *picture, const char *file_path)
|
||||||
sws_ctx, (const uint8_t *const *)frame->data, frame->linesize, 0,
|
sws_ctx, (const uint8_t *const *)frame->data, frame->linesize, 0,
|
||||||
frame->height, dst_data, dst_linesize);
|
frame->height, dst_data, dst_linesize);
|
||||||
|
|
||||||
picture->data =
|
target_pic->data =
|
||||||
Memory_Alloc(picture->height * picture->width * sizeof(RGB888));
|
Memory_Alloc(target_pic->height * target_pic->width * sizeof(RGB888));
|
||||||
|
|
||||||
av_image_copy_to_buffer(
|
av_image_copy_to_buffer(
|
||||||
(uint8_t *)picture->data,
|
(uint8_t *)target_pic->data,
|
||||||
picture->width * picture->height * sizeof(RGB888),
|
target_pic->width * target_pic->height * sizeof(RGB888),
|
||||||
(const uint8_t *const *)dst_data, dst_linesize, AV_PIX_FMT_RGB24,
|
(const uint8_t *const *)dst_data, dst_linesize, AV_PIX_FMT_RGB24,
|
||||||
picture->width, picture->height, 1);
|
target_pic->width, target_pic->height, 1);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -137,11 +142,11 @@ fail:
|
||||||
"Error while opening picture %s: %s", full_path,
|
"Error while opening picture %s: %s", full_path,
|
||||||
av_err2str(error_code));
|
av_err2str(error_code));
|
||||||
|
|
||||||
picture->width = 0;
|
target_pic->width = 0;
|
||||||
picture->height = 0;
|
target_pic->height = 0;
|
||||||
if (picture->data) {
|
if (target_pic->data) {
|
||||||
Memory_Free(picture->data);
|
Memory_Free(target_pic->data);
|
||||||
picture->data = NULL;
|
target_pic->data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sws_ctx) {
|
if (sws_ctx) {
|
||||||
|
@ -172,3 +177,87 @@ fail:
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool S_Picture_Scale(
|
||||||
|
PICTURE *target_pic, const PICTURE *source_pic, int target_width,
|
||||||
|
int target_height)
|
||||||
|
{
|
||||||
|
assert(source_pic);
|
||||||
|
assert(source_pic->data);
|
||||||
|
assert(target_pic);
|
||||||
|
assert(!target_pic->data);
|
||||||
|
|
||||||
|
int source_width = source_pic->width;
|
||||||
|
int source_height = source_pic->height;
|
||||||
|
|
||||||
|
// keep aspect ratio and fit inside, adding black bars on the sides
|
||||||
|
const float source_ratio = source_width / (float)source_height;
|
||||||
|
const float target_ratio = target_width / (float)target_height;
|
||||||
|
{
|
||||||
|
int new_width = source_ratio < target_ratio
|
||||||
|
? target_height * source_ratio
|
||||||
|
: target_width;
|
||||||
|
int new_height = source_ratio < target_ratio
|
||||||
|
? target_height
|
||||||
|
: target_width / source_ratio;
|
||||||
|
target_width = new_width;
|
||||||
|
target_height = new_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ret = false;
|
||||||
|
struct SwsContext *sws_ctx = sws_getContext(
|
||||||
|
source_width, source_height, AV_PIX_FMT_RGB24, target_width,
|
||||||
|
target_height, AV_PIX_FMT_RGB24, SWS_BILINEAR, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
if (!sws_ctx) {
|
||||||
|
LOG_ERROR("Failed to get SWS context");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
target_pic->width = target_width;
|
||||||
|
target_pic->height = target_height;
|
||||||
|
target_pic->data =
|
||||||
|
Memory_Alloc(target_height * target_width * sizeof(RGB888));
|
||||||
|
|
||||||
|
uint8_t *src_planes[4];
|
||||||
|
uint8_t *dst_planes[4];
|
||||||
|
int src_linesize[4];
|
||||||
|
int dst_linesize[4];
|
||||||
|
|
||||||
|
av_image_fill_arrays(
|
||||||
|
src_planes, src_linesize, (const uint8_t *)source_pic->data,
|
||||||
|
AV_PIX_FMT_RGB24, source_width, source_height, 1);
|
||||||
|
|
||||||
|
av_image_fill_arrays(
|
||||||
|
dst_planes, dst_linesize, (const uint8_t *)target_pic->data,
|
||||||
|
AV_PIX_FMT_RGB24, target_pic->width, target_pic->height, 1);
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
LOG_DEBUG("%p %d", src_planes[i], src_linesize[i]);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
LOG_DEBUG("%p %d", dst_planes[i], dst_linesize[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
sws_scale(
|
||||||
|
sws_ctx, (const uint8_t *const *)src_planes, src_linesize, 0,
|
||||||
|
source_height, (uint8_t *const *)dst_planes, dst_linesize);
|
||||||
|
|
||||||
|
ret = true;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (sws_ctx) {
|
||||||
|
sws_freeContext(sws_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
if (target_pic) {
|
||||||
|
Memory_Free(target_pic->data);
|
||||||
|
target_pic->width = 0;
|
||||||
|
target_pic->height = 0;
|
||||||
|
target_pic->data = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
|
@ -5,6 +5,9 @@
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
bool S_Picture_LoadFromFile(PICTURE *picture, const char *file_path);
|
bool S_Picture_LoadFromFile(PICTURE *target_pic, const char *file_path);
|
||||||
|
bool S_Picture_Scale(
|
||||||
|
PICTURE *target_pic, const PICTURE *source_pic, int target_width,
|
||||||
|
int target_height);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue