2012-07-28 51 views
1

我正在开发一个Java应用程序,它捕捉来自dvi图像采集卡的视频。 我想渲染帧,这是我实时从这个图像采集卡获取的帧。但是我面对生产力方面的问题 - 渲染速度非常慢,我的电脑每秒只能渲染5-6帧。虽然该设备能够捕获高达每秒40帧。我分析了我的代码,发现drawImage方法相对较慢。如果我使用BMP图像调用drawImage方法,则通过ImageIO.readImage加载,而不是花费20 ms来使用drawImage绘制它。有了这些图像,我从图像采集卡中获得了图像,它需要超过100毫秒的时间。我学的帧抓取器库的代码,并且发现的BufferedImage以如下方式创建 -如何提高由Java语言中的ComponentColorModel创建的BufferedImage的绘图性能?

ColorModel cm; 
    if (format == PixelFormat.RGB24) { 
     cm = new ComponentColorModel(
      ColorSpace.getInstance(ColorSpace.CS_sRGB), new int[] {8,8,8}, 
      false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE); 
    } else { 
     throw new UnsupportedOperationException(); 
    } 
    SampleModel sm = cm.createCompatibleSampleModel(width, height); 
    DataBuffer db = new DataBufferByte(pixels, length); 
    WritableRaster raster = Raster.createWritableRaster(sm, db, null); 
    return new BufferedImage(cm, raster, false, null); 

像素是一个字节数组,由帧抓取器提供。 有没有什么办法可以创建BufferedImage不同,以更快地调用drawImage方法。我知道ColorSpaces,我不需要保留正确的颜色空间。速度更重要。

在此先感谢

回答

1

我曾与JAI的为ImageIO的API,它听起来类似的TIFF执行的问题(我不知道这是否会帮助或没有)。

基本上,它将色彩模式转换为“单个像素包装样品模型”:P

这不是我的代码,我拿不出它的信用,我前一段时间发现它在网络上和我怕我不记得在那里(我也尝试搜索,但没有找到合适的参考。

/******************************************************************************* 
* 
* It seems that SinglePixelPackedSampleModel is the only fast mode when a 
* color profile is converted. This is probably a bug (that has nothing to do 
* with bugs 4886071 and 4705399). 
* Note that grayscale images (TYPE_GRAY) are not converted. 
* 
******************************************************************************/ 
public static BufferedImage convertToSinglePixelPackedSampleModel(BufferedImage image) { 

    long time = System.currentTimeMillis(); 

    WritableRaster sourceRaster = image.getRaster(); 
    ColorModel colorModel = image.getColorModel(); 
    ICC_ColorSpace colorSpace = (ICC_ColorSpace) colorModel.getColorSpace(); 
    final SampleModel ssmd = sourceRaster.getSampleModel(); 

    if (colorSpace.getType() == ColorSpace.TYPE_GRAY) { 

     logger.info(">>>> TYPE_GRAY, not converting"); 

    } else if (!(ssmd instanceof PixelInterleavedSampleModel)) { 

     logger.info(">>>> sourceSampleModel is " + ssmd.getClass() + ", not converting"); 

    } else { 

     PixelInterleavedSampleModel sourceSampleModel = (PixelInterleavedSampleModel) ssmd; 
     int[] bitMasks = new int[]{0x00ff0000, 0x0000ff00, 0x000000ff}; 

     SinglePixelPackedSampleModel sampleModel = new SinglePixelPackedSampleModel(DataBuffer.TYPE_INT, image.getWidth(), 
       image.getHeight(), bitMasks); 

     WritableRaster destRaster = Raster.createWritableRaster(sampleModel, null); 
     DataBufferInt destDataBuffer = (DataBufferInt) destRaster.getDataBuffer(); 
     int[] destBuffer = destDataBuffer.getData(); 
     int[] bandOffsets = sourceSampleModel.getBandOffsets(); 

     for (int i = 0; i < bandOffsets.length; i++) { 
      bandOffsets[i] += ((-sourceRaster.getSampleModelTranslateX() * sourceSampleModel.getPixelStride()) 
        - (sourceRaster.getSampleModelTranslateY() * sourceSampleModel.getScanlineStride())); 
     } 

     DataBuffer sourceDataBuffer = sourceRaster.getDataBuffer(); 

     if (sourceDataBuffer instanceof DataBufferUShort) { 

      convertUShortDataBuffer(image, (DataBufferUShort) sourceDataBuffer, sourceSampleModel, bandOffsets, destBuffer); 

     } else if (sourceDataBuffer instanceof DataBufferByte) { 

      convertByteDataBuffer(image, (DataBufferByte) sourceDataBuffer, sourceSampleModel, bandOffsets, destBuffer); 

     } else { 

      throw new IllegalArgumentException("Cannot deal with " + sourceDataBuffer.getClass()); 

     } 

     String sourceProfileName = getICCProfileName(colorSpace.getProfile()); 

     if (sourceProfileName.equals("Nikon sRGB 4.0.0.3001")) { 
      logger.warn(">>>> Workaround #1094403: using sRGB instead of " + sourceProfileName); 
      colorSpace = new ICC_ColorSpace(ICC_Profile.getInstance(ColorSpace.CS_LINEAR_RGB)); 
     } 

     colorModel = new DirectColorModel(colorSpace, 24, bitMasks[0], bitMasks[1], bitMasks[2], 0, false, DataBuffer.TYPE_INT); 
     image = new BufferedImage(colorModel, destRaster, false, null); 
    } 

    time = System.currentTimeMillis() - time; 
    logger.info(">>>> convertToSinglePixelPackedSampleModel() completed ok in " + time + " msec"); 

    return image; 
} 

/** 
* @param image 
* @param sourceDataBuffer 
* @param sourceSampleModel 
* @param bandOffsets 
* @param destBuffer 
*/ 
protected static void convertByteDataBuffer(BufferedImage image, DataBufferByte sourceDataBuffer, 
     PixelInterleavedSampleModel sourceSampleModel, int[] bandOffsets, int[] destBuffer) { 
    int base = 0; 
    int i = 0; 
    byte[] sourceBuffer = sourceDataBuffer.getData(); 
    int pixelStride = sourceSampleModel.getPixelStride(); 

    for (int y = 0; y < image.getHeight(); y++) { 
     int j = base; 

     for (int x = 0; x < image.getWidth(); x++) { 
      int r = (sourceBuffer[j + bandOffsets[0]] & 0xff); 
      int g = (sourceBuffer[j + bandOffsets[1]] & 0xff); 
      int b = (sourceBuffer[j + bandOffsets[2]] & 0xff); 

      destBuffer[i++] = (r << 16) | (g << 8) | b; 
      j += pixelStride; 
     } 

     base += sourceSampleModel.getScanlineStride(); 
    } 
} 

protected static void convertUShortDataBuffer(BufferedImage image, DataBufferUShort sourceDataBuffer, 
     PixelInterleavedSampleModel sourceSampleModel, int[] bandOffsets, int[] destBuffer) { 
    int base = 0; 
    int i = 0; 
    short[] sourceBuffer = sourceDataBuffer.getData(); 

    for (int y = 0; y < image.getHeight(); y++) { 
     int j = base; 

     for (int x = 0; x < image.getWidth(); x++) { 
      int r = (sourceBuffer[j + bandOffsets[0]] & 0xffff) >> 8; 
      int g = (sourceBuffer[j + bandOffsets[1]] & 0xffff) >> 8; 
      int b = (sourceBuffer[j + bandOffsets[2]] & 0xffff) >> 8; 

      destBuffer[i++] = (r << 16) | (g << 8) | b; 
      j += 3; 
     } 

     base += sourceSampleModel.getScanlineStride(); 
    } 
} 

// public static ICC_Profile getICCProfile(RenderedImage image) { 
// 
//  ColorSpace colorSpace = image.getColorModel().getColorSpace(); 
// 
//  if (colorSpace instanceof ICC_ColorSpace) { 
// 
//   ICC_ColorSpace iccColorSpace = (ICC_ColorSpace) colorSpace; 
// 
//   return iccColorSpace.getProfile(); 
// 
//  } 
// 
//  return null; 
// 
// } 

public static String getICCProfileName(ICC_Profile profile) { 

    if (profile == null) { 
     return null; 
    } 

    byte[] xx = profile.getData(ICC_Profile.icSigProfileDescriptionTag); 
    int offset = 12; 
    int count; 

    for (count = 1; xx[offset + count] != 0; count++) { 
     ; 
    } 

    return new String(xx, 0, offset, count); 

} 

基本上,只要拨打.convertToSinglePixelPackedSampleModel(image)

我把绘制时间一个(相对较大的TIFF图像)从几分钟降到少于几秒conds:P

ps的 - 我想这,我发现原来的代码http://www.koders.com/java/fidFE1D69AFE6930A514D5E189310AB10A3DFD43F78.aspx

+0

我有一个类似的问题。缓冲图像绘制起来非常慢。这解决了它。 – 2014-01-13 11:21:51