2012-07-28 2 views
1

저는 Java 응용 프로그램을 개발하고 있습니다.이 응용 프로그램은 dvi 프레임 그래버에서 비디오를 캡처합니다. 실시간으로이 프레임 그래버에서 가져온 프레임을 렌더링하고 싶습니다. 그러나 저는 생산성 문제에 직면했습니다. 렌더링 속도가 매우 느 렸고 컴퓨터가 초당 5-6 프레임 만 렌더링 할 수있었습니다. 이 장치는 초당 최대 40 프레임을 캡처 할 수 있었지만 내 코드를 프로파일 링하고 drawImage 메소드가 상대적으로 느리다는 것을 알아 냈습니다. BMP 이미지로 drawImage 메서드를 호출하면 drawImage를 사용하여 그리는 데 20 밀리 초가 걸린 것보다 ImageIO.readImage를 통해로드됩니다. 이미지로, 나는 프레임 그래버에서 얻었습니다. 그 (것)들을 그리는 데는 100 밀리 초가 걸립니다. I 프레임 그래버 라이브러리의 부호를 조사하고, 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); 

화소 즉, 프레임 그래버에 의해 제공되는 바이트의 어레이이다. drawImage 메서드를보다 빠르게 호출 할 수 있도록, BufferedImage를 다르게 생성 할 수있는 방법이 있습니까? ColorSpaces에 대해 알고, 정확한 색상 공간을 유지할 필요가 없습니다. 속도는 훨씬 더 중요합니다. 사전

답변

1

에서

덕분에 나는 (이 도움이 또는하지 않을 경우 나도 몰라) 비슷한 소리 ImageIO에서 API에 대한 재이의 티파니 구현에 문제가 있었다.

기본적으로, 그것은 "단일 픽셀 포장 샘플 모델"로 색상 모델을 변환합니다 : 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)를 호출합니다.

내가의 렌더링 시간이 걸렸습니다 a (상대적으로 큰 TIFF 이미지)를 몇 분에서 몇 분 미만으로 낮추십시오. conds : P

추신 - 난 내가 비슷한 문제를 가지고 원래의 코드 http://www.koders.com/java/fidFE1D69AFE6930A514D5E189310AB10A3DFD43F78.aspx

+0

를 발견 한 곳이 생각합니다. bufferedImage는 페인트하는 것이 정말 느 렸습니다. 이것으로 해결했습니다. –