⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 subpicture.java

📁 优秀的MPEG2-TS流分析软件
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * @(#)SUBPICTURE.java - creates SUP file to use as DVD subtitles
 *
 * Copyright (c) 2003-2005 by dvb.matt, All Rights Reserved.
 * 
 * This file is part of X, a free Java based demux utility.
 * X is intended for educational purposes only, as a non-commercial test project.
 * It may not be used otherwise. Most parts are only experimental.
 * 
 *
 * This program is free software; you can redistribute it free of charge
 * and/or modify it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

/*
 * thanx to Samuel Hocevar for his very helpful annotations of DVD subtitle RLE stuff
 * http://www.via.ecp.fr/~sam/doc/dvd/
 */

package net.sourceforge.dvb.projectx.subtitle;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.font.FontRenderContext;
import java.awt.image.BufferedImage;
import java.awt.geom.Rectangle2D;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.StringTokenizer;

import javax.swing.JFrame;
import javax.swing.JPanel;

import net.sourceforge.dvb.projectx.common.Resource;
import net.sourceforge.dvb.projectx.common.X;



public class SubPicture extends JFrame
{

public Picture picture;

String title = Resource.getString("subpicture.title");

public SubPicture()
{
	addWindowListener(new WindowAdapter()
	{
		public void windowClosing(WindowEvent e)
		{
			close();
		}
	});

	picture = new Picture();
	picture.run(); //DM18052004 081.7 int02 add

	getContentPane().add("Center", picture);

	setTitle(title);
	setSize(new Dimension(726,601)); //DM24012004 081.6 int11 changed, //DM20042004 081.7 int02 changed
	setLocation(100,100);
	setResizable(false); //DM17042004 081.7 int02 add
	//setVisible(false);
}

public void newTitle(String newtitle)
{
	setTitle(title+" "+newtitle); 
}

public void close()
{ 
	dispose(); //DM18052004 081.7 int02 changed
}


public class Picture extends JPanel implements Runnable
{
	public java.text.DateFormat sms = new java.text.SimpleDateFormat("HH:mm:ss.SSS");
	public Thread thread;
	private int w=720, h=576, x=20, nibble=0, val=0, default_alpha=10; //DM24012004 081.6 int11 changed, //DM20042004 081.7 int02 changed
	private int modified_alpha = 0;

	private BufferedImage bimg;
	private Graphics2D big;
	private Font font, font_alt, font_std; //DM30122003 081.6 int10 add, //DM01032004 081.6 int18 add
	private FontRenderContext frc;

	//DM26052004 081.7 int03 changed
	private final int default_teletext_colors[] = {
		//bg = 0 = black
		0xFF606060, //Y 40%
		0xFFEB6060, //red lighter
		0xFF10EB10, //green
		0xFFEBEB10, //yellow
		0xFF5050EB, //blue lighter
		0xFFEB60EB, //magenta lighter
		0xFF10EBEB, //cyan
		0xFFEBEBEB, //Y 100%

		//bg = 1 = red
		0xFF606060, //Y black
		0xFFE06060, //red
		0xFF60E060, //green
		0xFFE0E060, //yellow
		0xFF6060E0, //blue
		0xFFE060E0, //magenta
		0xFF60E0E0, //cyan
		0xFFE0E0E0, //white-gray

		//bg = 2 = green
		0xFF707070, //Y black
		0xFFD07070, //red
		0xFF70D070, //green
		0xFFD0D070, //yellow
		0xFF7070D0, //blue
		0xFFD070D0, //magenta
		0xFF70D0D0, //cyan
		0xFFD0D0D0, //white-gray

		//bg = 3 = yellow
		0xFF808080, //Y black
		0xFFC08080, //red
		0xFF80C080, //green
		0xFFC0C080, //yellow
		0xFF8080C0, //blue
		0xFFC080C0, //magenta
		0xFF80C0C0, //cyan
		0xFFC0C0C0, //white-gray

		//bg = 4 = blue
		0xFF909090, //Y black
		0xFFC09090, //red
		0xFF90C090, //green
		0xFFC0C090, //yellow
		0xFF9090C0, //blue
		0xFFC090C0, //magenta
		0xFF90C0C0, //cyan
		0xFFB0B0B0, //white-gray

		//bg = 5 = magenta
		0xFFA0A0A0, //Y black
		0xFFB0A0A0, //red
		0xFFA0B0A0, //green
		0xFFB0B0A0, //yellow
		0xFFA0A0B0, //blue
		0xFFB0A0B0, //magenta
		0xFFA0B0B0, //cyan
		0xFFA0A0A0, //white-gray

		//bg = 6 = cyan
		0xFFB0B0B0, //Y black
		0xFFC0A0A0, //red
		0xFFA0D0A0, //green
		0xFFC0D0A0, //yellow
		0xFFA0A0D0, //blue
		0xFFD0A0D0, //magenta
		0xFFA0D0D0, //cyan
		0xFF909090, //white-gray

		//bg = 7 = white
		0xFFD0D0D0, //Y black
		0xFFE09090, //red
		0xFF90E090, //green
		0xFFE0E090, //yellow
		0xFF9090E0, //blue
		0xFFE090E0, //magenta
		0xFF90E0E0, //cyan
		0xFF808080, //white-gray

		0, // backgr black, user_transparency
		0x80 // backgr blue, sign for full transparency
	};

	private final int default_sup_colors[] = {
		0xFF101010, //black
		0xFFA0A0A0, //Y 50%
		0xFFEBEBEB, //Y 100%
		0xFF606060, //Y 25%
		0xFFEB1010, //red
		0xFF10EB10, //green
		0xFFEBEB10, //yellow
		0xFF1010EB, //blue
		0xFFEB10EB, //magenta
		0xFF10EBEB, //cyan
		0xFFEB8080, //red lighter
		0xFF80EB80, //green lighter
		0xFFEBEB80, //yellow lighter
		0xFF8080EB, //blue lighter
		0xFFEB80EB, //magante lighter
		0xFF80EBEB, //cyan lighter
		0 // full transparency black bg
	};

	private Object[] str = new Object[0];
	private byte[] RLEheader = { 0x53,0x50,0,0,0,0,0,0,0,0,0,0,0,0 }; // startcode + later reverse 5PTS, DTS=0
	private byte[] sections = {
		0, 0,           // next contr sequ.
		3, 0x32, 0x10,         // color palette linkage
		4, (byte)0xFF, (byte)0xFA,         // color alpha channel linkage F=opaque
		5, 0, 0, 0, 0, 0, 0, // coordinates Xa,Ya,Xe,Ye
		6, 0, 0, 0, 0,     // bytepos start top_field, start bottom_field
		1,  // start displ.  //0 means force display
		(byte)0xFF,    // end of sequ.
		1, 0x50,  // time for next sequ,
		0, 0,  //next contr sequ.
		2,   // stop displ.
		(byte)0xFF     // end of sequ: timedur in pts/1100, size s.a. , add 0xFF if size is not WORD aligned
	};

	private ByteArrayOutputStream out = new ByteArrayOutputStream();
	private byte newline[] = { 0,0 };
	private int Rect[] = new int[4];
	private int pos[] = new int[4];
	private int option[] = new int[10]; //DM26052004 081.7 int03 changed

	//DM26052004 081.7 int03 changed
	private int standard_values[] = { 26, 10, 32, 80, 560, 720, 576, -1, 4 };

	private ArrayList user_color_table = new ArrayList();
	private Bitmap bitmap;
	private boolean read_from_Image = false;
	private int isforced_status = 0;
	private boolean global_error = false;

	private int line_offset = 28;

	public DVBSubpicture dvb = new DVBSubpicture(); //DM24042004 081.7 int02 new

	public Picture()
	{ 
		bimg = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
		big = bimg.createGraphics();

		set("Tahoma", ("" + "26;10;32;80;560;720;576;-1;4"));
		frc = big.getFontRenderContext();

		//   big.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

		setBackground(Color.gray);
		sms.setTimeZone(java.util.TimeZone.getTimeZone("GMT+0:00"));
	}

	public void paint(Graphics g)
	{
		if (big == null) 
			return;

		g.drawImage(bimg, 0, 0, this);
	}

	/*** paint pic from ttx **/
	public void showPicTTX(Object[] str)
	{
		this.str = str;
		buildImgTTX();
		repaint();
	}

	// set display time
	//DM22032004 081.6 int18 changed
	//DM26052004 081.7 int03 changed
	public byte[] setTime(byte tmp[], long out_time)
	{
		long in_time = 0;

		for (int a=0; a<4; a++) // in_pts
			in_time |= (0xFF & tmp[a+2])<<(a*8);

		//long difference = (long)Math.round((out_time - in_time) / 1100.0); // 900.0
		long difference = 1L + ((out_time - in_time) / 1000);

		int tp = (0xFF & tmp[12])<<8 | (0xFF & tmp[13]);
		tmp[34+tp] = (byte)(0xFF & difference>>>8);
		tmp[35+tp] = (byte)(0xFF & difference);

		newTitle(" / " + Resource.getString("subpicture.in_time") + ": " + sms.format(new java.util.Date(in_time / 90)) + " " + Resource.getString("subpicture.duration") + ": " + sms.format(new java.util.Date((out_time - in_time) / 90)) );

		return tmp;
	}

	/*** build Image from text **/
	//DM30122003 081.6 int10 changed
	//DM05052004 081.7 int02 changed
	public void buildImgTTX()
	{
		int space = 6;
		Rect[0] = option[3];
		//Rect[3] = (2 * space) + (option[0] * str.length);
		Rect[3] = (2 * space) + (line_offset * str.length);
		Rect[1] = option[6] - option[2] - Rect[3];
		Rect[2] = option[4];

		pos[0] = Rect[0];
		pos[1] = Rect[1];
		pos[2] = Rect[0] + Rect[2] - 1;
		pos[3] = Rect[1] + Rect[3] - 1;

		//DM08032004 081.6 int18 add
		paintVideoSize();

		big.setColor(Color.white);
		big.drawRect(Rect[0] - 1, Rect[1] - 1, Rect[2] + 1, Rect[3] + 1);
		big.setFont(font_std);
		big.drawString("x" + pos[0] + ", y" + pos[1] + " / " + (pos[2] - pos[0] + 1) + "*" + (pos[3] - pos[1] + 1), Rect[0] - 1, Rect[1] - 5);

		int color_table[] = getColorTable(1);

		big.setFont(font);

		ArrayList list = new ArrayList();
		boolean antialiasing;

		/**
		 * pre-check, whether we have not more than 2 'speaker-colors'
		 */
		for (int a = 0; a < str.length; a++)
		{
			int[] chars = (int[])str[a];

			for (int b = 0; b < chars.length; b++)
			{
				//source background color
				int offset = (7 & chars[b]>>>4)<<3;

				//source modified foreground color
				int paint_color = color_table[offset + (7 & chars[b])];
				String str = Integer.toString(paint_color);
				String sign = new Character((char)(chars[b]>>>8)).toString();

				//remember new color
				if (list.indexOf(str) < 0 && !sign.equals(" "))
					list.add(str);
			}
		}

		/**
		 * define background; if less than 3 front-colors, use 'simple' antialiasing with full transparency
		 */
		if (list.size() < 3 && X.cBox[79].isSelected())
		{
			big.setColor(new Color(color_table[65])); // deep blue, full transp
			modified_alpha = 0;
			antialiasing = true;
		}
		else
		{
			big.setColor(new Color(color_table[64])); // black, half transp
			modified_alpha = default_alpha;
			antialiasing = false;
		}

		big.fillRect(Rect[0], Rect[1], Rect[2], Rect[3]); // background

		Rectangle2D r;

		// paint background of char
		for (int a = 0; antialiasing && a < str.length; a++)
		{
			int[] chars = (int[])str[a];
			String str = "";

			big.setColor(new Color(color_table[64])); // black

			/**
			 * concatenate string, no special colors required
			 */
			for (int i = 0; i < chars.length; i++)
				str += new Character((char)(chars[i]>>>8)).toString();

			x = option[3];
			//int y = Rect[1] + (option[0] * (1 + a));
			int y = Rect[1] + (line_offset * (1 + a));
			int[] offs = { 2, 3, 3, 3, 3, 3, 2 };

			for (int i = 0; i < offs.length; i++) // horiz. lines
			{
				int _x = x;
				int _y = y - (offs.length / 2) + i;

				for (int j = -offs[i]; j < offs[i] + 1; j++)
					big.drawString(str, _x + j, _y);
			}
		}


		// paint ascii char
		for (int a=0; a < str.length; a++)
		{
			int[] chars = (int[])str[a];
			x = option[3];

			//DM26052004 081.7 int03 changed
			for (int b=0; b < chars.length; b++)
			{
				//source background color
				int offset = (7 & chars[b]>>>4)<<3;

				//source foreground color
				big.setColor(new Color(color_table[offset + (7 & chars[b])]));
				//big.drawString("" + (char)(chars[b]>>>8), x, Rect[1] + (option[0] * (1 + a)));
				big.drawString("" + (char)(chars[b]>>>8), x, Rect[1] + (line_offset * (1 + a)));

				x += font.getStringBounds("" + (char)(chars[b]>>>8), frc).getWidth();
			}
		}
	}

	public void resetUserColorTable()
	{
		user_color_table.clear();
	}

	public Object[] getUserColorTableArray()
	{
		return user_color_table.toArray();
	}

	public ArrayList getUserColorTable()
	{
		return user_color_table;
	}

	public void updateUserColorTable(Bitmap new_bitmap)
	{
		bitmap = new_bitmap;

		int pixel[] = bitmap.getPixel();

		for (int a=0; a < pixel.length; a++)
		{
			String pixel_str = "" + pixel[a];

			if (!user_color_table.contains(pixel_str))
				user_color_table.add(pixel_str);

			bitmap.getColorIndex(getUserColorTableIndex(pixel[a]));
		}
	}

	private void updateUserColorTable(int pixel[])
	{
		for (int a=0; a < pixel.length; a++)
		{
			String pixel_str = "" + pixel[a];

			if (user_color_table.contains(pixel_str))
				continue;

			else
				user_color_table.add(pixel_str);
		}
	}

	private int getUserColorTableIndex(int color_index)
	{
		int value;

		if ((value = user_color_table.indexOf("" + color_index)) < 0)
			return 0;

		return value;
	}

	//DM26052004 081.7 int03 changed
	public byte[] writeRLE(long start_time, int onscreen_time) throws IOException
	{
		read_from_Image = true; // use user defined alpha value for color index 0

		bitmap = new Bitmap( Rect[0], Rect[1], Rect[2], Rect[3], bimg.getRGB(Rect[0], Rect[1], Rect[2], Rect[3], null, 0, Rect[2]), 2, 0, 1, 2, start_time, onscreen_time);

		return buildRLE();
	}

	public byte[] writeRLE(Bitmap new_bitmap) throws IOException
	{
		bitmap = new_bitmap;
		setArea();

		return buildRLE();
	}

	private byte[] buildRLE()
	{
		byte picture_packet[] = null;

		try 
		{

		int pixels[] = bitmap.getPixel();

		updateUserColorTable(pixels);

		out.reset(); 
		out.write(RLEheader);   //start picture in .sup form

		int bottom_field_start_pos = 0;

		// read out interlaced RGB
		for (int i=0, l=0, a=0, b=0, color_index=0; i < 2; i++)
		{
			// top_field first
			for (l=0, color_index=0, a = i * bitmap.getWidth(); a < pixels.length; a += (2 * bitmap.getWidth()))
			{
				for (l=0, color_index=0, b=0; b < bitmap.getWidth(); b++, l++)
				{
					if (pixels[a + b] != color_index)
					{
						// write last RLE nibbles, while color change
						updateRLE(l, color_index);
						color_index = pixels[a + b];
						l=0;
					}
					else if ( l > 254 )
					{
						// write last RLE nibbles, cannot incl. more than 255 pixels
						updateRLE(l, color_index);
						l=0;
					}
					// std: adds l-bit to active color
				}

				l -= 1;

				while ( l > 255 )  // never used ?!
				{ 
					updateRLE(255, color_index); 
					l -= 255; 
				}

				updateRLE(l, color_index);   // write last RLE nibbles, line end
				alignRLE();
				out.write(newline);  // new line CR, byte aligned
			}

			alignRLE();

			if (bottom_field_start_pos == 0) 
				bottom_field_start_pos = out.size() - 10;        // save startpos of bottom_field (size-14)
		}

		out.write(newline);  //DM26052004 081.7 int03 add , not the best solution, but need the "0,0" here

		int pack = out.size() - 12;
		int control_block_pos = pack + 24;
		int onscreen_time_pos = out.size() + 22;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -