Skip to content

Commit

Permalink
Merge pull request #3911 from melissalinkert/dicom-dual-personality
Browse files Browse the repository at this point in the history
DICOM writer: initial support for dual personality DICOM/TIFF
  • Loading branch information
dgault authored Jul 31, 2023
2 parents 6c25c68 + 013b211 commit c31c9ef
Show file tree
Hide file tree
Showing 8 changed files with 433 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -638,12 +638,18 @@ public boolean testConvert(IFormatWriter writer, String[] args)
((TiffWriter) writer).setBigTiff(bigtiff);
((TiffWriter) writer).setCanDetectBigTiff(!nobigtiff);
}
else if (writer instanceof DicomWriter) {
((DicomWriter) writer).setBigTiff(bigtiff);
}
else if (writer instanceof ImageWriter) {
IFormatWriter w = ((ImageWriter) writer).getWriter(out);
if (w instanceof TiffWriter) {
((TiffWriter) w).setBigTiff(bigtiff);
((TiffWriter) w).setCanDetectBigTiff(!nobigtiff);
}
else if (w instanceof DicomWriter) {
((DicomWriter) w).setBigTiff(bigtiff);
}
}

String format = writer.getFormat();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,7 @@ public enum DicomAttribute {
ITEM(0xFFFEE000),
ITEM_DELIMITATION_ITEM(0xFFFEE00D),
SEQUENCE_DELIMITATION_ITEM(0xFFFEE0DD),
TRAILING_PADDING(0xFFFCFFFC),

// directory structuring elements
FILE_SET_ID(0x00041130),
Expand Down
24 changes: 19 additions & 5 deletions components/formats-bsd/src/loci/formats/dicom/DicomTag.java
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,11 @@ else if (vr == IMPLICIT) {
vr = DicomAttribute.getDefaultVR(tag);
}

if (!readValue) {
if (!readValue || attribute == PIXEL_DATA) {
long skip = elementLength & 0xffffffffL;
if (skip > 0 && skip <= in.length() - in.getFilePointer()) {
in.skipBytes(skip);
}
return;
}

Expand Down Expand Up @@ -352,10 +356,20 @@ private int getNextTag(RandomAccessInputStream in) throws FormatException, IOExc
return tag;
}

if (elementLength < 0 && groupWord == 0x7fe0) {
in.skipBytes(12);
elementLength = in.readInt();
if (elementLength < 0) elementLength = in.readInt();
// indicates that we have found pixel data
if (groupWord == 0x7fe0) {
// the length may legitimately be between 2 and 4 GB
long length = elementLength & 0xffffffffL;

// length of 0xffffffff means undefined length, which is uncommon but allowed
if (elementLength == -1 || (length > 0 && length < in.length())) {
return tag;
}
else {
in.skipBytes(12);
elementLength = in.readInt();
if (elementLength < 0) elementLength = in.readInt();
}
}

if (elementLength == 0 && (groupWord == 0x7fe0 || tag == 0x291014)) {
Expand Down
24 changes: 20 additions & 4 deletions components/formats-bsd/src/loci/formats/in/DicomReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,9 @@ else if (child.attribute == OPTICAL_PATH_DESCRIPTION) {
case EXTENDED_DEPTH_OF_FIELD:
edf = tag.getStringValue().equalsIgnoreCase("yes");
break;
case TRAILING_PADDING:
decodingTags = false;
break;
default:
in.seek(tag.getEndPointer());
}
Expand Down Expand Up @@ -707,6 +710,9 @@ else if (child.attribute == OPTICAL_PATH_DESCRIPTION) {
if (m.sizeZ == 0) {
m.sizeZ = 1;
}
if (m.imageCount == 0) {
m.imageCount = 1;
}
if (opticalChannels == 0 || (concatenationNumber == null && ((imagesPerFile / m.sizeZ) % opticalChannels != 0))) {
opticalChannels = 1;
}
Expand Down Expand Up @@ -1494,8 +1500,8 @@ private void getTile(DicomTile tile, byte[] buf, int x, int y, int w, int h)
LOGGER.error("attempted to read beyond end of file ({}, {})", tile.fileOffset, tile.file);
return;
}
stream.seek(tile.fileOffset);
LOGGER.debug("reading from offset = {}, file = {}", tile.fileOffset, tile.file);
stream.seek(tile.fileOffset);

if (tile.isRLE) {
// plane is compressed using run-length encoding
Expand Down Expand Up @@ -1601,7 +1607,14 @@ else if (pt < b.length - 2) {
options.interleaved = isInterleaved();
if (tile.isJPEG) codec = new JPEGCodec();
else codec = new JPEG2000Codec();
b = codec.decompress(b, options);

try {
b = codec.decompress(b, options);
}
catch (NullPointerException e) {
LOGGER.debug("Could not read empty or invalid tile", e);
return;
}

int rowLen = w * bpp;
int srcRowLen = tile.region.width * bpp;
Expand Down Expand Up @@ -1709,7 +1722,10 @@ private void calculatePixelsOffsets(long baseOffset) throws FormatException, IOE
in.seek(in.getFilePointer() - 1);
}
}
in.skipBytes(i == 0 ? 64 : 53);
if (in.readInt() == 0xe000fffe) {
in.skipBytes(12);
}
in.skipBytes(i == 0 ? 60 : 49);
while (in.read() == 0);
offset = in.getFilePointer() - 1;
}
Expand Down Expand Up @@ -1757,7 +1773,7 @@ else if (buf[q] == (byte) 0xff && buf[q + 1] == (byte) 0xd9) {
}
}
}
else offset = baseOffset + plane*i;
else offset = baseOffset + (long) plane*i;

tilePositions.get(getCoreIndex()).get(i).fileOffset = offset;
tilePositions.get(getCoreIndex()).get(i).last = i == imagesPerFile - 1;
Expand Down
Loading

0 comments on commit c31c9ef

Please sign in to comment.