feat: implement album art display functionality and update application version to dev50
Some checks failed
Build (3DS) / build (push) Failing after 1m59s
Some checks failed
Build (3DS) / build (push) Failing after 1m59s
This commit is contained in:
137
source/gui.c
137
source/gui.c
@@ -3,6 +3,8 @@
|
||||
#include <citro3d.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <png.h>
|
||||
#include "gui.h"
|
||||
#include "metadata.h"
|
||||
|
||||
@@ -180,14 +182,6 @@ void guiDisplayMetadata(struct metadata_t* metadata, const char* filename)
|
||||
C2D_TextOptimize(&text);
|
||||
C2D_DrawText(&text, C2D_WithColor, 10.0f, y, 0.5f, scale * 0.8f, scale * 0.8f, GUI_COLOR_TEXT_DIM);
|
||||
}
|
||||
|
||||
/* Draw album art indicator if available */
|
||||
if(metadata->hasAlbumArt)
|
||||
{
|
||||
C2D_TextParse(&text, textBuf, "[Art]");
|
||||
C2D_TextOptimize(&text);
|
||||
C2D_DrawText(&text, C2D_WithColor, 350.0f, 10.0f, 0.5f, 0.4f, 0.4f, GUI_COLOR_ACCENT);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -343,3 +337,130 @@ void guiDisplayVersion(const char* version)
|
||||
C2D_TextOptimize(&text);
|
||||
C2D_DrawText(&text, C2D_WithColor, 80.0f, 220.0f, 0.5f, 0.45f, 0.45f, GUI_COLOR_TEXT_DIM);
|
||||
}
|
||||
|
||||
/**
|
||||
* PNG read callback for memory buffer
|
||||
*/
|
||||
static void pngReadCallback(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||
{
|
||||
uint8_t** buffer_ptr = (uint8_t**)png_get_io_ptr(png_ptr);
|
||||
memcpy(data, *buffer_ptr, length);
|
||||
*buffer_ptr += length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display album art on top screen
|
||||
*/
|
||||
void guiDisplayAlbumArt(struct metadata_t* metadata)
|
||||
{
|
||||
if(!metadata || !metadata->hasAlbumArt || !metadata->albumArt)
|
||||
return;
|
||||
|
||||
C2D_SceneBegin(topTarget);
|
||||
|
||||
/* Decode PNG image */
|
||||
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
if(!png_ptr)
|
||||
return;
|
||||
|
||||
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||
if(!info_ptr)
|
||||
{
|
||||
png_destroy_read_struct(&png_ptr, NULL, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if(setjmp(png_jmpbuf(png_ptr)))
|
||||
{
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set up custom read function */
|
||||
uint8_t* buffer_ptr = metadata->albumArt;
|
||||
png_set_read_fn(png_ptr, &buffer_ptr, pngReadCallback);
|
||||
|
||||
/* Read PNG info */
|
||||
png_read_info(png_ptr, info_ptr);
|
||||
|
||||
int width = png_get_image_width(png_ptr, info_ptr);
|
||||
int height = png_get_image_height(png_ptr, info_ptr);
|
||||
png_byte color_type = png_get_color_type(png_ptr, info_ptr);
|
||||
png_byte bit_depth = png_get_bit_depth(png_ptr, info_ptr);
|
||||
|
||||
/* Convert to RGBA8 */
|
||||
if(bit_depth == 16)
|
||||
png_set_strip_16(png_ptr);
|
||||
if(color_type == PNG_COLOR_TYPE_PALETTE)
|
||||
png_set_palette_to_rgb(png_ptr);
|
||||
if(color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
|
||||
png_set_expand_gray_1_2_4_to_8(png_ptr);
|
||||
if(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
|
||||
png_set_tRNS_to_alpha(png_ptr);
|
||||
if(color_type == PNG_COLOR_TYPE_RGB ||
|
||||
color_type == PNG_COLOR_TYPE_GRAY ||
|
||||
color_type == PNG_COLOR_TYPE_PALETTE)
|
||||
png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER);
|
||||
if(color_type == PNG_COLOR_TYPE_GRAY ||
|
||||
color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
|
||||
png_set_gray_to_rgb(png_ptr);
|
||||
|
||||
png_read_update_info(png_ptr, info_ptr);
|
||||
|
||||
/* Allocate image buffer */
|
||||
png_bytep* row_pointers = (png_bytep*)malloc(sizeof(png_bytep) * height);
|
||||
if(!row_pointers)
|
||||
{
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
for(int y = 0; y < height; y++)
|
||||
{
|
||||
row_pointers[y] = (png_byte*)malloc(png_get_rowbytes(png_ptr, info_ptr));
|
||||
if(!row_pointers[y])
|
||||
{
|
||||
for(int i = 0; i < y; i++)
|
||||
free(row_pointers[i]);
|
||||
free(row_pointers);
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read image data */
|
||||
png_read_image(png_ptr, row_pointers);
|
||||
|
||||
/* Scale to fit in top-right corner (max 60x60) */
|
||||
int displayWidth = width;
|
||||
int displayHeight = height;
|
||||
if(width > 60 || height > 60)
|
||||
{
|
||||
float scale = 60.0f / (width > height ? width : height);
|
||||
displayWidth = (int)(width * scale);
|
||||
displayHeight = (int)(height * scale);
|
||||
}
|
||||
|
||||
/* Draw the image pixel by pixel */
|
||||
float startX = 330.0f; /* Top right corner */
|
||||
float startY = 10.0f;
|
||||
|
||||
for(int y = 0; y < displayHeight; y++)
|
||||
{
|
||||
int srcY = (y * height) / displayHeight;
|
||||
for(int x = 0; x < displayWidth; x++)
|
||||
{
|
||||
int srcX = (x * width) / displayWidth;
|
||||
png_bytep px = &(row_pointers[srcY][srcX * 4]);
|
||||
u32 color = C2D_Color32(px[0], px[1], px[2], px[3]);
|
||||
C2D_DrawRectSolid(startX + x, startY + y, 0.5f, 1, 1, color);
|
||||
}
|
||||
}
|
||||
|
||||
/* Clean up */
|
||||
for(int y = 0; y < height; y++)
|
||||
free(row_pointers[y]);
|
||||
free(row_pointers);
|
||||
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user