Vobsub format -- How to change color palette in .sub file

Discussion about Txt2Vobsub. Requests and bug fixing.

Moderators: george, roger_rabbit

Post Reply
vince100
Junior Member
Posts: 6
Joined: Thu Jun 07, 2007 11:04 pm

Vobsub format -- How to change color palette in .sub file

Post by vince100 »

Could someone please point me to a detailed documentation of the vobsub format?

I'd like to directly change the DVD color palette in the .sub file (not by changing the .idx file).

This is necessary when merging two .sub files with different color palettes.

Since Txt2Vobsub can write .sub files, I figure you may know, TrustFm?
trustfm
Site Admin
Posts: 1649
Joined: Sun Feb 27, 2005 4:40 pm

Post by trustfm »

as far as i remember the sub file does NOT have that information ! Has only the trasparency information. Unfortunatelly the colors pallette is taken from the IFO file ...
vince100
Junior Member
Posts: 6
Joined: Thu Jun 07, 2007 11:04 pm

Post by vince100 »

I think some color indexes are stored in the .sub file, although the palette itself is in the .idx file.

That's why changing the palette in the .idx file will show weird colors.

So one way to correct the color problem is to change those indexes according to the indexes used in the first subtitle.

I think it will work if two palettes have the same colors but in different order, but not if the two palettes have completely different colors.

Do you think there are some other solutions?


P.S. sorry, probably i should have posted this in VobsubMuxer section ... please feel free to move it ...
Last edited by vince100 on Fri Jun 08, 2007 6:39 pm, edited 1 time in total.
vince100
Junior Member
Posts: 6
Joined: Thu Jun 07, 2007 11:04 pm

Post by vince100 »

On a second thought, I think it should work regardless.

Just use the color indexes of the first subtitle for the rest of subtitles.

Since the first one should look ok, the rest should look ok too, although maybe a bit different from the original.

The problem now is which bytes store those information (most likely it's two or four bytes with the color indexes of BG-TEXT-ANITALISING-OUTLINE).
vince100
Junior Member
Posts: 6
Joined: Thu Jun 07, 2007 11:04 pm

Post by vince100 »

hmm, this is more complicated than i thought --- it turned out each subtitle image has its own color and transparency info.


bool CVobSubImage::Decode(uchar* lpData, int packetsize, int datasize,
bool fCustomPal,
int tridx,
RGBQUAD* orgpal /*[16]*/, RGBQUAD* cuspal /*[4]*/,
bool fTrim)
{
GetPacketInfo(lpData, packetsize, datasize);

if(!Alloc(rect.Width(), rect.Height())) return(false);

lpPixels = lpTemp1;

nPlane = 0;
fAligned = 1;

this->fCustomPal = fCustomPal;
this->orgpal = orgpal;
this->tridx = tridx;
this->cuspal = cuspal;

CPoint p(rect.left, rect.top);

int end0 = nOffset[1];
int end1 = datasize;

while((nPlane == 0 && nOffset[0] < end0) || (nPlane == 1 && nOffset[1] < end1))
{
uint code;

if((code = GetNibble(lpData)) >= 0x4
|| (code = (code << 4) | GetNibble(lpData)) >= 0x10
|| (code = (code << 4) | GetNibble(lpData)) >= 0x40
|| (code = (code << 4) | GetNibble(lpData)) >= 0x100)
{
DrawPixels(p, code >> 2, code & 3);
if((p.x += code >> 2) < rect.right) continue;
}

DrawPixels(p, rect.right - p.x, code & 3);

if(!fAligned) GetNibble(lpData); // align to byte

p.x = rect.left;
p.y++;
nPlane = 1 - nPlane;
}

rect.bottom = min(p.y, rect.bottom);

if(fTrim) TrimSubImage();

return(true);
}

void CVobSubImage::GetPacketInfo(uchar* lpData, int packetsize, int datasize)
{
int nextctrlblk = datasize;

int i;

ushort pal = 0, tr = 0;

do
{
i = nextctrlblk;

int t = (lpData << 8) | lpData[i+1]; i += 2;
nextctrlblk = (lpData << 8) | lpData[i+1]; i += 2;

bool fBreak = false;

while(!fBreak)
{
int len = 0;

switch(lpData)
{
case 0x00: len = 0; break;
case 0x01: len = 0; break;
case 0x02: len = 0; break;
case 0x03: len = 2; break;
case 0x04: len = 2; break;
case 0x05: len = 6; break;
case 0x06: len = 4; break;
default: len = 0; break;
}

if(i+len >= packetsize)
{
TRACE(_T("Warning: Wrong subpicture parameter block ending\n"));
break;
}

switch(lpData[i++])
{
case 0x00: // forced start displaying
fForced = true;
break;
case 0x01: // start displaying
fForced = false;
break;
case 0x02: // stop displaying
nDisplayTime = 1024 * t / 90;
break;
case 0x03:
pal = (lpData << 8) | lpData[i+1]; i += 2;
break;
case 0x04:
tr = (lpData << 8) | lpData[i+1]; i += 2;
break;
case 0x05:
rect = CRect((lpData << 4) + (lpData[i+1] >> 4),
(lpData[i+3] << 4) + (lpData[i+4] >> 4),
((lpData[i+1] & 0x0f) << 8) + lpData[i+2] + 1,
((lpData[i+4] & 0x0f) << 8) + lpData[i+5] + 1);
i += 6;
break;
case 0x06:
nOffset[0] = (lpData << 8) + lpData[i+1]; i += 2;
nOffset[1] = (lpData << 8) + lpData[i+1]; i += 2;
break;
case 0xff: // end of ctrlblk
fBreak = true;
continue;
default: // skip this ctrlblk
fBreak = true;
break;
}
}
}
while(i <= nextctrlblk && i < packetsize && nextctrlblk < packetsize-4);

if(nextctrlblk > packetsize-4)
{
TRACE(_T("Warning: Wrong subpicture parameter block ending\n"));
}

for(i = 0; i < 4; i++)
{
this->pal.pal = (pal >> (i << 2)) & 0xf;
this->pal.tr = (tr >> (i << 2)) & 0xf;
}

}
Post Reply