docs: private void writeSub(String fname) throws CoreException {
  		BufferedOutputStream out = null;
  		List<Integer> offsets = null;
  		List<Integer> timestamps = null;
  		SortedMap<Integer, SubPicture> exportedSubPictures = new TreeMap<Integer, SubPicture>();
  		int frameNum = 0;
  		String fn = "";
  
  		List<Integer> subPicturesToBeExported = getSubPicturesToBeExported();
  
  		if (subPicturesToBeExported.isEmpty()) {
  			return;
  		}
  
  		OutputMode outputMode = configuration.getOutputMode();
  		try {
  			// handle file name extensions depending on mode
  			if (outputMode == OutputMode.VOBSUB) {
  				fname = FilenameUtils.removeExtension(fname) + ".sub";
  				out = new BufferedOutputStream(new FileOutputStream(fname));
  				offsets = new ArrayList<Integer>();
  				timestamps = new ArrayList<Integer>();
  			} else if (outputMode == OutputMode.SUPIFO) {
  				fname = FilenameUtils.removeExtension(fname) + ".sup";
  				out = new BufferedOutputStream(new FileOutputStream(fname));
  			} else if (outputMode == OutputMode.BDSUP) {
  				fname = FilenameUtils.removeExtension(fname) + ".sup";
  				out = new BufferedOutputStream(new FileOutputStream(fname));
  			} else {
  				fn = FilenameUtils.removeExtension(fname);
  				fname = fn + ".xml";
  			}
  
  			// main loop
  			int offset = 0;
  			for (int i : subPicturesToBeExported) {
  				SubPicture subPicture = subPictures[i];
  				if (outputMode == OutputMode.VOBSUB) {
  					offsets.add(offset);
  					convertSup(i, frameNum / 2 + 1,
  							subPicturesToBeExported.size());
  					subVobTrg.copyInfo(subPicture);
  					byte buf[] = SubDvdWriter.createSubFrame(subVobTrg,
  							trgBitmap);
  					out.write(buf);
  					offset += buf.length;
  					timestamps.add((int) subPicture.getStartTime());
  				} else if (outputMode == OutputMode.SUPIFO) {
  					convertSup(i, frameNum / 2 + 1,
  							subPicturesToBeExported.size());
  					subVobTrg.copyInfo(subPicture);
  					byte buf[] = SupDvdWriter.createSupFrame(subVobTrg,
  							trgBitmap);
  					out.write(buf);
  				} else if (outputMode == OutputMode.BDSUP) {
  					subPicture.setCompositionNumber(frameNum);
  					convertSup(i, frameNum / 2 + 1,
  							subPicturesToBeExported.size());
  					byte buf[] = SupBDWriter.createSupFrame(subPicture,
  							trgBitmap, trgPal);
  					out.write(buf);
  				} else {
  					// Xml
  					convertSup(i, frameNum / 2 + 1,
  							subPicturesToBeExported.size());
  					String fnp = SupXml.getPNGname(fn, i + 1);
  					// File file = new File(fnp);
  					// ImageIO.write(trgBitmap.getImage(trgPal), "png", file);
  					out = new BufferedOutputStream(new FileOutputStream(fnp));
  					EnhancedPngEncoder pngEncoder = new EnhancedPngEncoder(
  							trgBitmap.getImage(trgPal.getColorModel()));
  					byte buf[] = pngEncoder.pngEncode();
  					out.write(buf);
  					out.close();
  					exportedSubPictures.put(i, subPicture);
  				}
  				frameNum += 2;
  			}
  		} catch (IOException ex) {
  			throw new CoreException(ex.getMessage());
  		} finally {
  			try {
  				if (out != null) {
  					out.close();
  				}
  			} catch (IOException ex) {
  			}
  		}
  
  		Palette trgPallete = null;
  		if (outputMode == OutputMode.VOBSUB) {
  			// VobSub - write IDX
  			/* return offsets as array of ints */
  			int[] ofs = new int[offsets.size()];
  			for (int i = 0; i < ofs.length; i++) {
  				ofs[i] = offsets.get(i);
  			}
  			int[] ts = new int[timestamps.size()];
  			for (int i = 0; i < ts.length; i++) {
  				ts[i] = timestamps.get(i);
  			}
  			fname = FilenameUtils.removeExtension(fname) + ".idx";
  			trgPallete = currentDVDPalette;
  			SubDvdWriter.writeIdx(fname, subPictures[0], ofs, ts, trgPallete);
  		} else if (outputMode == OutputMode.XML) {
  			// XML - write XML
  			SupXml.writeXml(fname, exportedSubPictures);
  		}
  	}