diff --git a/docs/CHANGES.TXT b/docs/CHANGES.TXT index 5e37a7913..4a4835c4a 100644 --- a/docs/CHANGES.TXT +++ b/docs/CHANGES.TXT @@ -52,6 +52,7 @@ - Extract multiple teletext pages simultaneously with separate output files - Use --tpage multiple times (e.g., --tpage 100 --tpage 200) - Output files are named with page suffix (e.g., output_p100.srt, output_p200.srt) +- Fix: SPUPNG subtitle offset calculation to center based on actual image dimensions - New: Added --list-tracks (-L) option to list all tracks in media files without processing New: Chinese, Korean, Japanese support - proper encoding and OCR. diff --git a/src/lib_ccx/ccx_encoders_common.c b/src/lib_ccx/ccx_encoders_common.c index 4c3b6db9d..7cf473de9 100644 --- a/src/lib_ccx/ccx_encoders_common.c +++ b/src/lib_ccx/ccx_encoders_common.c @@ -775,6 +775,7 @@ struct encoder_ctx *init_encoder(struct encoder_cfg *opt) return NULL; } ctx->in_fileformat = opt->in_format; + ctx->is_pal = (opt->in_format == 2); /** used in case of SUB_EOD_MARKER */ ctx->prev_start = -1; diff --git a/src/lib_ccx/ccx_encoders_common.h b/src/lib_ccx/ccx_encoders_common.h index 4a1866e51..c24235841 100644 --- a/src/lib_ccx/ccx_encoders_common.h +++ b/src/lib_ccx/ccx_encoders_common.h @@ -182,10 +182,10 @@ struct encoder_ctx // OCR in SPUPNG int nospupngocr; + int is_pal; - // Teletext multi-page output (issue #665) - struct ccx_s_write *tlt_out[MAX_TLT_PAGES_EXTRACT]; // Output files per teletext page - uint16_t tlt_out_pages[MAX_TLT_PAGES_EXTRACT]; // Page numbers for each output slot + struct ccx_s_write *tlt_out[MAX_TLT_PAGES_EXTRACT]; // Output files per teletext page + uint16_t tlt_out_pages[MAX_TLT_PAGES_EXTRACT]; // Page numbers for each output slot unsigned int tlt_srt_counter[MAX_TLT_PAGES_EXTRACT]; // SRT counter per page int tlt_out_count; // Number of teletext output files }; diff --git a/src/lib_ccx/ccx_encoders_spupng.c b/src/lib_ccx/ccx_encoders_spupng.c index 09fca63f5..9306f534e 100644 --- a/src/lib_ccx/ccx_encoders_spupng.c +++ b/src/lib_ccx/ccx_encoders_spupng.c @@ -251,6 +251,9 @@ void set_spupng_offset(void *ctx, int x, int y) sp->xOffset = x; sp->yOffset = y; } + +// Forward declaration for calculate_spupng_offsets +static void calculate_spupng_offsets(struct spupng_t *sp, struct encoder_ctx *ctx); int save_spupng(const char *filename, uint8_t *bitmap, int w, int h, png_color *palette, png_byte *alpha, int nb_color) { @@ -384,7 +387,7 @@ int write_cc_bitmap_as_spupng(struct cc_subtitle *sub, struct encoder_ctx *conte struct cc_bitmap *rect; png_color *palette = NULL; png_byte *alpha = NULL; - int wrote_opentag = 1; + int wrote_opentag = 0; // Track if we actually wrote the tag x_pos = -1; y_pos = -1; @@ -395,13 +398,11 @@ int write_cc_bitmap_as_spupng(struct cc_subtitle *sub, struct encoder_ctx *conte return 0; inc_spupng_fileindex(sp); - write_sputag_open(sp, sub->start_time, sub->end_time - 1); if (sub->nb_data == 0 && (sub->flags & SUB_EOD_MARKER)) { context->prev_start = -1; - if (wrote_opentag) - write_sputag_close(sp); + // No subtitle data, skip writing return 0; } rect = sub->data; @@ -440,7 +441,13 @@ int write_cc_bitmap_as_spupng(struct cc_subtitle *sub, struct encoder_ctx *conte } } filename = get_spupng_filename(sp); - set_spupng_offset(sp, x_pos, y_pos); + + // Set image dimensions for offset calculation + sp->img_w = width; + sp->img_h = height; + + // Calculate centered offsets based on screen size (PAL/NTSC) + calculate_spupng_offsets(sp, context); if (sub->flags & SUB_EOD_MARKER) context->prev_start = sub->start_time; pbuf = (uint8_t *)malloc(width * height); @@ -475,6 +482,15 @@ int write_cc_bitmap_as_spupng(struct cc_subtitle *sub, struct encoder_ctx *conte /* TODO do rectangle wise, one color table should not be used for all rectangles */ mapclut_paletee(palette, alpha, (uint32_t *)rect[0].data1, rect[0].nb_colors); + + // Save PNG file first + save_spupng(filename, pbuf, width, height, palette, alpha, rect[0].nb_colors); + freep(&pbuf); + + // Write XML tag with calculated centered offsets + write_sputag_open(sp, sub->start_time, sub->end_time - 1); + wrote_opentag = 1; // Mark that we wrote the tag + #ifdef ENABLE_OCR if (!context->nospupngocr) { @@ -487,8 +503,6 @@ int write_cc_bitmap_as_spupng(struct cc_subtitle *sub, struct encoder_ctx *conte } } #endif - save_spupng(filename, pbuf, width, height, palette, alpha, rect[0].nb_colors); - freep(&pbuf); end: if (wrote_opentag) @@ -991,6 +1005,8 @@ int spupng_export_string2png(struct spupng_t *sp, char *str, FILE *output) */ // Save image + sp->img_w = canvas_width; + sp->img_h = canvas_height; write_image(buffer, output, canvas_width, canvas_height); free(tmp); free(buffer); @@ -1081,6 +1097,28 @@ int eia608_to_str(struct encoder_ctx *context, struct eia608_screen *data, char // string needs to be in UTF-8 encoding. // This function will take care of encoding. +static void calculate_spupng_offsets(struct spupng_t *sp, struct encoder_ctx *ctx) +{ + int screen_w = 720; + int screen_h; + + /* Teletext is always PAL */ + if (ctx->in_fileformat == 2 || ctx->is_pal) + { + screen_h = 576; + } + else + { + screen_h = 480; + } + + sp->xOffset = (screen_w - sp->img_w) / 2; + sp->yOffset = (screen_h - sp->img_h) / 2; + + // SPU / DVD requires even yOffset (interlacing) + if (sp->yOffset & 1) + sp->yOffset++; +} int spupng_write_string(struct spupng_t *sp, char *string, LLONG start_time, LLONG end_time, struct encoder_ctx *context) { @@ -1099,6 +1137,7 @@ int spupng_write_string(struct spupng_t *sp, char *string, LLONG start_time, LLO } // free(string_utf32); fclose(sp->fppng); + calculate_spupng_offsets(sp, context); write_sputag_open(sp, start_time, end_time); write_spucomment(sp, string); write_sputag_close(sp); diff --git a/src/lib_ccx/ccx_encoders_structs.h b/src/lib_ccx/ccx_encoders_structs.h index efecbb722..9b0cf036b 100644 --- a/src/lib_ccx/ccx_encoders_structs.h +++ b/src/lib_ccx/ccx_encoders_structs.h @@ -39,6 +39,8 @@ struct spupng_t int fileIndex; int xOffset; int yOffset; + int img_w; + int img_h; }; #endif