mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
Fixed scaling subtitles with anti-aliasing
This commit is contained in:
parent
3d55d3045e
commit
f672fe90c1
@ -1228,6 +1228,7 @@ Peter Bieringer <pb@bieringer.de>
|
|||||||
external commands
|
external commands
|
||||||
for making the functions cRecordingInfo::SetData() and cRecordingInfo::SetAux() public
|
for making the functions cRecordingInfo::SetData() and cRecordingInfo::SetAux() public
|
||||||
for adding some missing user command calls for copying, renaming and moving recordings
|
for adding some missing user command calls for copying, renaming and moving recordings
|
||||||
|
for fixing scaling subtitles with anti-aliasing
|
||||||
|
|
||||||
Alexander Damhuis <ad@phonedation.de>
|
Alexander Damhuis <ad@phonedation.de>
|
||||||
for reporting problems when deleting a timer that is currently recording
|
for reporting problems when deleting a timer that is currently recording
|
||||||
|
1
HISTORY
1
HISTORY
@ -9616,3 +9616,4 @@ Video Disk Recorder Revision History
|
|||||||
"TITLE - EPISODE" and "TITLE: EPISODE" the same.
|
"TITLE - EPISODE" and "TITLE: EPISODE" the same.
|
||||||
- Decreased the scrambling timeout for CAMs known to decrypt a certain channel, so
|
- Decreased the scrambling timeout for CAMs known to decrypt a certain channel, so
|
||||||
that it won't collide with MAXBROKENTIMEOUT in recorder.c.
|
that it won't collide with MAXBROKENTIMEOUT in recorder.c.
|
||||||
|
- Fixed scaling subtitles with anti-aliasing (thanks to Peter Bieringer).
|
||||||
|
109
dvbsubtitle.c
109
dvbsubtitle.c
@ -7,7 +7,7 @@
|
|||||||
* Original author: Marco Schluessler <marco@lordzodiac.de>
|
* Original author: Marco Schluessler <marco@lordzodiac.de>
|
||||||
* With some input from the "subtitles plugin" by Pekka Virtanen <pekka.virtanen@sci.fi>
|
* With some input from the "subtitles plugin" by Pekka Virtanen <pekka.virtanen@sci.fi>
|
||||||
*
|
*
|
||||||
* $Id: dvbsubtitle.c 4.2 2020/05/15 12:32:51 kls Exp $
|
* $Id: dvbsubtitle.c 5.1 2021/03/17 15:24:34 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dvbsubtitle.h"
|
#include "dvbsubtitle.h"
|
||||||
@ -993,7 +993,9 @@ public:
|
|||||||
int64_t Pts(void) const { return pts; }
|
int64_t Pts(void) const { return pts; }
|
||||||
bool Pending(void) { return pending; }
|
bool Pending(void) { return pending; }
|
||||||
cSubtitleObjects *Objects(void) { return &objects; }
|
cSubtitleObjects *Objects(void) { return &objects; }
|
||||||
tArea *GetAreas(int &NumAreas, double FactorX, double FactorY);
|
tArea *GetAreas(int &NumAreas);
|
||||||
|
tArea CombineAreas(int NumAreas, const tArea *Areas);
|
||||||
|
tArea ScaleArea(const tArea &Area, double FactorX, double FactorY);
|
||||||
cSubtitleObject *GetObjectById(int ObjectId, bool New = false);
|
cSubtitleObject *GetObjectById(int ObjectId, bool New = false);
|
||||||
cSubtitleClut *GetClutById(int ClutId, bool New = false);
|
cSubtitleClut *GetClutById(int ClutId, bool New = false);
|
||||||
cSubtitleRegion *GetRegionById(int RegionId, bool New = false);
|
cSubtitleRegion *GetRegionById(int RegionId, bool New = false);
|
||||||
@ -1077,7 +1079,7 @@ void cDvbSubtitlePage::ParsePgs(int64_t Pts, cBitStream &bs)
|
|||||||
pending = true;
|
pending = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
tArea *cDvbSubtitlePage::GetAreas(int &NumAreas, double FactorX, double FactorY)
|
tArea *cDvbSubtitlePage::GetAreas(int &NumAreas)
|
||||||
{
|
{
|
||||||
if (regions.Count() > 0) {
|
if (regions.Count() > 0) {
|
||||||
NumAreas = regionRefs.Count();
|
NumAreas = regionRefs.Count();
|
||||||
@ -1085,13 +1087,11 @@ tArea *cDvbSubtitlePage::GetAreas(int &NumAreas, double FactorX, double FactorY)
|
|||||||
tArea *a = Areas;
|
tArea *a = Areas;
|
||||||
for (cSubtitleRegionRef *srr = regionRefs.First(); srr; srr = regionRefs.Next(srr)) {
|
for (cSubtitleRegionRef *srr = regionRefs.First(); srr; srr = regionRefs.Next(srr)) {
|
||||||
if (cSubtitleRegion *sr = GetRegionById(srr->RegionId())) {
|
if (cSubtitleRegion *sr = GetRegionById(srr->RegionId())) {
|
||||||
a->x1 = int(round(FactorX * srr->RegionHorizontalAddress()));
|
a->x1 = srr->RegionHorizontalAddress();
|
||||||
a->y1 = int(round(FactorY * srr->RegionVerticalAddress()));
|
a->y1 = srr->RegionVerticalAddress();
|
||||||
a->x2 = int(round(FactorX * (srr->RegionHorizontalAddress() + sr->RegionWidth() - 1)));
|
a->x2 = srr->RegionHorizontalAddress() + sr->RegionWidth() - 1;
|
||||||
a->y2 = int(round(FactorY * (srr->RegionVerticalAddress() + sr->RegionHeight() - 1)));
|
a->y2 = srr->RegionVerticalAddress() + sr->RegionHeight() - 1;
|
||||||
a->bpp = sr->RegionDepth();
|
a->bpp = sr->RegionDepth();
|
||||||
while ((a->Width() & 3) != 0)
|
|
||||||
a->x2++; // aligns width to a multiple of 4, so 2, 4 and 8 bpp will work
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
a->x1 = a->y1 = a->x2 = a->y2 = a->bpp = 0;
|
a->x1 = a->y1 = a->x2 = a->y2 = a->bpp = 0;
|
||||||
@ -1103,6 +1103,37 @@ tArea *cDvbSubtitlePage::GetAreas(int &NumAreas, double FactorX, double FactorY)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tArea cDvbSubtitlePage::CombineAreas(int NumAreas, const tArea *Areas)
|
||||||
|
{
|
||||||
|
tArea a;
|
||||||
|
a.x1 = INT_MAX;
|
||||||
|
a.x2 = INT_MIN;
|
||||||
|
a.y1 = INT_MAX;
|
||||||
|
a.y2 = INT_MIN;
|
||||||
|
a.bpp = 1;
|
||||||
|
for (int i = 0; i < NumAreas; i++) {
|
||||||
|
a.x1 = min(a.x1, Areas[i].x1);
|
||||||
|
a.x2 = max(a.x2, Areas[i].x2);
|
||||||
|
a.y1 = min(a.y1, Areas[i].y1);
|
||||||
|
a.y2 = max(a.y2, Areas[i].y2);
|
||||||
|
a.bpp = max(a.bpp, Areas[i].bpp);
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
tArea cDvbSubtitlePage::ScaleArea(const tArea &Area, double FactorX, double FactorY)
|
||||||
|
{
|
||||||
|
tArea a;
|
||||||
|
a.x1 = int(round(FactorX * Area.x1) );
|
||||||
|
a.x2 = int(round(FactorX * Area.x2) - 1);
|
||||||
|
a.y1 = int(round(FactorY * Area.y1) );
|
||||||
|
a.y2 = int(round(FactorY * Area.y2) - 1);
|
||||||
|
a.bpp = Area.bpp;
|
||||||
|
while ((a.Width() & 3) != 0)
|
||||||
|
a.x2++; // aligns width to a multiple of 4, so 2, 4 and 8 bpp will work
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
cSubtitleClut *cDvbSubtitlePage::GetClutById(int ClutId, bool New)
|
cSubtitleClut *cDvbSubtitlePage::GetClutById(int ClutId, bool New)
|
||||||
{
|
{
|
||||||
for (cSubtitleClut *sc = cluts.First(); sc; sc = cluts.Next(sc)) {
|
for (cSubtitleClut *sc = cluts.First(); sc; sc = cluts.Next(sc)) {
|
||||||
@ -1219,11 +1250,13 @@ private:
|
|||||||
int timeout;
|
int timeout;
|
||||||
tArea *areas;
|
tArea *areas;
|
||||||
int numAreas;
|
int numAreas;
|
||||||
|
tArea areaCombined;
|
||||||
|
tArea areaOsd;
|
||||||
double osdFactorX;
|
double osdFactorX;
|
||||||
double osdFactorY;
|
double osdFactorY;
|
||||||
cVector<cBitmap *> bitmaps;
|
cVector<cBitmap *> bitmaps;
|
||||||
public:
|
public:
|
||||||
cDvbSubtitleBitmaps(int State, int64_t Pts, int Timeout, tArea *Areas, int NumAreas, double OsdFactorX, double OsdFactorY);
|
cDvbSubtitleBitmaps(int State, int64_t Pts, int Timeout, tArea *Areas, int NumAreas, double OsdFactorX, double OsdFactorY, tArea &AreaCombined, tArea &AreaOsd);
|
||||||
~cDvbSubtitleBitmaps();
|
~cDvbSubtitleBitmaps();
|
||||||
int State(void) { return state; }
|
int State(void) { return state; }
|
||||||
int64_t Pts(void) { return pts; }
|
int64_t Pts(void) { return pts; }
|
||||||
@ -1234,13 +1267,15 @@ public:
|
|||||||
void DbgDump(int WindowWidth, int WindowHeight);
|
void DbgDump(int WindowWidth, int WindowHeight);
|
||||||
};
|
};
|
||||||
|
|
||||||
cDvbSubtitleBitmaps::cDvbSubtitleBitmaps(int State, int64_t Pts, int Timeout, tArea *Areas, int NumAreas, double OsdFactorX, double OsdFactorY)
|
cDvbSubtitleBitmaps::cDvbSubtitleBitmaps(int State, int64_t Pts, int Timeout, tArea *Areas, int NumAreas, double OsdFactorX, double OsdFactorY, tArea &AreaCombined, tArea &AreaOsd)
|
||||||
{
|
{
|
||||||
state = State;
|
state = State;
|
||||||
pts = Pts;
|
pts = Pts;
|
||||||
timeout = Timeout;
|
timeout = Timeout;
|
||||||
areas = Areas;
|
areas = Areas;
|
||||||
numAreas = NumAreas;
|
numAreas = NumAreas;
|
||||||
|
areaCombined = AreaCombined;
|
||||||
|
areaOsd = AreaOsd;
|
||||||
osdFactorX = OsdFactorX;
|
osdFactorX = OsdFactorX;
|
||||||
osdFactorY = OsdFactorY;
|
osdFactorY = OsdFactorY;
|
||||||
}
|
}
|
||||||
@ -1260,25 +1295,25 @@ void cDvbSubtitleBitmaps::AddBitmap(cBitmap *Bitmap)
|
|||||||
void cDvbSubtitleBitmaps::Draw(cOsd *Osd)
|
void cDvbSubtitleBitmaps::Draw(cOsd *Osd)
|
||||||
{
|
{
|
||||||
bool Scale = !(DoubleEqual(osdFactorX, 1.0) && DoubleEqual(osdFactorY, 1.0));
|
bool Scale = !(DoubleEqual(osdFactorX, 1.0) && DoubleEqual(osdFactorY, 1.0));
|
||||||
bool AntiAlias = true;
|
bool AntiAlias = Setup.AntiAlias;
|
||||||
if (Scale && osdFactorX > 1.0 || osdFactorY > 1.0) {
|
if (Scale && osdFactorX > 1.0 || osdFactorY > 1.0) {
|
||||||
// Upscaling requires 8bpp:
|
// Upscaling requires 8bpp:
|
||||||
int Bpp[MAXOSDAREAS];
|
int Bpp = areaOsd.bpp;
|
||||||
for (int i = 0; i < numAreas; i++) {
|
areaOsd.bpp = 8;
|
||||||
Bpp[i] = areas[i].bpp;
|
if (Osd->CanHandleAreas(&areaOsd, 1) != oeOk) {
|
||||||
areas[i].bpp = 8;
|
areaOsd.bpp = Bpp;
|
||||||
}
|
|
||||||
if (Osd->CanHandleAreas(areas, numAreas) != oeOk) {
|
|
||||||
for (int i = 0; i < numAreas; i++)
|
|
||||||
areas[i].bpp = Bpp[i];
|
|
||||||
AntiAlias = false;
|
AntiAlias = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (State() == 0 || Osd->SetAreas(areas, numAreas) == oeOk) {
|
if (State() == 0 || Osd->SetAreas(&areaOsd, 1) == oeOk) {
|
||||||
|
cBitmap combined(areaCombined.Width(), areaCombined.Height(), areaCombined.bpp);
|
||||||
|
combined.SetOffset(areaCombined.x1, areaCombined.y1);
|
||||||
for (int i = 0; i < bitmaps.Size(); i++) {
|
for (int i = 0; i < bitmaps.Size(); i++) {
|
||||||
|
// merge bitmaps into combined
|
||||||
cBitmap *b = bitmaps[i];
|
cBitmap *b = bitmaps[i];
|
||||||
Osd->DrawScaledBitmap(int(round(b->X0() * osdFactorX)), int(round(b->Y0() * osdFactorY)), *b, osdFactorX, osdFactorY, AntiAlias);
|
combined.DrawBitmap(b->X0(), b->Y0(), *b);
|
||||||
}
|
}
|
||||||
|
Osd->DrawScaledBitmap(int(round(combined.X0() * osdFactorX)), int(round(combined.Y0() * osdFactorY)), combined, osdFactorX, osdFactorY, AntiAlias);
|
||||||
Osd->Flush();
|
Osd->Flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1734,25 +1769,27 @@ void cDvbSubtitleConverter::FinishPage(cDvbSubtitlePage *Page)
|
|||||||
if (!AssertOsd())
|
if (!AssertOsd())
|
||||||
return;
|
return;
|
||||||
int NumAreas;
|
int NumAreas;
|
||||||
tArea *Areas = Page->GetAreas(NumAreas, osdFactorX, osdFactorY);
|
tArea *Areas = Page->GetAreas(NumAreas);
|
||||||
|
tArea AreaCombined = Page->CombineAreas(NumAreas, Areas);
|
||||||
|
tArea AreaOsd = Page->ScaleArea(AreaCombined, osdFactorX, osdFactorY);
|
||||||
int Bpp = 8;
|
int Bpp = 8;
|
||||||
bool Reduced = false;
|
bool Reduced = false;
|
||||||
while (osd && osd->CanHandleAreas(Areas, NumAreas) != oeOk) {
|
if (osd && NumAreas > 0) {
|
||||||
dbgoutput("CanHandleAreas: %d<br>\n", osd->CanHandleAreas(Areas, NumAreas));
|
while (osd->CanHandleAreas(&AreaOsd, 1) != oeOk) {
|
||||||
int HalfBpp = Bpp / 2;
|
dbgoutput("CanHandleAreas: %d<br>\n", osd->CanHandleAreas(&AreaOsd, 1));
|
||||||
if (HalfBpp >= 2) {
|
int HalfBpp = Bpp / 2;
|
||||||
for (int i = 0; i < NumAreas; i++) {
|
if (HalfBpp >= 2) {
|
||||||
if (Areas[i].bpp >= Bpp) {
|
if (AreaOsd.bpp >= Bpp) {
|
||||||
Areas[i].bpp = HalfBpp;
|
AreaOsd.bpp = HalfBpp;
|
||||||
Reduced = true;
|
Reduced = true;
|
||||||
}
|
}
|
||||||
}
|
Bpp = HalfBpp;
|
||||||
Bpp = HalfBpp;
|
}
|
||||||
|
else
|
||||||
|
return; // unable to draw bitmaps
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
return; // unable to draw bitmaps
|
cDvbSubtitleBitmaps *Bitmaps = new cDvbSubtitleBitmaps(Page->PageState(), Page->Pts(), Page->PageTimeout(), Areas, NumAreas, osdFactorX, osdFactorY, AreaCombined, AreaOsd);
|
||||||
}
|
|
||||||
cDvbSubtitleBitmaps *Bitmaps = new cDvbSubtitleBitmaps(Page->PageState(), Page->Pts(), Page->PageTimeout(), Areas, NumAreas, osdFactorX, osdFactorY);
|
|
||||||
bitmaps->Add(Bitmaps);
|
bitmaps->Add(Bitmaps);
|
||||||
for (int i = 0; i < NumAreas; i++) {
|
for (int i = 0; i < NumAreas; i++) {
|
||||||
if (cSubtitleRegionRef *srr = Page->GetRegionRefByIndex(i)) {
|
if (cSubtitleRegionRef *srr = Page->GetRegionRefByIndex(i)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user