コード例 #1
0
ファイル: SupBD.java プロジェクト: bepcyc/BDSup2Sub
  /**
   * 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());
    }
  }
コード例 #2
0
ファイル: SupBD.java プロジェクト: bepcyc/BDSup2Sub
  /**
   * Decode caption from the input stream.
   *
   * @param subPictureBD SubPicture object containing info about the caption
   * @param transparentColorIndex index of the transparent color
   * @return bitmap of the decoded caption
   * @throws CoreException
   */
  private Bitmap decodeImage(SubPictureBD subPictureBD, int transparentColorIndex)
      throws CoreException {
    int width = subPictureBD.getImageWidth();
    int height = subPictureBD.getImageHeight();
    // always decode image obj 0, start with first entry in fragment list
    ImageObjectFragment imageObjectFragment =
        subPictureBD.getImageObject().getFragmentList().get(0);
    long startOfs = imageObjectFragment.getImageBufferOfs();

    if (width > subPictureBD.getWidth() || height > subPictureBD.getHeight()) {
      throw new CoreException(
          "Subpicture too large: "
              + width
              + "x"
              + height
              + " at offset "
              + ToolBox.toHexLeftZeroPadded(startOfs, 8));
    }

    Bitmap bm = new Bitmap(width, height, (byte) transparentColorIndex);

    int b;
    int index = 0;
    int ofs = 0;
    int size;
    int xpos = 0;

    try {
      // just for multi-packet support, copy all of the image data in one common buffer
      byte[] buffer = new byte[subPictureBD.getImageObject().getBufferSize()];
      index = 0;

      for (ImageObjectFragment fragment : subPictureBD.getImageObject().getFragmentList()) {
        // copy data of all packet to one common buffer
        imageObjectFragment = fragment;
        for (int i = 0; i < imageObjectFragment.getImagePacketSize(); i++) {
          buffer[index + i] =
              (byte) this.buffer.getByte(imageObjectFragment.getImageBufferOfs() + i);
        }
        index += imageObjectFragment.getImagePacketSize();
      }

      index = 0;

      do {
        b = buffer[index++] & 0xff;
        if (b == 0) {
          b = buffer[index++] & 0xff;
          if (b == 0) {
            // next line
            ofs = (ofs / width) * width;
            if (xpos < width) {
              ofs += width;
            }
            xpos = 0;
          } else {
            if ((b & 0xC0) == 0x40) {
              // 00 4x xx -> xxx zeroes
              size = ((b - 0x40) << 8) + (buffer[index++] & 0xff);
              for (int i = 0; i < size; i++) {
                bm.getInternalBuffer()[ofs++] = 0; /*(byte)b;*/
              }
              xpos += size;
            } else if ((b & 0xC0) == 0x80) {
              // 00 8x yy -> x times value y
              size = (b - 0x80);
              b = buffer[index++] & 0xff;
              for (int i = 0; i < size; i++) {
                bm.getInternalBuffer()[ofs++] = (byte) b;
              }
              xpos += size;
            } else if ((b & 0xC0) != 0) {
              // 00 cx yy zz -> xyy times value z
              size = ((b - 0xC0) << 8) + (buffer[index++] & 0xff);
              b = buffer[index++] & 0xff;
              for (int i = 0; i < size; i++) {
                bm.getInternalBuffer()[ofs++] = (byte) b;
              }
              xpos += size;
            } else {
              // 00 xx -> xx times 0
              for (int i = 0; i < b; i++) {
                bm.getInternalBuffer()[ofs++] = 0;
              }
              xpos += b;
            }
          }
        } else {
          bm.getInternalBuffer()[ofs++] = (byte) b;
          xpos++;
        }
      } while (index < buffer.length);

      return bm;
    } catch (FileBufferException ex) {
      throw new CoreException(ex.getMessage());
    } catch (ArrayIndexOutOfBoundsException ex) {
      logger.warn(
          "Problems during RLE decoding of picture OBJ at offset "
              + ToolBox.toHexLeftZeroPadded(startOfs + index, 8)
              + "\n");
      return bm;
    }
  }
コード例 #3
0
ファイル: SupXml.java プロジェクト: akjujoki/BDSup2Sub
  /* (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!");
    }
  }