Merge branch 'pr/n129_anshul1912'

This commit is contained in:
cfsmp3 2015-01-07 15:16:23 +01:00
commit e6024c1cb1
12 changed files with 353 additions and 567 deletions

View File

@ -80,30 +80,9 @@ void write_stringz_as_sami(char *string, struct encoder_ctx *context, LLONG ms_s
int write_cc_bitmap_as_sami(struct cc_subtitle *sub, struct encoder_ctx *context)
{
struct spupng_t *sp = (struct spupng_t *)context->out->spupng_data;
int x_pos, y_pos, width, height, i;
int x, y, y_off, x_off, ret;
uint8_t *pbuf;
//char *filename;
int ret = 0;
struct cc_bitmap* rect;
png_color *palette = NULL;
png_byte *alpha = NULL;
#ifdef ENABLE_OCR
char*str = NULL;
#endif
//int used;
#ifdef ENABLE_OCR
unsigned h1, m1, s1, ms1;
unsigned h2, m2, s2, ms2;
#endif
LLONG ms_start, ms_end;
//char timeline[128];
int len = 0;
x_pos = -1;
y_pos = -1;
width = 0;
height = 0;
if (context->prev_start != -1 && (sub->flags & SUB_EOD_MARKER))
{
@ -124,110 +103,45 @@ int write_cc_bitmap_as_sami(struct cc_subtitle *sub, struct encoder_ctx *context
if(sub->nb_data == 0 )
return 0;
rect = sub->data;
for(i = 0;i < sub->nb_data;i++)
{
if(x_pos == -1)
{
x_pos = rect[i].x;
y_pos = rect[i].y;
width = rect[i].w;
height = rect[i].h;
}
else
{
if(x_pos > rect[i].x)
{
width += (x_pos - rect[i].x);
x_pos = rect[i].x;
}
if (rect[i].y < y_pos)
{
height += (y_pos - rect[i].y);
y_pos = rect[i].y;
}
if (rect[i].x + rect[i].w > x_pos + width)
{
width = rect[i].x + rect[i].w - x_pos;
}
if (rect[i].y + rect[i].h > y_pos + height)
{
height = rect[i].y + rect[i].h - y_pos;
}
}
}
if ( sub->flags & SUB_EOD_MARKER )
context->prev_start = sub->start_time;
pbuf = (uint8_t*) malloc(width * height);
memset(pbuf, 0x0, width * height);
for(i = 0;i < sub->nb_data;i++)
{
x_off = rect[i].x - x_pos;
y_off = rect[i].y - y_pos;
for (y = 0; y < rect[i].h; y++)
{
for (x = 0; x < rect[i].w; x++)
pbuf[((y + y_off) * width) + x_off + x] = rect[i].data[0][y * rect[i].w + x];
}
}
palette = (png_color*) malloc(rect[0].nb_colors * sizeof(png_color));
if(!palette)
{
ret = -1;
goto end;
}
alpha = (png_byte*) malloc(rect[0].nb_colors * sizeof(png_byte));
if(!alpha)
{
ret = -1;
goto end;
}
/* TODO do rectangle, wise one color table should not be used for all rectangle */
mapclut_paletee(palette, alpha, (uint32_t *)rect[0].data[1],rect[0].nb_colors);
quantize_map(alpha, palette, pbuf, width*height, 3, rect[0].nb_colors);
#ifdef ENABLE_OCR
str = ocr_bitmap(palette,alpha,pbuf,width,height);
if(str && str[0])
#if ENABLE_OCR
if (rect[0].ocr_text && *(rect[0].ocr_text))
{
if (context->prev_start != -1 || !(sub->flags & SUB_EOD_MARKER))
{
char *token = NULL;
sprintf(context->buffer,
char *buf = (char*)context->buffer;
sprintf(buf,
"<SYNC start=%llu><P class=\"UNKNOWNCC\">\r\n"
,(unsigned long long)ms_start);
write(context->out->fh,context->buffer,strlen(context->buffer));
token = strtok(str,"\r\n");
write(context->out->fh, buf, strlen(buf));
token = strtok(rect[0].ocr_text,"\r\n");
while (token)
{
sprintf(context->buffer,"%s",token);
sprintf(buf, "%s", token);
token = strtok(NULL,"\r\n");
if(token)
strcat(context->buffer,"<br>\n");
strcat(buf, "<br>\n");
else
strcat(context->buffer,"\n");
write(context->out->fh,context->buffer,strlen(context->buffer));
strcat(buf, "\n");
write(context->out->fh, buf, strlen(buf));
}
sprintf(context->buffer,
sprintf(buf,
"<SYNC start=%llu><P class=\"UNKNOWNCC\">&nbsp;</P></SYNC>\r\n\r\n"
,(unsigned long long)ms_end);
write(context->out->fh,context->buffer,strlen(context->buffer));
write(context->out->fh, buf, strlen(buf));
}
}
#endif
end:
sub->nb_data = 0;
freep(&sub->data);
freep(&palette);
freep(&alpha);
return ret;
}

View File

@ -106,30 +106,12 @@ void write_stringz_as_smptett(char *string, struct encoder_ctx *context, LLONG m
int write_cc_bitmap_as_smptett(struct cc_subtitle *sub, struct encoder_ctx *context)
{
struct spupng_t *sp = (struct spupng_t *)context->out->spupng_data;
int x_pos, y_pos, width, height, i;
int x, y, y_off, x_off, ret;
uint8_t *pbuf;
//char *filename;
int ret = 0;
struct cc_bitmap* rect;
png_color *palette = NULL;
png_byte *alpha = NULL;
#ifdef ENABLE_OCR
char*str = NULL;
#endif
//int used;
#ifdef ENABLE_OCR
unsigned h1, m1, s1, ms1;
unsigned h2, m2, s2, ms2;
#endif
LLONG ms_start, ms_end;
//char timeline[128];
int len = 0;
x_pos = -1;
y_pos = -1;
width = 0;
height = 0;
if (context->prev_start != -1 && (sub->flags & SUB_EOD_MARKER))
{
@ -150,96 +132,34 @@ int write_cc_bitmap_as_smptett(struct cc_subtitle *sub, struct encoder_ctx *cont
if(sub->nb_data == 0 )
return 0;
rect = sub->data;
for(i = 0;i < sub->nb_data;i++)
{
if(x_pos == -1)
{
x_pos = rect[i].x;
y_pos = rect[i].y;
width = rect[i].w;
height = rect[i].h;
}
else
{
if(x_pos > rect[i].x)
{
width += (x_pos - rect[i].x);
x_pos = rect[i].x;
}
if (rect[i].y < y_pos)
{
height += (y_pos - rect[i].y);
y_pos = rect[i].y;
}
if (rect[i].x + rect[i].w > x_pos + width)
{
width = rect[i].x + rect[i].w - x_pos;
}
if (rect[i].y + rect[i].h > y_pos + height)
{
height = rect[i].y + rect[i].h - y_pos;
}
}
}
if ( sub->flags & SUB_EOD_MARKER )
context->prev_start = sub->start_time;
pbuf = (uint8_t*) malloc(width * height);
memset(pbuf, 0x0, width * height);
for(i = 0;i < sub->nb_data;i++)
{
x_off = rect[i].x - x_pos;
y_off = rect[i].y - y_pos;
for (y = 0; y < rect[i].h; y++)
{
for (x = 0; x < rect[i].w; x++)
pbuf[((y + y_off) * width) + x_off + x] = rect[i].data[0][y * rect[i].w + x];
}
}
palette = (png_color*) malloc(rect[0].nb_colors * sizeof(png_color));
if(!palette)
{
ret = -1;
goto end;
}
alpha = (png_byte*) malloc(rect[0].nb_colors * sizeof(png_byte));
if(!alpha)
{
ret = -1;
goto end;
}
/* TODO do rectangle, wise one color table should not be used for all rectangle */
mapclut_paletee(palette, alpha, (uint32_t *)rect[0].data[1],rect[0].nb_colors);
quantize_map(alpha, palette, pbuf, width*height, 3, rect[0].nb_colors);
#ifdef ENABLE_OCR
str = ocr_bitmap(palette,alpha,pbuf,width,height);
if(str && str[0])
if (rect[0].ocr_text && *(rect[0].ocr_text))
{
if (context->prev_start != -1 || !(sub->flags & SUB_EOD_MARKER))
{
char *buf = (char *) context->buffer;
unsigned h1, m1, s1, ms1;
unsigned h2, m2, s2, ms2;
mstotime (ms_start,&h1,&m1,&s1,&ms1);
mstotime (ms_end-1,&h2,&m2,&s2,&ms2); // -1 To prevent overlapping with next line.
sprintf ((char *) context->buffer,"<p begin=\"%02u:%02u:%02u.%03u\" end=\"%02u:%02u:%02u.%03u\">\n",h1,m1,s1,ms1, h2,m2,s2,ms2);
write (context->out->fh, context->buffer,strlen(context->buffer) );
len = strlen(str);
write (context->out->fh, str, len);
write (context->out->fh, buf,strlen(buf) );
len = strlen(rect[0].ocr_text);
write (context->out->fh, rect[0].ocr_text, len);
write (context->out->fh, encoded_crlf, encoded_crlf_length);
sprintf ((char *) str,"</p>\n");
sprintf ( buf,"</p>\n");
write (context->out->fh, buf,strlen(buf) );
}
}
#endif
end:
sub->nb_data = 0;
freep(&sub->data);
freep(&palette);
freep(&alpha);
return ret;
}

View File

@ -1,9 +1,6 @@
#include "lib_ccx.h"
#include "ccx_common_option.h"
#include "ccx_encoders_common.h"
#include "png.h"
#include "spupng_encoder.h"
#include "ocr.h"
#include "utility.h"
/* The timing here is not PTS based, but output based, i.e. user delay must be accounted for
@ -75,16 +72,8 @@ void write_stringz_as_srt(char *string, struct encoder_ctx *context, LLONG ms_st
int write_cc_bitmap_as_srt(struct cc_subtitle *sub, struct encoder_ctx *context)
{
int x_pos, y_pos, width, height, i;
int x, y, y_off, x_off, ret;
uint8_t *pbuf;
//char *filename;
int ret = 0;
struct cc_bitmap* rect;
png_color *palette = NULL;
png_byte *alpha = NULL;
#ifdef ENABLE_OCR
char*str = NULL;
#endif
LLONG ms_start, ms_end;
#ifdef ENABLE_OCR
unsigned h1,m1,s1,ms1;
@ -94,11 +83,6 @@ int write_cc_bitmap_as_srt(struct cc_subtitle *sub, struct encoder_ctx *context)
int used;
#endif
x_pos = -1;
y_pos = -1;
width = 0;
height = 0;
if (context->prev_start != -1 && (sub->flags & SUB_EOD_MARKER))
{
ms_start = context->prev_start;
@ -117,76 +101,13 @@ int write_cc_bitmap_as_srt(struct cc_subtitle *sub, struct encoder_ctx *context)
if(sub->nb_data == 0 )
return 0;
rect = sub->data;
for(i = 0;i < sub->nb_data;i++)
{
if(x_pos == -1)
{
x_pos = rect[i].x;
y_pos = rect[i].y;
width = rect[i].w;
height = rect[i].h;
}
else
{
if(x_pos > rect[i].x)
{
width += (x_pos - rect[i].x);
x_pos = rect[i].x;
}
if (rect[i].y < y_pos)
{
height += (y_pos - rect[i].y);
y_pos = rect[i].y;
}
if (rect[i].x + rect[i].w > x_pos + width)
{
width = rect[i].x + rect[i].w - x_pos;
}
if (rect[i].y + rect[i].h > y_pos + height)
{
height = rect[i].y + rect[i].h - y_pos;
}
}
}
if ( sub->flags & SUB_EOD_MARKER )
if(sub->flags & SUB_EOD_MARKER)
context->prev_start = sub->start_time;
pbuf = (uint8_t*) malloc(width * height);
memset(pbuf, 0x0, width * height);
for(i = 0;i < sub->nb_data;i++)
{
x_off = rect[i].x - x_pos;
y_off = rect[i].y - y_pos;
for (y = 0; y < rect[i].h; y++)
{
for (x = 0; x < rect[i].w; x++)
pbuf[((y + y_off) * width) + x_off + x] = rect[i].data[0][y * rect[i].w + x];
}
}
palette = (png_color*) malloc(rect[0].nb_colors * sizeof(png_color));
if(!palette)
{
ret = -1;
goto end;
}
alpha = (png_byte*) malloc(rect[0].nb_colors * sizeof(png_byte));
if(!alpha)
{
ret = -1;
goto end;
}
/* TODO do rectangle, wise one color table should not be used for all rectangle */
mapclut_paletee(palette, alpha, (uint32_t *)rect[0].data[1],rect[0].nb_colors);
quantize_map(alpha, palette, pbuf, width*height, 3, rect[0].nb_colors);
rect = sub->data;
#ifdef ENABLE_OCR
str = ocr_bitmap(palette,alpha,pbuf,width,height);
if(str && str[0])
if (rect[0].ocr_text && *(rect[0].ocr_text))
{
if (context->prev_start != -1 || !(sub->flags & SUB_EOD_MARKER))
{
@ -200,18 +121,14 @@ int write_cc_bitmap_as_srt(struct cc_subtitle *sub, struct encoder_ctx *context)
h1,m1,s1,ms1, h2,m2,s2,ms2);
used = encode_line(context->buffer,(unsigned char *) timeline);
write (context->out->fh, context->buffer, used);
len = strlen(str);
write (context->out->fh, str, len);
len = strlen(rect[0].ocr_text);
write (context->out->fh, rect[0].ocr_text, len);
write (context->out->fh, encoded_crlf, encoded_crlf_length);
}
}
#endif
end:
sub->nb_data = 0;
freep(&sub->data);
freep(&palette);
freep(&alpha);
return ret;
}

View File

@ -124,10 +124,15 @@ enum
DTVCC_PACKET_START = 3,
};
const char *language[4] =
/**
* After Adding a new language here, dont forget
* to increase NB_LANGUAGE define ccx_common_constants.h
*/
const char *language[NB_LANGUAGE] =
{
"und",
"eng",
"fin",
"spa",
NULL
};

View File

@ -267,5 +267,6 @@ enum ccx_code_type
#define CCX_TXT_AUTO_NOT_YET_FOUND 1
#define CCX_TXT_IN_USE 2 // Positive autodetected, or forced, etc
extern const char *language[4];
#define NB_LANGUAGE 5
extern const char *language[NB_LANGUAGE];
#endif

View File

@ -19,6 +19,9 @@ struct cc_bitmap
int nb_colors;
unsigned char *data[2];
int linesize[2];
#ifdef ENABLE_OCR
char *ocr_text;
#endif
};
enum ccx_eia608_format

View File

@ -232,30 +232,14 @@ int write_cc_buffer_as_transcript2(struct eia608_screen *data, struct encoder_ct
}
int write_cc_bitmap_as_transcript(struct cc_subtitle *sub, struct encoder_ctx *context)
{
struct spupng_t *sp = (struct spupng_t *)context->out->spupng_data;
int x_pos, y_pos, width, height, i;
int x, y, y_off, x_off, ret;
uint8_t *pbuf;
//char *filename;
int ret = 0;
struct cc_bitmap* rect;
png_color *palette = NULL;
png_byte *alpha = NULL;
#ifdef ENABLE_OCR
char*str = NULL;
#endif
//int used;
#ifdef ENABLE_OCR
unsigned h1,m1,s1,ms1;
unsigned h2,m2,s2,ms2;
#endif
LLONG start_time, end_time;
//char timeline[128];
int len = 0;
x_pos = -1;
y_pos = -1;
width = 0;
height = 0;
if (context->prev_start != -1 && (sub->flags & SUB_EOD_MARKER))
{
@ -269,82 +253,19 @@ int write_cc_bitmap_as_transcript(struct cc_subtitle *sub, struct encoder_ctx *c
}
if(sub->nb_data == 0 )
return 0;
return ret;
rect = sub->data;
for(i = 0;i < sub->nb_data;i++)
{
if(x_pos == -1)
{
x_pos = rect[i].x;
y_pos = rect[i].y;
width = rect[i].w;
height = rect[i].h;
}
else
{
if(x_pos > rect[i].x)
{
width += (x_pos - rect[i].x);
x_pos = rect[i].x;
}
if (rect[i].y < y_pos)
{
height += (y_pos - rect[i].y);
y_pos = rect[i].y;
}
if (rect[i].x + rect[i].w > x_pos + width)
{
width = rect[i].x + rect[i].w - x_pos;
}
if (rect[i].y + rect[i].h > y_pos + height)
{
height = rect[i].y + rect[i].h - y_pos;
}
}
}
if ( sub->flags & SUB_EOD_MARKER )
context->prev_start = sub->start_time;
pbuf = (uint8_t*) malloc(width * height);
memset(pbuf, 0x0, width * height);
for(i = 0;i < sub->nb_data;i++)
{
x_off = rect[i].x - x_pos;
y_off = rect[i].y - y_pos;
for (y = 0; y < rect[i].h; y++)
{
for (x = 0; x < rect[i].w; x++)
pbuf[((y + y_off) * width) + x_off + x] = rect[i].data[0][y * rect[i].w + x];
}
}
palette = (png_color*) malloc(rect[0].nb_colors * sizeof(png_color));
if(!palette)
{
ret = -1;
goto end;
}
alpha = (png_byte*) malloc(rect[0].nb_colors * sizeof(png_byte));
if(!alpha)
{
ret = -1;
goto end;
}
/* TODO do rectangle, wise one color table should not be used for all rectangle */
mapclut_paletee(palette, alpha, (uint32_t *)rect[0].data[1],rect[0].nb_colors);
quantize_map(alpha, palette, pbuf, width*height, 3, rect[0].nb_colors);
#ifdef ENABLE_OCR
str = ocr_bitmap(palette,alpha,pbuf,width,height);
if(str && str[0])
#if ENABLE_OCR
if (rect[0].ocr_text && *(rect[0].ocr_text))
{
if (context->prev_start != -1 || !(sub->flags & SUB_EOD_MARKER))
{
char *token = NULL;
token = strtok(str,"\r\n");
token = strtok(rect[0].ocr_text ,"\r\n");
while (token)
{
@ -402,11 +323,8 @@ int write_cc_bitmap_as_transcript(struct cc_subtitle *sub, struct encoder_ctx *c
}
#endif
end:
sub->nb_data = 0;
freep(&sub->data);
freep(&palette);
freep(&alpha);
return ret;
}

View File

@ -25,6 +25,7 @@
#include "dvb_subtitle_decoder.h"
#include "utility.h"
#include "ccx_decoders_common.h"
#include "ocr.h"
#define DVBSUB_PAGE_SEGMENT 0x10
#define DVBSUB_REGION_SEGMENT 0x11
@ -272,6 +273,9 @@ typedef struct DVBSubContext
int lang_index;
int version;
int time_out;
#ifdef ENABLE_OCR
void *ocr_ctx;
#endif
DVBSubRegion *region_list;
DVBSubCLUT *clut_list;
DVBSubObject *object_list;
@ -429,6 +433,9 @@ void* dvbsub_init_decoder(struct dvb_config* cfg)
ctx->ancillary_id = cfg->ancillary_id[0];
ctx->lang_index = cfg->lang_index[0];
#ifdef ENABLE_OCR
ctx->ocr_ctx = init_ocr(ctx->lang_index);
#endif
ctx->version = -1;
default_clut.id = -1;
@ -1425,6 +1432,7 @@ static int write_dvb_sub(void *dvb_ctx, struct cc_subtitle *sub)
struct cc_bitmap *rect = NULL;
uint32_t *clut_table;
int offset_x=0, offset_y=0;
int ret = 0;
sub->type = CC_BITMAP;
sub->lang_index = ctx->lang_index;
@ -1458,6 +1466,9 @@ static int write_dvb_sub(void *dvb_ctx, struct cc_subtitle *sub)
sub->data = rect;
for (display = ctx->display_list; display; display = display->next)
{
#ifdef ENABLE_OCR
char *ocr_str = NULL;
#endif
region = get_region(ctx, display->region_id);
if (!region)
@ -1497,6 +1508,11 @@ static int write_dvb_sub(void *dvb_ctx, struct cc_subtitle *sub)
rect->data[0] = malloc(region->buf_size);
memcpy(rect->data[0], region->pbuf, region->buf_size);
#ifdef ENABLE_OCR
ret = ocr_rect(ctx->ocr_ctx, rect, &ocr_str);
if(ret >= 0)
rect->ocr_text = ocr_str;
#endif
rect++;
}

View File

@ -3,18 +3,115 @@
#ifdef ENABLE_OCR
#include "platform.h"
#include "capi.h"
#include "ccx_common_constants.h"
#include "allheaders.h"
#include <dirent.h>
#include "spupng_encoder.h"
char* ocr_bitmap(png_color *palette,png_byte *alpha, unsigned char* indata,int w, int h)
struct ocrCtx
{
TessBaseAPI* api;
};
struct transIntensity
{
uint8_t *t;
png_color *palette;
};
static int check_trans_tn_intensity(const void *p1, const void *p2, void *arg)
{
struct transIntensity *ti = arg;
unsigned char* tmp = (unsigned char*)p1;
unsigned char* act = (unsigned char*)p2;
unsigned char tmp_i;
unsigned char act_i;
/** TODO verify that RGB follow ITU-R BT.709
* Below fomula is valid only for 709 standurd
* Y = 0.2126 R + 0.7152 G + 0.0722 B
*/
tmp_i = (0.2126 * ti->palette[*tmp].red) + (0.7152 * ti->palette[*tmp].green) + (0.0722 * ti->palette[*tmp].blue);
act_i = (0.2126 * ti->palette[*act].red) + (0.7152 * ti->palette[*act].green) + (0.0722 * ti->palette[*act].blue);;
if (ti->t[*tmp] < ti->t[*act] || (ti->t[*tmp] == ti->t[*act] && tmp_i < act_i))
return -1;
else if (ti->t[*tmp] == ti->t[*act] && tmp_i == act_i)
return 0;
return 1;
}
static int search_language_pack(const char *dirname,const char *lang)
{
DIR *dp;
struct dirent *dirp;
char filename[256];
if ((dp = opendir(dirname)) == NULL)
{
return -1;
}
snprintf(filename, 256, "%s.traineddata",lang);
while ((dirp = readdir(dp)) != NULL)
{
if(!strcmp(dirp->d_name, filename))
{
closedir(dp);
return 0;
}
}
closedir(dp);
return -1;
}
static void delete_ocr (struct ocrCtx* ctx)
{
TessBaseAPIEnd(ctx->api);
TessBaseAPIDelete(ctx->api);
freep(ctx);
}
void* init_ocr(int lang_index)
{
int ret;
struct ocrCtx* ctx;
ctx = (struct ocrCtx*)malloc(sizeof(struct ocrCtx));
if(!ctx)
return NULL;
ctx->api = TessBaseAPICreate();
/* if language was undefined use english */
if(lang_index == 0)
{
/* select english */
lang_index = 1;
}
/* if langauge pack not found use english */
ret = search_language_pack("tessdata",language[lang_index]);
if(ret < 0 )
{
/* select english */
lang_index = 1;
}
ret = TessBaseAPIInit3(ctx->api,"", language[lang_index]);
if(ret < 0)
{
goto fail;
}
return ctx;
fail:
delete_ocr(ctx);
return NULL;
}
char* ocr_bitmap(void* arg, png_color *palette,png_byte *alpha, unsigned char* indata,int w, int h)
{
PIX *pix;
char*text_out= NULL;
int i,j,index,ret;
int i,j,index;
unsigned int wpl;
unsigned int *data,*ppixel;
api = TessBaseAPICreate();
struct ocrCtx* ctx = arg;
pix = pixCreate(w, h, 32);
if(pix == NULL)
{
@ -37,18 +134,192 @@ char* ocr_bitmap(png_color *palette,png_byte *alpha, unsigned char* indata,int w
}
}
ret = TessBaseAPIInit3(api,"", "eng");
if(ret < 0)
{
return NULL;
}
//text_out = TessBaseAPIProcessPages(api, "/home/anshul/test_videos/dvbsubtest.d/sub0018.png", 0, 0);
text_out = TessBaseAPIProcessPage(api, pix, 0, NULL, NULL, 0);
text_out = TessBaseAPIProcessPage(ctx->api, pix, 0, NULL, NULL, 0);
if(!text_out)
printf("\nsomething messy\n");
//TessDeleteText(text_out);
pixDestroy(&pix);
return text_out;
}
/*
* @param alpha out
* @param intensity in
* @param palette out should be already initialized
* @param bitmap in
* @param size in size of bitmap
* @param max_color in
* @param nb_color in
*/
static int quantize_map(png_byte *alpha, png_color *palette,
uint8_t *bitmap, int size, int max_color, int nb_color)
{
/*
* occurrence of color in image
*/
uint32_t *histogram = NULL;
/* intensity ordered table */
uint8_t *iot = NULL;
/* array of color with most occurrence according to histogram
* save index of intensity order table
*/
uint32_t *mcit = NULL;
struct transIntensity ti = { alpha,palette};
int ret = 0;
histogram = (uint32_t*) malloc(nb_color * sizeof(uint32_t));
if (!histogram)
{
ret = -1;
goto end;
}
iot = (uint8_t*) malloc(nb_color * sizeof(uint8_t));
if (!iot)
{
ret = -1;
goto end;
}
mcit = (uint32_t*) malloc(nb_color * sizeof(uint32_t));
if (!mcit)
{
ret = -1;
goto end;
}
memset(histogram, 0, nb_color * sizeof(uint32_t));
/* initializing intensity ordered table with serial order of unsorted color table */
for (int i = 0; i < nb_color; i++)
{
iot[i] = i;
}
memset(mcit, 0, nb_color * sizeof(uint32_t));
/* calculate histogram of image */
for (int i = 0; i < size; i++)
{
histogram[bitmap[i]]++;
}
/* sorted in increasing order of intensity */
shell_sort((void*)iot, nb_color, sizeof(*iot), check_trans_tn_intensity, (void*)&ti);
#if OCR_DEBUG
ccx_common_logging.log_ftn("Intensity ordered table\n");
for (int i = 0; i < nb_color; i++)
{
ccx_common_logging.log_ftn("%02d) map %02d hist %02d\n",
i, iot[i], histogram[iot[i]]);
}
#endif
/**
* using selection sort since need to find only max_color
* Hostogram becomes invalid in this loop
*/
for (int i = 0; i < max_color; i++)
{
uint32_t max_val = 0;
uint32_t max_ind = 0;
int j;
for (j = 0; j < nb_color; j++)
{
if (max_val < histogram[iot[j]])
{
max_val = histogram[iot[j]];
max_ind = j;
}
}
for (j = i; j > 0 && max_ind < mcit[j - 1]; j--)
{
mcit[j] = mcit[j - 1];
}
mcit[j] = max_ind;
histogram[iot[max_ind]] = 0;
}
#if OCR_DEBUG
ccx_common_logging.log_ftn("max redundant intensities table\n");
for (int i = 0; i < max_color; i++)
{
ccx_common_logging.log_ftn("%02d) mcit %02d\n",
i, mcit[i]);
}
#endif
for (int i = 0, mxi = 0; i < nb_color; i++)
{
int step, inc;
if (i == mcit[mxi])
{
mxi = (mxi < max_color) ? mxi + 1 : mxi;
continue;
}
inc = (mxi) ? -1 : 0;
step = mcit[mxi + inc] + ((mcit[mxi] - mcit[mxi + inc]) / 2);
if (i <= step)
{
int index = iot[mcit[mxi + inc]];
alpha[iot[i]] = alpha[index];
palette[iot[i]].red = palette[index].red;
palette[iot[i]].blue = palette[index].blue;
palette[iot[i]].green = palette[index].green;
}
else
{
int index = iot[mcit[mxi]];
alpha[iot[i]] = alpha[index];
palette[iot[i]].red = palette[index].red;
palette[iot[i]].blue = palette[index].blue;
palette[iot[i]].green = palette[index].green;
}
}
#if OCR_DEBUG
ccx_common_logging.log_ftn("Colors present in quantized Image\n");
for (int i = 0; i < nb_color; i++)
{
ccx_common_logging.log_ftn("%02d)r %03d g %03d b %03d a %03d\n",
i, palette[i].red, palette[i].green, palette[i].blue, alpha[i]);
}
#endif
end: freep(&histogram);
freep(&mcit);
freep(&iot);
return ret;
}
int ocr_rect(void* arg, struct cc_bitmap *rect, char **str)
{
int ret = 0;
png_color *palette = NULL;
png_byte *alpha = NULL;
palette = (png_color*) malloc(rect[0].nb_colors * sizeof(png_color));
if(!palette)
{
ret = -1;
goto end;
}
alpha = (png_byte*) malloc(rect[0].nb_colors * sizeof(png_byte));
if(!alpha)
{
ret = -1;
goto end;
}
/* TODO do rectangle wise, one color table should not be used for all rectangles */
mapclut_paletee(palette, alpha, (uint32_t *)rect->data[1],rect->nb_colors);
quantize_map(alpha, palette, rect->data[0], rect->w * rect->h, 3, rect->nb_colors);
*str = ocr_bitmap(arg, palette, alpha, rect->data[0], rect->w, rect->h);
end:
freep(&palette);
freep(&alpha);
return ret;
}
#else
char* ocr_bitmap(png_color *palette,png_byte *alpha, unsigned char* indata,unsigned char d,int w, int h)
{

View File

@ -1,6 +1,9 @@
#ifndef OCR_H
#define OCR_H
#include <png.h>
char* ocr_bitmap(png_color *palette,png_byte *alpha, unsigned char* indata,int w, int h);
void* init_ocr(int lang_index);
char* ocr_bitmap(void* arg, png_color *palette,png_byte *alpha, unsigned char* indata,int w, int h);
int ocr_rect(void* arg, struct cc_bitmap *rect, char **str);
#endif

View File

@ -334,7 +334,7 @@ void set_spupng_offset(void *ctx,int x,int y)
sp->xOffset = x;
sp->yOffset = y;
}
static int save_spupng(const char *filename, uint8_t *bitmap, int w, int h,
int save_spupng(const char *filename, uint8_t *bitmap, int w, int h,
png_color *palette, png_byte *alpha, int nb_color)
{
FILE *f = NULL;
@ -458,181 +458,6 @@ int mapclut_paletee(png_color *palette, png_byte *alpha, uint32_t *clut,
return 0;
}
struct transIntensity
{
uint8_t *t;
png_color *palette;
};
int check_trans_tn_intensity(const void *p1, const void *p2, void *arg)
{
struct transIntensity *ti = arg;
unsigned char* tmp = (unsigned char*)p1;
unsigned char* act = (unsigned char*)p2;
unsigned char tmp_i;
unsigned char act_i;
/** TODO verify that RGB follow ITU-R BT.709
* Below fomula is valid only for 709 standurd
* Y = 0.2126 R + 0.7152 G + 0.0722 B
*/
tmp_i = (0.2126 * ti->palette[*tmp].red) + (0.7152 * ti->palette[*tmp].green) + (0.0722 * ti->palette[*tmp].blue);
act_i = (0.2126 * ti->palette[*act].red) + (0.7152 * ti->palette[*act].green) + (0.0722 * ti->palette[*act].blue);;
if (ti->t[*tmp] < ti->t[*act] || (ti->t[*tmp] == ti->t[*act] && tmp_i < act_i))
return -1;
else if (ti->t[*tmp] == ti->t[*act] && tmp_i == act_i)
return 0;
return 1;
}
/*
* @param alpha out
* @param intensity in
* @param palette out should be already initialized
* @param bitmap in
* @param size in size of bitmap
* @param max_color in
* @param nb_color in
*/
int quantize_map(png_byte *alpha, png_color *palette,
uint8_t *bitmap, int size, int max_color, int nb_color)
{
/*
* occurrence of color in image
*/
uint32_t *histogram = NULL;
/* intensity ordered table */
uint8_t *iot = NULL;
/* array of color with most occurrence according to histogram
* save index of intensity order table
*/
uint32_t *mcit = NULL;
struct transIntensity ti = { alpha,palette};
int ret = 0;
histogram = (uint32_t*) malloc(nb_color * sizeof(uint32_t));
if (!histogram)
{
ret = -1;
goto end;
}
iot = (uint8_t*) malloc(nb_color * sizeof(uint8_t));
if (!iot)
{
ret = -1;
goto end;
}
mcit = (uint32_t*) malloc(nb_color * sizeof(uint32_t));
if (!mcit)
{
ret = -1;
goto end;
}
memset(histogram, 0, nb_color * sizeof(uint32_t));
/* initializing intensity ordered table with serial order of unsorted color table */
for (int i = 0; i < nb_color; i++)
{
iot[i] = i;
}
memset(mcit, 0, nb_color * sizeof(uint32_t));
/* calculate histogram of image */
for (int i = 0; i < size; i++)
{
histogram[bitmap[i]]++;
}
/* sorted in increasing order of intensity */
shell_sort((void*)iot, nb_color, sizeof(*iot), check_trans_tn_intensity, (void*)&ti);
#if OCR_DEBUG
ccx_common_logging.log_ftn("Intensity ordered table\n");
for (int i = 0; i < nb_color; i++)
{
ccx_common_logging.log_ftn("%02d) map %02d hist %02d\n",
i, iot[i], histogram[iot[i]]);
}
#endif
/**
* using selection sort since need to find only max_color
* Hostogram becomes invalid in this loop
*/
for (int i = 0; i < max_color; i++)
{
uint32_t max_val = 0;
uint32_t max_ind = 0;
int j;
for (j = 0; j < nb_color; j++)
{
if (max_val < histogram[iot[j]])
{
max_val = histogram[iot[j]];
max_ind = j;
}
}
for (j = i; j > 0 && max_ind < mcit[j - 1]; j--)
{
mcit[j] = mcit[j - 1];
}
mcit[j] = max_ind;
histogram[iot[max_ind]] = 0;
}
#if OCR_DEBUG
ccx_common_logging.log_ftn("max redundant intensities table\n");
for (int i = 0; i < max_color; i++)
{
ccx_common_logging.log_ftn("%02d) mcit %02d\n",
i, mcit[i]);
}
#endif
for (int i = 0, mxi = 0; i < nb_color; i++)
{
int step, inc;
if (i == mcit[mxi])
{
mxi = (mxi < max_color) ? mxi + 1 : mxi;
continue;
}
inc = (mxi) ? -1 : 0;
step = mcit[mxi + inc] + ((mcit[mxi] - mcit[mxi + inc]) / 2);
if (i <= step)
{
int index = iot[mcit[mxi + inc]];
alpha[iot[i]] = alpha[index];
palette[iot[i]].red = palette[index].red;
palette[iot[i]].blue = palette[index].blue;
palette[iot[i]].green = palette[index].green;
}
else
{
int index = iot[mcit[mxi]];
alpha[iot[i]] = alpha[index];
palette[iot[i]].red = palette[index].red;
palette[iot[i]].blue = palette[index].blue;
palette[iot[i]].green = palette[index].green;
}
}
#if OCR_DEBUG
ccx_common_logging.log_ftn("Colors present in quantized Image\n");
for (int i = 0; i < nb_color; i++)
{
ccx_common_logging.log_ftn("%02d)r %03d g %03d b %03d a %03d\n",
i, palette[i].red, palette[i].green, palette[i].blue, alpha[i]);
}
#endif
end: freep(&histogram);
freep(&mcit);
freep(&iot);
return ret;
}
int write_cc_bitmap_as_spupng(struct cc_subtitle *sub, struct encoder_ctx *context)
{
struct spupng_t *sp = (struct spupng_t *)context->out->spupng_data;
@ -643,9 +468,6 @@ 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;
#ifdef ENABLE_OCR
char*str = NULL;
#endif
x_pos = -1;
y_pos = -1;
@ -730,14 +552,12 @@ int write_cc_bitmap_as_spupng(struct cc_subtitle *sub, struct encoder_ctx *conte
goto end;
}
#ifdef ENABLE_OCR
/* TODO do rectangle wise, one color table should not be used for all rectangles */
mapclut_paletee(palette, alpha, (uint32_t *)rect[0].data[1],rect[0].nb_colors);
quantize_map(alpha, palette, pbuf, width*height, 3, rect[0].nb_colors);
str = ocr_bitmap(palette,alpha,pbuf,width,height);
if(str && str[0])
#if ENABLE_OCR
if (rect[0].ocr_text && *(rect[0].ocr_text))
{
write_spucomment(sp,str);
write_spucomment(sp, rect[0].ocr_text);
}
#endif
save_spupng(filename,pbuf,width, height, palette, alpha,rect[0].nb_colors);

View File

@ -34,6 +34,4 @@ void inc_spupng_fileindex(void *ctx);
void set_spupng_offset(void *ctx,int x,int y);
int mapclut_paletee(png_color *palette, png_byte *alpha, uint32_t *clut,
uint8_t depth);
int quantize_map(png_byte *alpha, png_color *palette,
uint8_t *bitmap, int size, int max_color, int nb_color);
#endif