001/* ***** BEGIN LICENSE BLOCK ***** 002 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 003 * 004 * The contents of this file are subject to the Mozilla Public License Version 005 * 1.1 (the "License"); you may not use this file except in compliance with 006 * the License. You may obtain a copy of the License at 007 * http://www.mozilla.org/MPL/ 008 * 009 * Software distributed under the License is distributed on an "AS IS" basis, 010 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 011 * for the specific language governing rights and limitations under the 012 * License. 013 * 014 * The Original Code is part of dcm4che, an implementation of DICOM(TM) in 015 * Java(TM), hosted at https://github.com/gunterze/dcm4che. 016 * 017 * The Initial Developer of the Original Code is 018 * Agfa Healthcare. 019 * Portions created by the Initial Developer are Copyright (C) 2013 020 * the Initial Developer. All Rights Reserved. 021 * 022 * Contributor(s): 023 * See @authors listed below 024 * 025 * Alternatively, the contents of this file may be used under the terms of 026 * either the GNU General Public License Version 2 or later (the "GPL"), or 027 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 028 * in which case the provisions of the GPL or the LGPL are applicable instead 029 * of those above. If you wish to allow use of your version of this file only 030 * under the terms of either the GPL or the LGPL, and not to allow others to 031 * use your version of this file under the terms of the MPL, indicate your 032 * decision by deleting the provisions above and replace them with the notice 033 * and other provisions required by the GPL or the LGPL. If you do not delete 034 * the provisions above, a recipient may use your version of this file under 035 * the terms of any one of the MPL, the GPL or the LGPL. 036 * 037 * ***** END LICENSE BLOCK ***** */ 038 039package org.dcm4che3.imageio.codec.jpeg; 040 041/** 042 * The JAI-ImageIO JPEG-LS CLibJPEGImageReader/CLibJPEGImageWriter contain a bug that makes them calculate non-default 043 * JPEG-LS coding parameters for images with more than 12 bits per pixel, resulting in two problems: 044 * <ol> 045 * <li>JPEG-LS streams created by CLibJPEGImageWriter are not compliant with the JPEG-LS specification and can 046 * therefore not be decoded using standard-compliant decoders. (Note: Some commercial decoders can automatically detect 047 * such faulty JPEG-LS streams and are able to decode them correctly, e.g. Agfa/Pegasus.)</li> 048 * <li>Reading a correct JPEG-LS stream using default coding parameters (i.e. not containing an LSE segment) with 049 * CLibJPEGImageReader will result in a corrupted image.</li> 050 * </ol> 051 * <p> 052 * This enum contains different options to use with a {@link PatchJPEGLSImageInputStream} or {@link 053 * PatchJPEGLSImageOutputStream} to both patch faulty JPEG-LS streams created by JAI-ImageIO to make them readable 054 * by standard-compliant decoders and to make correct JPEG-LS streams (created by other encoders) readable by 055 * JAI-ImageIO. 056 * 057 * @see <a href="http://www.dcm4che.org/jira/browse/DCMEE-1144">http://www.dcm4che.org/jira/browse/DCMEE-1144</a> 058 * @see <a href="http://dcm4che.org/jira/browse/DCMEEREQ-799">http://dcm4che.org/jira/browse/DCMEEREQ-799</a> 059 * @see <a href="https://java.net/jira/browse/JAI_IMAGEIO_CORE-183">https://java.net/jira/browse/JAI_IMAGEIO_CORE-183</a> 060 * @see <a href="http://charls.codeplex.com/discussions/230307">http://charls.codeplex.com/discussions/230307</a> 061 * 062 * @author Gunter Zeilinger <gunterze@gmail.com> 063 * @author Hermann Czedik-Eysenberg <hermann-agfa@czedik.net> 064 */ 065public enum PatchJPEGLS { 066 067 /** 068 * Amend JPEG-LS Coding parameters actually used by JAI-ImageIO. 069 * <p> 070 * Used to patch faulty JPEG-LS streams created by JAI-ImageIO CLibImageWriter, so the resulting JPEG-LS 071 * stream can be decoded by JPEG-LS compliant decoders. 072 * <p> 073 * Warning: Patching a correct JPEG-LS (not created by JAI-ImageIO) with this option is likely to corrupt it (if it 074 * has more than 12 bits per pixel and uses default coding parameters, i.e. doesn't contain an LSE segment). Use 075 * JAI2ISO_IF_NO_APP_OR_COM to prevent this problem in some cases. 076 */ 077 JAI2ISO, 078 079 /** 080 * Amend JPEG-LS Coding parameters actually used by JAI-ImageIO, but only if the stream does NOT contain APPn or 081 * COM segments and is therefore more likely to have been actually created by JAI-ImageIO. 082 * <p> 083 * This option can be used, if you are not 100% sure whether the stream has actually been created by JAI-ImageIO 084 * and you want to decrease the likeliness of corrupting a correct stream by incorrectly patching it. 085 * It will prevent patching streams of some correct encoders (e.g. Agfa/Pegasus) that add APPn or COM 086 * segments. But as some correct encoders (e.g. dcmtk in the current version 3.6.0) also do not create APPn or COM 087 * segments, this option might still patch a correct stream and thereby make it corrupt. 088 */ 089 JAI2ISO_IF_NO_APP_OR_COM, 090 091 /** 092 * Amend default JPEG-LS Coding parameters (for streams that do not contain them yet). 093 * <p> 094 * Used to patch correct JPEG-LS streams, so they can be decompressed by the faulty JAI-ImageIO 095 * CLibImageReader. The resulting stream will still be correct JPEG-LS and can also be decoded by other decoders. 096 * <p> 097 * Warning: Patching faulty JPEG-LS streams created by JAI-ImageIO with this option will make them corrupt (i.e. 098 * unreadable by both JAI-ImageIO and standard-compliant decoders). 099 */ 100 ISO2JAI, 101 102 /** 103 * Amend default JPEG-LS Coding parameters (for streams that do not contain them yet), but only if the stream 104 * contains APPn or COM segments - so it was certainly not created by JAI-ImageIO. 105 * <p> 106 * This option can be used to prevent adding those default parameters to faulty streams created by JAI-ImageIO 107 * which would make them unreadable for both JAI-ImageIO and standard-compliant decoders. 108 * On the other hand some correct encoders (e.g. dcmtk 3.6.0) also do not add APPn or COM segments and will 109 * therefore not be patched, which prevents them from getting decompressed correctly with JAI-ImageIO, if this 110 * option is used. (Use the ISO2JAI option for reading such streams with JAI-ImageIO.) 111 */ 112 ISO2JAI_IF_APP_OR_COM; 113 114 public JPEGLSCodingParam createJPEGLSCodingParam(byte[] jpeg) { 115 JPEGHeader jpegHeader = new JPEGHeader(jpeg, JPEG.SOS); 116 int soiOff = jpegHeader.offsetOf(JPEG.SOI); 117 int sof55Off = jpegHeader.offsetOf(JPEG.SOF55); 118 int lseOff = jpegHeader.offsetOf(JPEG.LSE); 119 int sosOff = jpegHeader.offsetOf(JPEG.SOS); 120 121 if (soiOff == -1) 122 return null; // no JPEG 123 124 if (sof55Off == -1) 125 return null; // no JPEG-LS 126 127 if (lseOff != -1) 128 return null; // already patched 129 130 if (sosOff == -1) 131 return null; 132 133 // additional markers (APPn or COM) besides SOI, SOF55 and SOS 134 boolean additionalMarkers = jpegHeader.numberOfMarkers() > 3; 135 136 if (this == ISO2JAI_IF_APP_OR_COM && !additionalMarkers) 137 return null; 138 139 if (this == JAI2ISO_IF_NO_APP_OR_COM && additionalMarkers) 140 return null; 141 142 int p = jpeg[sof55Off+3] & 255; 143 if (p <= 12) 144 return null; // not more than 12 bits per pixel 145 146 JPEGLSCodingParam param = this == JAI2ISO 147 ? JPEGLSCodingParam.getJAIJPEGLSCodingParam(p) 148 : JPEGLSCodingParam.getDefaultJPEGLSCodingParam(p, 149 jpeg[sosOff+6] & 255); 150 param.setOffset(sosOff-1); 151 return param; 152 } 153}