Beispiel #1
0
 /**
  * decode given picture
  *
  * @param pic SubPicture object containing info about caption
  * @throws CoreException
  */
 private void decode(SubPictureBD pic) throws CoreException {
   palette = decodePalette(pic);
   bitmap = decodeImage(pic, palette.getIndexOfMostTransparentPaletteEntry());
   primaryColorIndex =
       bitmap.getPrimaryColorIndex(
           palette.getAlpha(), configuration.getAlphaThreshold(), palette.getY());
 }
Beispiel #2
0
  /**
   * decode palette from the input stream
   *
   * @param pic SubPicture object containing info about the current caption
   * @return
   * @throws CoreException
   */
  private Palette decodePalette(SubPictureBD pic) throws CoreException {
    boolean fadeOut = false;
    int paletteIndex;
    List<PaletteInfo> paletteInfos = pic.getPalettes().get(pic.getImageObject().getPaletteID());
    if (paletteInfos == null) {
      throw new CoreException("Palette ID out of bounds.");
    }

    Palette palette = new Palette(256, Core.usesBT601());
    // by definition, index 0xff is always completely transparent
    // also all entries must be fully transparent after initialization

    try {
      for (PaletteInfo paletteInfo : paletteInfos) {
        int index = paletteInfo.getPaletteOffset();
        for (int i = 0; i < paletteInfo.getPaletteSize(); i++) {
          // each palette entry consists of 5 bytes
          paletteIndex = buffer.getByte(index);
          int y = buffer.getByte(++index);
          int cr, cb;
          if (configuration.isSwapCrCb()) {
            cb = buffer.getByte(++index);
            cr = buffer.getByte(++index);
          } else {
            cr = buffer.getByte(++index);
            cb = buffer.getByte(++index);
          }
          int alpha = buffer.getByte(++index);

          int alphaOld = palette.getAlpha(paletteIndex);
          // avoid fading out
          if (alpha >= alphaOld) {
            if (alpha
                < configuration
                    .getAlphaCrop()) { // to not mess with scaling algorithms, make transparent
                                       // color black
              y = 16;
              cr = 128;
              cb = 128;
            }
            palette.setAlpha(paletteIndex, alpha);
          } else {
            fadeOut = true;
          }

          palette.setYCbCr(paletteIndex, y, cb, cr);
          index++;
        }
      }
      if (fadeOut) {
        logger.warn("fade out detected -> patched palette\n");
      }
      return palette;
    } catch (FileBufferException ex) {
      throw new CoreException(ex.getMessage());
    }
  }
Beispiel #3
0
  public Palette(Palette palette) {
    size = palette.getSize();
    useBT601 = palette.usesBT601();
    r = new byte[size];
    g = new byte[size];
    b = new byte[size];
    a = new byte[size];
    y = new byte[size];
    cb = new byte[size];
    cr = new byte[size];

    for (int i = 0; i < size; i++) {
      a[i] = palette.a[i];
      r[i] = palette.r[i];
      g[i] = palette.g[i];
      b[i] = palette.b[i];
      y[i] = palette.y[i];
      cb[i] = palette.cb[i];
      cr[i] = palette.cr[i];
    }
  }
Beispiel #4
0
  /**
   * 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) {
      }
    }
  }
Beispiel #5
0
 /* (non-Javadoc)
  * @see SubtitleStream#getImage(Bitmap)
  */
 public BufferedImage getImage(Bitmap bm) {
   return bm.getImage(palette.getColorModel());
 }
Beispiel #6
0
 /* (non-Javadoc)
  * @see SubtitleStream#getImage()
  */
 public BufferedImage getImage() {
   return bitmap.getImage(palette.getColorModel());
 }
Beispiel #7
0
  /* (non-Javadoc)
   * @see deadbeef.SupTools.SubtitleStream#decode(int)
   */
  @Override
  public void decode(int index) throws CoreException {
    try {
      File f = new File(subPictures.get(index).getFileName());
      if (!f.exists()) {
        throw new CoreException("file " + subPictures.get(index).getFileName() + " not found.");
      }
      BufferedImage img = ImageIO.read(f);
      int w = img.getWidth();
      int h = img.getHeight();

      this.palette = null;

      // first try to read image and palette directly from imported image
      if (img.getType() == BufferedImage.TYPE_BYTE_INDEXED) {
        IndexColorModel icm = (IndexColorModel) img.getColorModel();
        if (icm.getMapSize() < 255 || (icm.hasAlpha() && icm.getAlpha(255) == 0)) {
          // create palette
          palette = new Palette(256);
          for (int i = 0; i < icm.getMapSize(); i++) {
            int alpha = (icm.getRGB(i) >> 24) & 0xff;
            if (alpha >= configuration.getAlphaCrop()) {
              palette.setARGB(i, icm.getRGB(i));
            } else {
              palette.setARGB(i, 0);
            }
          }
          // copy pixels
          WritableRaster raster = img.getRaster();
          bitmap =
              new Bitmap(
                  img.getWidth(),
                  img.getHeight(),
                  (byte[]) raster.getDataElements(0, 0, img.getWidth(), img.getHeight(), null));
        }
      }

      // if this failed, assume RGB image and quantize palette
      if (palette == null) {
        // grab int array (ARGB)
        int[] pixels = new int[w * h];
        img.getRGB(0, 0, w, h, pixels, 0, w);
        // quantize image
        QuantizeFilter qf = new QuantizeFilter();
        bitmap = new Bitmap(img.getWidth(), img.getHeight());
        int ct[] = qf.quantize(pixels, bitmap.getInternalBuffer(), w, h, 255, false, false);
        int size = ct.length;
        if (size > 255) {
          logger.warn("Quantizer failed.\n");
          size = 255;
        }
        // create palette
        palette = new Palette(256);
        for (int i = 0; i < size; i++) {
          int alpha = (ct[i] >> 24) & 0xff;
          if (alpha >= configuration.getAlphaCrop()) {
            palette.setARGB(i, ct[i]);
          } else {
            palette.setARGB(i, 0);
          }
        }
      }
      primaryColorIndex =
          bitmap.getPrimaryColorIndex(
              palette.getAlpha(), configuration.getAlphaThreshold(), palette.getY());
      // crop
      BitmapBounds bounds =
          bitmap.getCroppingBounds(palette.getAlpha(), configuration.getAlphaCrop());
      if (bounds.yMin > 0
          || bounds.xMin > 0
          || bounds.xMax < bitmap.getWidth() - 1
          || bounds.yMax < bitmap.getHeight() - 1) {
        w = bounds.xMax - bounds.xMin + 1;
        h = bounds.yMax - bounds.yMin + 1;
        if (w < 2) {
          w = 2;
        }
        if (h < 2) {
          h = 2;
        }
        bitmap = bitmap.crop(bounds.xMin, bounds.yMin, w, h);
        // update picture
        SubPictureXml pic = subPictures.get(index);
        pic.setImageWidth(w);
        pic.setImageHeight(h);
        pic.setOfsX(pic.getOriginalXOffset() + bounds.xMin);
        pic.setOfsY(pic.getOriginalYOffset() + bounds.yMin);
      }
    } catch (IOException e) {
      throw new CoreException(e.getMessage());
    } catch (OutOfMemoryError e) {
      JOptionPane.showMessageDialog(
          null,
          "Out of heap! Use -Xmx256m to increase heap!",
          "Error!",
          JOptionPane.WARNING_MESSAGE);
      throw new CoreException("Out of heap! Use -Xmx256m to increase heap!");
    }
  }