2017-03-20 14 views
0

お客様が提供するJPG画像をsRGB形式(sRGB IEC61966-2.1)に変換してWeb対応にする必要があります。sRGB IEC61966-2.1ラスタ画像用カラーモデル

私はImageIOBufferedImageで正常にそれを行うことができますが、この操作は本当に遅いです:

val srgbSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB) 
val colorConversionOperation = new ColorConvertOp(srgbSpace, null) 
val converted = colorConversionOperation.filter(inputImage, null) 

は(すでにColorConvertOpRenderingHintsを提供しようとした - それは役立ちません)

を私の知る限り理解して、犯人はBufferedImageであり、私はRasterに取り組む必要があります。

val iccProfile = ICC_Profile.getInstance(ColorSpace.CS_sRGB) 
val iccColorSpace = new ICC_ColorSpace(iccProfile) 
val sourceColorSpace = inputImage.getColorModel.getColorSpace 

val colorConversionOperation = new ColorConvertOp(sourceColorSpace, iccColorSpace, null) 
val converted = colorConversionOperation.filter(inputImage.getRaster, null) 

これは確かに大きなパフォーマンス向上をもたらしますが、Rasterの保存方法はわかりませんので、最終イメージに適切なカラースペースとカラープロファイルの情報が含まれています。

は現在、私は次のように Rasterから BufferedImageを作成します。この場合は正しいです

Color space: RGB 
Color profile: sRGB IEC61966-2.1 

val outImage = new BufferedImage(ColorModel.getRGBdefault, converted, false, null); 

私はBufferedImageで動作

は、最終的JPGはとして保存されます。私は Color profile情報を失ったことを意味し

Color space: RGB 

私はRaster秒で動作

は、最終JPGは、同じように保存されます。 RasterBufferedImageに変換すると、私は ColorModel.getRGBdefaultを実行しますが、sRGB IEC61966-2.1の場合、 ColorModelのインスタンスを取得する方法はわかりません。

+1

'ColorModel.getRGBdefault'は常にsRGBの色空間にあります(APIドキュメントに記載されています)。しかし、私は同意します、出力JPEGが異なっているのは奇妙です...事は(画像を書くために 'ImageIO'とその' JPEGImageWriter'を使っていると仮定して)、ICCカラープロファイルはデフォルトでは書き込まれません。色空間はsRGBです。なんらかの理由で、 'converted'イメージの色空間はsRGBと同じですが、' isCS_sRGB() 'メソッドは' false'を返します(理由は分かりません)。 ICCプロファイルをメタデータ( 'IIOMetadata'クラス)に渡すことで、強制的にICCプロファイルを記述できると思います。 – haraldK

+0

@haraldK IIOMedatadaにICCプロファイルを渡す例がありますか? IIOMetadata/JPEGMetadataを見ていて、ICCプロファイルを渡す方法がわかりません。私はここに何か助けとなることができれば、私のクラスパス上に12個のImageIOを持っています。 –

答えて

1

ここで画像は、sRGB色空間であっても、画像ISN」場合(これは自動的に行われ、出力JPEGファイル内のICCプロファイルセグメント出力にどのように「力」JPEGImageWriterをに示す「短い」サンプルコードですあなたがテストから見たように、sRGB色空間でのt)。

public class ICCTest { 
    public static void main(String[] args) throws IOException { 
     // Fist let's assume this isn't already in sRGB (it is...) 
     BufferedImage inputImage = new BufferedImage(10, 10, BufferedImage.TYPE_3BYTE_BGR); 

     // Conversion similar to yours 
     ColorSpace sRGB = ColorSpace.getInstance(ColorSpace.CS_sRGB); 
     WritableRaster raster = new ColorConvertOp(inputImage.getColorModel().getColorSpace(), sRGB, null) 
      .filter(inputImage.getRaster(), null); 

     ComponentColorModel cm = new ComponentColorModel(sRGB, false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE); 
     BufferedImage converted = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null); 

     // Just for comparison  
     ImageIO.write(converted, "JPEG", new File("converted.jpg")); 

     // Write image with forced ICC profile 
     ImageWriter writer = ImageIO.getImageWritersByFormatName("JPEG").next(); 
     try (ImageOutputStream out = ImageIO.createImageOutputStream(new File("converted_icc.jpg"))) { 
      writer.setOutput(out); 

      ImageWriteParam param = writer.getDefaultWriteParam(); 
      IIOMetadata metadata = writer.getDefaultImageMetadata(ImageTypeSpecifier.createFromRenderedImage(converted2), param); 
      metadata.mergeTree("javax_imageio_jpeg_image_1.0", createICCTree((ICC_ColorSpace) sRGB)); 

      writer.write(null, new IIOImage(converted, null, metadata), param); 
     } 
     writer.dispose(); 
    } 

    // Create a minimal IIOMetadata tree, containing an ICC profile 
    private static IIOMetadataNode createICCTree(ColorSpace cs) { 
     IIOMetadataNode root = new IIOMetadataNode("javax_imageio_jpeg_image_1.0"); 

     IIOMetadataNode jpegVariety = new IIOMetadataNode("JPEGvariety"); 
     root.appendChild(jpegVariety); 
     root.appendChild(new IIOMetadataNode("markerSequence")); // Must be present, even if empty... 

     IIOMetadataNode app0JFIF = new IIOMetadataNode("app0JFIF"); 
     jpegVariety.appendChild(app0JFIF); 

     IIOMetadataNode icc = new IIOMetadataNode("app2ICC"); 
     app0JFIF.appendChild(icc); 

     icc.setUserObject(cs.getProfile()); 

     return root; 
    } 
} 

詳細については、JPEG metadata formatを参照してください。

PS:現代のWebブラウザでは、ほとんどの場合、sRGBであるかのように、プロファイルなしのJPEGを扱うと思います(JFIF仕様では間違っていますが)。したがって、色空間の変換を行う限り、実際にICCプロファイルを出力する必要はありません。

+0

ありがとう。私はJavaでの画像操作に慣れていないし、 'Color Profile'がメタデータに正しく追加された瞬間には、あなたの助けなしに1ヶ月かかるだろう。乾杯! –

関連する問題