2013-10-24 2 views
0

TIFF에서 PNG 형식으로 이미지를 변환 할 때 실제로 최종 이미지가 가능한 가장 작게되도록 비트 심도를 1 (검정색 & 흰색)로 설정하고 서명 이미지를 사용하고 있습니다. 내 문제는 원본 이미지가 "너무 희색"이며 전환 과정에서 이미지가 무시되므로 일부 픽셀이 "손실"된다는 것입니다.비트 심도 = 1 (흑백)으로 TIFF-PNG 변환에서 어느 픽셀이 검정색 (임계 값)이되는지 제어하는 ​​방법이 있습니까?

내가 원하는 것은 이미지에 threshold을 적용하도록 PNG 인코더에 지시하는 방법입니다. 예를 들어, 회색 레벨이 240보다 크고 검정색이 아닌 경우 흰색입니다. 이미지가 서명이기 때문에 이미지를 픽셀의 많은 부분을 잃지 않는 다른 방법으로 브라우저에 표시해야합니다.

sample signature

이 내가 PNG 형식으로 TIFF에서 이미지를 변환하는 데 사용하는 코드는 다음과 같습니다 : 다음은 샘플입니다

public byte[]tiffToPng(byte[]tiffBytes) throws IOException { 

    SeekableStream stream = new ByteArraySeekableStream(tiffBytes); 
    ImageDecoder decoder = ImageCodec.createImageDecoder("tiff", stream, null); 
    RenderedImage renderedImage = decoder.decodeAsRenderedImage(0); 

    PNGEncodeParam pngEncodeParam = PNGEncodeParam.getDefaultEncodeParam(renderedImage); 
    pngEncodeParam.setBitDepth(1); 

    ByteArrayOutputStream pngBytesStream = new ByteArrayOutputStream(); 
    ImageEncoder encoder = ImageCodec.createImageEncoder("png", pngBytesStream, pngEncodeParam); 
    encoder.encode(renderedImage); 
    pngBytesStream.flush(); 
    return pngBytesStream.toByteArray(); 
} 

답변

1

음, 잠시 후, 먼저 conversion of the RenderedImage to a BufferedImage을 작성한 다음 RGB 값에 대한 루프를 수행하고 thresholding이 수행됩니다. 마지막으로 결과 이미지를 PNG (비트 심도 = 1)로 인코딩했습니다.

public byte[]tiffToPng(byte[]tiffBytes) throws IOException { 
    SeekableStream stream = new ByteArraySeekableStream(tiffBytes); 
    ImageDecoder decoder = ImageCodec.createImageDecoder("tiff", stream, null); 
    RenderedImage tiffRenderedImage = decoder.decodeAsRenderedImage(0); 

    BufferedImage tiffBufferedImage = toBufferedImage(tiffRenderedImage); 
    for (int y = 0; y < tiffBufferedImage.getHeight(); y++) { 
     for (int x = 0; x < tiffBufferedImage.getWidth(); x++) { 
      int rgb = tiffBufferedImage.getRGB(x, y); 
      int a = (rgb>>24)&0xFF; 
      int r = (rgb>>16)&0xFF; 
      int g = (rgb>>8)&0xFF; 
      int b = (rgb>>0)&0xFF; 
      if(a == 0xFF && r == g && g == b) { 
       if(r < 254) { 
        tiffBufferedImage.setRGB(x, y, 0xFF000000); 
       } else { 
        tiffBufferedImage.setRGB(x, y, 0xFFFFFFFF); 
       } 
      } 
     } 
    } 

    PNGEncodeParam pngEncodeParam = PNGEncodeParam.getDefaultEncodeParam(tiffBufferedImage); 
    pngEncodeParam.setBitDepth(1); 
    ByteArrayOutputStream pngBytesStream = new ByteArrayOutputStream(); 
    ImageEncoder encoder = ImageCodec.createImageEncoder("png", pngBytesStream, pngEncodeParam); 
    encoder.encode(tiffBufferedImage); 
    pngBytesStream.flush(); 
    return pngBytesStream.toByteArray(); 
} 

public BufferedImage toBufferedImage(RenderedImage img) { 
     if (img instanceof BufferedImage) { 
      return (BufferedImage) img; 
     } 
     ColorModel cm = img.getColorModel(); 
     int width = img.getWidth(); 
     int height = img.getHeight(); 
     WritableRaster raster = cm.createCompatibleWritableRaster(width, height); 
     boolean isAlphaPremultiplied = cm.isAlphaPremultiplied(); 
     Hashtable properties = new Hashtable(); 
     String[] keys = img.getPropertyNames(); 
     if (keys != null) { 
      for (int i = 0; i < keys.length; i++) { 
       properties.put(keys[i], img.getProperty(keys[i])); 
      } 
     } 
     BufferedImage result = new BufferedImage(cm, raster, isAlphaPremultiplied, properties); 
     img.copyData(raster); 
     return result; 
    } 

그리고 이것은 최종 이미지입니다 : 이것은이다

signature succesfully converted PNG 1 bit depth

0

당신이 원하는 것은 더 많은 이미지 전처리 일을, 내가 인코더가이를 허용하지 않을 것입니다. 이미지 (밝기/대비 및/또는 감마)를 사전 처리하고 저장하십시오.

+0

감사합니다! 내가 어떻게 할 수 있니? 그냥 어떤 방향으로 나를 가리켜 ... – lmiguelmh