/** * Create VobSub IDX file * * @param fname file name * @param pic a SubPicture object used to read screen width and height * @param offsets array of offsets (one for each caption) * @param timestamps array of PTS time stamps (one for each caption) * @param palette 16 color main Palette * @throws bdsup2sub.core.CoreException */ public static void writeIdx( String fname, SubPicture pic, int[] offsets, int[] timestamps, Palette palette) throws CoreException { BufferedWriter out = null; try { out = new BufferedWriter(new FileWriter(fname)); out.write("# VobSub index file, v7 (do not modify this line!)"); out.newLine(); out.write("# Created by " + Constants.APP_NAME + " " + Constants.APP_VERSION); out.newLine(); out.newLine(); out.write("# Frame size"); out.newLine(); out.write( "size: " + pic.getWidth() + "x" + (pic.getHeight() - 2 * configuration.getCropOffsetY())); out.newLine(); out.newLine(); out.write("# Origin - upper-left corner"); out.newLine(); out.write("org: 0, 0"); out.newLine(); out.newLine(); out.write("# Scaling"); out.newLine(); out.write("scale: 100%, 100%"); out.newLine(); out.newLine(); out.write("# Alpha blending"); out.newLine(); out.write("alpha: 100%"); out.newLine(); out.newLine(); out.write("# Smoothing"); out.newLine(); out.write("smooth: OFF"); out.newLine(); out.newLine(); out.write("# Fade in/out in milliseconds"); out.newLine(); out.write("fadein/out: 0, 0"); out.newLine(); out.newLine(); out.write("# Force subtitle placement relative to (org.x, org.y)"); out.newLine(); out.write("align: OFF at LEFT TOP"); out.newLine(); out.newLine(); out.write("# For correcting non-progressive desync. (in millisecs or hh:mm:ss:ms)"); out.newLine(); out.write("time offset: 0"); out.newLine(); out.newLine(); out.write("# ON: displays only forced subtitles, OFF: shows everything"); out.newLine(); out.write("forced subs: OFF"); out.newLine(); out.newLine(); out.write("# The palette of the generated file"); out.newLine(); out.write("palette: "); // Palette pal = Core.getCurrentDVDPalette(); for (int i = 0; i < palette.getSize(); i++) { int rbg[] = palette.getRGB(i); int val = (rbg[0] << 16) | (rbg[1] << 8) | rbg[2]; out.write(ToolBox.toHexLeftZeroPadded(val, 6).substring(2)); if (i != palette.getSize() - 1) { out.write(", "); } } out.newLine(); out.newLine(); out.write("# Custom colors (transp idxs and the four colors)"); out.newLine(); out.write("custom colors: OFF, tridx: 1000, colors: 000000, 444444, 888888, cccccc"); out.newLine(); out.newLine(); out.write("# Language index in use"); out.newLine(); out.write("langidx: 0"); out.newLine(); out.newLine(); out.write("# " + LANGUAGES[configuration.getLanguageIdx()][0]); out.newLine(); out.write("id: " + LANGUAGES[configuration.getLanguageIdx()][1] + ", index: 0"); out.newLine(); out.write( "# Decomment next line to activate alternative name in DirectVobSub / Windows Media Player 6.x"); out.newLine(); out.write("# alt: " + LANGUAGES[configuration.getLanguageIdx()][0]); out.newLine(); out.write("# Vob/Cell ID: 1, 1 (PTS: 0)"); out.newLine(); for (int i = 0; i < timestamps.length; i++) { out.write("timestamp: " + ptsToTimeStrIdx(timestamps[i])); out.write(", filepos: " + ToolBox.toHexLeftZeroPadded(offsets[i], 9).substring(2)); out.newLine(); } } catch (IOException ex) { throw new CoreException(ex.getMessage()); } finally { try { if (out != null) { out.close(); } } catch (IOException ex) { } } }
/** * Create Xml file * * @param fname file name * @param pics Map of SubPictures and their original indexes which were used to generate the png * file names * @throws CoreException */ public static void writeXml(String fname, SortedMap<Integer, SubPicture> pics) throws CoreException { double fps = configuration.getFpsTrg(); double fpsXml = XmlFps(fps); BufferedWriter out = null; String name = FilenameUtils.removeExtension(FilenameUtils.getName(fname)); try { out = new BufferedWriter(new FileWriter(fname)); out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); out.newLine(); out.write( "<BDN Version=\"0.93\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"BD-03-006-0093b BDN File Format.xsd\">"); out.newLine(); out.write(" <Description>"); out.newLine(); out.write(" <Name Title=\"" + name + "\" Content=\"\"/>"); out.newLine(); out.write(" <Language Code=\"" + LANGUAGES[configuration.getLanguageIdx()][2] + "\"/>"); out.newLine(); String res = configuration.getOutputResolution().getResolutionNameForXml(); out.write( " <Format VideoFormat=\"" + res + "\" FrameRate=\"" + ToolBox.formatDouble(fps) + "\" DropFrame=\"False\"/>"); out.newLine(); long t = pics.get(pics.firstKey()).getStartTime(); if (fps != fpsXml) { t = (t * 2000 + 1001) / 2002; } String ts = ptsToTimeStrXml(t, fpsXml); t = pics.get(pics.lastKey()).getEndTime(); if (fps != fpsXml) { t = (t * 2000 + 1001) / 2002; } String te = ptsToTimeStrXml(t, fpsXml); out.write( " <Events Type=\"Graphic\" FirstEventInTC=\"" + ts + "\" LastEventOutTC=\"" + te + "\" NumberofEvents=\"" + pics.size() + "\"/>"); out.newLine(); out.write(" </Description>"); out.newLine(); out.write(" <Events>"); out.newLine(); for (int idx : pics.keySet()) { SubPicture p = pics.get(idx); t = p.getStartTime(); if (fps != fpsXml) { t = (t * 2000 + 1001) / 2002; } ts = ptsToTimeStrXml(t, fpsXml); t = p.getEndTime(); if (fps != fpsXml) { t = (t * 2000 + 1001) / 2002; } te = ptsToTimeStrXml(t, fpsXml); String forced = p.isForced() ? "True" : "False"; out.write(" <Event InTC=\"" + ts + "\" OutTC=\"" + te + "\" Forced=\"" + forced + "\">"); out.newLine(); String pname = getPNGname(name, idx + 1); out.write( " <Graphic Width=\"" + p.getImageWidth() + "\" Height=\"" + p.getImageHeight() + "\" X=\"" + p.getXOffset() + "\" Y=\"" + p.getYOffset() + "\">" + pname + "</Graphic>"); out.newLine(); out.write(" </Event>"); out.newLine(); } out.write(" </Events>"); out.newLine(); out.write("</BDN>"); out.newLine(); } catch (IOException ex) { throw new CoreException(ex.getMessage()); } finally { try { if (out != null) { out.close(); } } catch (IOException ex) { } } }