|
From: <gun...@us...> - 2008-06-05 11:09:46
|
Revision: 6381
http://dcm4che.svn.sourceforge.net/dcm4che/?rev=6381&view=rev
Author: gunterze
Date: 2008-06-05 04:09:27 -0700 (Thu, 05 Jun 2008)
Log Message:
-----------
[#DCMEE-847] Pool BufferedImage objects for compression/decompression
Modified Paths:
--------------
dcm4chee/dcm4chee-arc/trunk/dcm4jboss-sar/src/etc/conf/xmdesc/dcm4chee-compression-xmbean.xml
dcm4chee/dcm4chee-arc/trunk/dcm4jboss-sar/src/java/org/dcm4chex/archive/codec/CodecCmd.java
dcm4chee/dcm4chee-arc/trunk/dcm4jboss-sar/src/java/org/dcm4chex/archive/codec/CompressCmd.java
dcm4chee/dcm4chee-arc/trunk/dcm4jboss-sar/src/java/org/dcm4chex/archive/codec/DecompressCmd.java
dcm4chee/dcm4chee-arc/trunk/dcm4jboss-sar/src/java/org/dcm4chex/archive/mbean/CompressionService.java
Added Paths:
-----------
dcm4chee/dcm4chee-arc/trunk/dcm4jboss-sar/src/java/org/dcm4chex/archive/codec/BufferedImagePool.java
Modified: dcm4chee/dcm4chee-arc/trunk/dcm4jboss-sar/src/etc/conf/xmdesc/dcm4chee-compression-xmbean.xml
===================================================================
--- dcm4chee/dcm4chee-arc/trunk/dcm4jboss-sar/src/etc/conf/xmdesc/dcm4chee-compression-xmbean.xml 2008-06-04 14:57:04 UTC (rev 6380)
+++ dcm4chee/dcm4chee-arc/trunk/dcm4jboss-sar/src/etc/conf/xmdesc/dcm4chee-compression-xmbean.xml 2008-06-05 11:09:27 UTC (rev 6381)
@@ -2,13 +2,17 @@
<!DOCTYPE mbean PUBLIC "-//JBoss//DTD JBOSS XMBEAN 1.1//EN" "http://www.jboss.org/j2ee/dtd/jboss_xmbean_1_1.dtd">
<mbean>
- <description><![CDATA[Compression Service. The Compression Service supports delayed, lossless compression
-of received images. This is an alternative to immediately compressing images when received. (The lossless compression rules are configured by the
-<b>CompressionRules</b> attribute
-in the StorageSCP service.) The value of the <b>MaxConcurrentCodec</b> attribute in the Compression Service also effects the on-the-fly
-compression and decompression during the receive and retrieve of images by the
-StorageSCP and QueryRetrieveSCP services. (For details, see the MaxConcurrentCodec attribute below.)]]></description>
-
+ <description><![CDATA[
+Compression Service. The Compression Service supports delayed, lossless
+compression of received images. This is an alternative to immediately
+compressing images when received. (The lossless compression rules are
+configured by the <b>CompressionRules</b> attribute in the StorageSCP
+service.) The value of the attributes <b>MaxConcurrentCodec</b>,
+<b>MaxBufferedImagePoolSize</b> and <b>MaxBufferedImagePoolMemoryattribute</b>
+of the Compression Service also effects the on-the-fly compression and
+decompression during the receive and retrieve of images by the StorageSCP and
+QueryRetrieveSCP services. (For details, see the these attributes below.)
+]]></description>
<descriptors>
<persistence persistPolicy="OnUpdate"/>
<persistence-manager value="org.jboss.mx.persistence.DelegatingPersistenceManager"/>
@@ -22,25 +26,86 @@
</constructor>
<!-- Attributes -->
- <attribute access="read-write" getMethod="getMaxConcurrentCodec" setMethod="setMaxConcurrentCodec">
- <description><![CDATA[Maximum number of concurrent tasks for compressing and decompressing images.
- When the default value is of MaxConcurrentCodec is 1, all
-compression and decompression operations are serialized. For example, if
-on-the-fly compression during an image receive is activated, and three modalities
-concurrently send uncompressed images to the archive, only one image
-received from one modality is compressed at the same time. This significantly reduces the receiving performance. The
-used codec allocates memory for uncompressed pixel data of at least
-one frame, so without limiting the maximum number of concurrent
+ <attribute access="read-write" getMethod="getMaxConcurrentCodec"
+ setMethod="setMaxConcurrentCodec">
+ <description><![CDATA[
+Maximum number of concurrent tasks for compressing and decompressing images.
+With the default value of <b>MaxConcurrentCodec</b> = 1, all compression and
+decompression operations are serialized. For example, if on-the-fly compression
+during an image receive is activated, and three modalities concurrently send
+uncompressed images to the archive, only one image received from one modality
+is compressed at the same time. This significantly reduces the receiving
+performance. The used codec allocates memory for uncompressed pixel data of at
+least one frame, so without limiting the maximum number of concurrent
compression tasks, memory consumption could become unacceptable.
-You will receive an out of memory error if the memory consumption exceeds the configured -Xmx value in
-the <i>archive-install-directory</i>/bin/run.conf file).]]></description>
- <name>MaxConcurrentCodec</name>
- <type>int</type>
- <descriptors>
- <value value="1"/>
- </descriptors>
+You will receive an out of memory error if the memory consumption exceeds the
+configured -Xmx value in the $DCM4CHEE_HOME/bin/run.conf file).
+]]></description>
+ <name>MaxConcurrentCodec</name>
+ <type>int</type>
+ <descriptors>
+ <value value="1" />
+ </descriptors>
</attribute>
-
+
+ <attribute access="read-write"
+ getMethod="getMaxBufferedImagePoolSize"
+ setMethod="setMaxBufferedImagePoolSize">
+ <description><![CDATA[
+Maximum number of pooled BufferedImage objects. If
+<b>MaxBufferedImagePoolSize</b> > 0, BufferedImage objects allocated for
+compression and decompression operations are pooled so they can be reused by
+subsequent compression and decompression operations with matching pixel matrix
+dimensions. The pool size is additional limited by
+<b>MaxBufferedImagePoolMemory</b>, the maximum amount of memory allocated by
+pooled BufferedImage objects.
+]]></description>
+ <name>MaxBufferedImagePoolSize</name>
+ <type>int</type>
+ <descriptors>
+ <value value="10" />
+ </descriptors>
+ </attribute>
+
+ <attribute access="read-only"
+ getMethod="getCurrentBufferedImagePoolSize">
+ <description>
+ Current number of pooled BufferedImage objects.
+ </description>
+ <name>CurrentBufferedImagePoolSize</name>
+ <type>int</type>
+ </attribute>
+
+
+ <attribute access="read-write"
+ getMethod="getMaxBufferedImagePoolMemory"
+ setMethod="setMaxBufferedImagePoolMemory">
+ <description><![CDATA[
+Maximum amount of memory allocated by pooled BufferedImage objects.
+1MB = 1000000 bytes. If <b>MaxBufferedImagePoolSize</b> > 0, BufferedImage
+objects allocated for compression and decompression operations are pooled so
+they can be reused by subsequent compression and decompression operations with
+matching pixel matrix dimensions. The pool size is additional limited by
+<b>MaxBufferedImagePoolSize</b>, the maximum number of pooled BufferedImage
+objects.
+]]></description>
+ <name>MaxBufferedImagePoolMemory</name>
+ <type>java.lang.String</type>
+ <descriptors>
+ <value value="1MB" />
+ </descriptors>
+ </attribute>
+
+ <attribute access="read-only"
+ getMethod="getCurrentBufferedImagePoolMemory">
+ <description>
+ Current amount of memory allocated by pooled BufferedImage
+ objects. 1MB = 1000000 bytes.
+ </description>
+ <name>CurrentBufferedImagePoolMemory</name>
+ <type>java.lang.String</type>
+ </attribute>
+
<attribute access="read-write" getMethod="getTaskInterval" setMethod="setTaskInterval">
<description><![CDATA[Interval in which the database is checked for images to compress.
<br>Format:
@@ -96,7 +161,7 @@
<attribute access="read-write" getMethod="getTempDir" setMethod="setTempDir">
<description><![CDATA[Directory used to spool decompressed files for
compression verification. Relative path names are resolved relative to
- <i>archive-install-directory</i>/server/default/.]]>
+ $DCM4CHEE_HOME/server/default/.]]>
</description>
<name>TempDirectory</name>
<type>java.lang.String</type>
@@ -130,7 +195,7 @@
<attribute access="read-write"
getMethod="getFileSystemMgtName"
setMethod="setFileSystemMgtName">
- <description>Used internally. Do not modify.
+ <description>Used internally. Do NOT modify.
</description>
<name>FileSystemMgtName</name>
<type>javax.management.ObjectName</type>
Added: dcm4chee/dcm4chee-arc/trunk/dcm4jboss-sar/src/java/org/dcm4chex/archive/codec/BufferedImagePool.java
===================================================================
--- dcm4chee/dcm4chee-arc/trunk/dcm4jboss-sar/src/java/org/dcm4chex/archive/codec/BufferedImagePool.java (rev 0)
+++ dcm4chee/dcm4chee-arc/trunk/dcm4jboss-sar/src/java/org/dcm4chex/archive/codec/BufferedImagePool.java 2008-06-05 11:09:27 UTC (rev 6381)
@@ -0,0 +1,192 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is part of dcm4che, an implementation of DICOM(TM) in
+ * Java(TM), available at http://sourceforge.net/projects/dcm4che.
+ *
+ * The Initial Developer of the Original Code is
+ * Agfa HealthCare.
+ * Portions created by the Initial Developer are Copyright (C) 2006-2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * See listed authors below.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+package org.dcm4chex.archive.codec;
+
+import java.awt.color.ColorSpace;
+import java.awt.image.BandedSampleModel;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.ComponentColorModel;
+import java.awt.image.DataBuffer;
+import java.awt.image.PixelInterleavedSampleModel;
+import java.awt.image.Raster;
+import java.awt.image.SampleModel;
+import java.awt.image.WritableRaster;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.dcm4chex.archive.util.FileUtils;
+
+/**
+ * @author Gunter Zeilinger <gun...@gm...>
+ * @version $Revision$ $Date$
+ * @since Jun 3, 2008
+ */
+class BufferedImagePool {
+
+ static final Logger log = Logger.getLogger(BufferedImagePool.class);
+
+ private static final int[] GRAY_BAND_OFFSETS = { 0 };
+ private static final int[] RGB_BAND_OFFSETS = { 0, 1, 2 };
+
+ private List<BufferedImage> pool = new ArrayList<BufferedImage>();
+ private int maxSize = 10;
+ private long maxMemory = FileUtils.MEGA;
+ private long poolMemory = 0;
+
+ public synchronized BufferedImage borrowOrCreateBufferedImage(int rows,
+ int columns, int bitsUsed, int samples, int planarConfiguration,
+ int dataType) {
+ for (int index = pool.size(); --index >= 0;) {
+ BufferedImage bi = pool.get(index);
+ ColorModel cm = bi.getColorModel();
+ WritableRaster raster = bi.getRaster();
+ DataBuffer db = raster.getDataBuffer();
+ if (raster.getHeight() == rows
+ && raster.getWidth() == columns
+ && raster.getNumBands() == samples
+ && cm.getComponentSize(0) == bitsUsed
+ && db.getNumBanks() == (planarConfiguration != 0 ? samples
+ : 1) && db.getDataType() == dataType) {
+ pool.remove(index);
+ poolMemory -= sizeOf(bi);
+ log("borrow", bi);
+ return bi;
+ }
+ }
+ WritableRaster r = Raster.createWritableRaster(getSampleModel(
+ rows, columns, samples, planarConfiguration, dataType), null);
+ BufferedImage bi = new BufferedImage(
+ getColorModel(bitsUsed, samples, dataType), r, false, null);
+ log("create", bi);
+ return bi;
+ }
+
+ private static void log(String msg, BufferedImage bi) {
+ if (log.isDebugEnabled()) {
+ ColorModel cm = bi.getColorModel();
+ WritableRaster raster = bi.getRaster();
+ log.debug(msg + " BufferedImage@"
+ + Integer.toHexString(bi.hashCode())
+ + " " + raster.getWidth() + "x" + raster.getHeight()
+ + "x" + raster.getNumBands() + " "
+ + DataBuffer.getDataTypeSize(raster.getTransferType())
+ + "(" + cm.getComponentSize(0) + ") bits");
+ }
+ }
+
+ private static SampleModel getSampleModel(int rows, int columns,
+ int samples, int planarConfiguration, int dataType) {
+ return (planarConfiguration == 0) ? new PixelInterleavedSampleModel(
+ dataType, columns, rows, samples, columns * samples,
+ samples == 1 ? GRAY_BAND_OFFSETS : RGB_BAND_OFFSETS)
+ : new BandedSampleModel(dataType, columns, rows, samples);
+ }
+
+ private static ColorModel getColorModel(int bitsUsed, int samples,
+ int dataType) {
+ return (samples == 3) ? new ComponentColorModel(ColorSpace
+ .getInstance(ColorSpace.CS_sRGB), new int[] { bitsUsed,
+ bitsUsed, bitsUsed }, false, false, ColorModel.OPAQUE, dataType)
+ : new ComponentColorModel(ColorSpace
+ .getInstance(ColorSpace.CS_GRAY),
+ new int[] { bitsUsed }, false, false,
+ ColorModel.OPAQUE, dataType);
+ }
+
+ private static int sizeOf(BufferedImage bi) {
+ WritableRaster raster = bi.getRaster();
+ int biSize = raster.getWidth() * raster.getHeight()
+ * raster.getNumBands()
+ * (DataBuffer.getDataTypeSize(raster.getTransferType()) >> 3);
+ return biSize;
+ }
+
+ public synchronized void returnBufferedImage(BufferedImage bi) {
+ long biSize;
+ if (maxSize == 0 || (biSize = sizeOf(bi)) > maxMemory) {
+ log("trash", bi);
+ return;
+ }
+ pool.add(bi);
+ poolMemory += biSize;
+ log("return", bi);
+ resize();
+ }
+
+ private void resize() {
+ BufferedImage bi;
+ while (pool.size() > maxSize || poolMemory > maxMemory) {
+ bi = pool.remove(0);
+ poolMemory -= sizeOf(bi);
+ log("trash", bi);
+ }
+ }
+
+ public final int getMaxSize() {
+ return maxSize;
+ }
+
+ public final void setMaxSize(int maxSize) {
+ if (maxSize < 0) {
+ throw new IllegalArgumentException("maxSize: " + maxSize);
+ }
+ this.maxSize = maxSize;
+ resize();
+ }
+
+ public final long getMaxMemory() {
+ return maxMemory;
+ }
+
+ public final void setMaxMemory(long maxMemory) {
+ if (maxMemory < 0) {
+ throw new IllegalArgumentException("maxMemory: " + maxMemory);
+ }
+ this.maxMemory = maxMemory;
+ }
+
+ public final int getPoolSize() {
+ return pool.size();
+ }
+
+ public final long getPoolMemory() {
+ return poolMemory;
+ }
+}
Modified: dcm4chee/dcm4chee-arc/trunk/dcm4jboss-sar/src/java/org/dcm4chex/archive/codec/CodecCmd.java
===================================================================
--- dcm4chee/dcm4chee-arc/trunk/dcm4jboss-sar/src/java/org/dcm4chex/archive/codec/CodecCmd.java 2008-06-04 14:57:04 UTC (rev 6380)
+++ dcm4chee/dcm4chee-arc/trunk/dcm4jboss-sar/src/java/org/dcm4chex/archive/codec/CodecCmd.java 2008-06-05 11:09:27 UTC (rev 6381)
@@ -39,22 +39,13 @@
package org.dcm4chex.archive.codec;
-import java.awt.Point;
-import java.awt.Transparency;
-import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
-import java.awt.image.ColorModel;
-import java.awt.image.ComponentColorModel;
import java.awt.image.DataBuffer;
-import java.awt.image.PixelInterleavedSampleModel;
-import java.awt.image.Raster;
-import java.awt.image.SampleModel;
-import java.awt.image.WritableRaster;
-import java.util.Hashtable;
import org.apache.log4j.Logger;
import org.dcm4che.data.Dataset;
import org.dcm4che.dict.Tags;
+import org.dcm4che.dict.UIDs;
import EDU.oswego.cs.dl.util.concurrent.FIFOSemaphore;
import EDU.oswego.cs.dl.util.concurrent.Semaphore;
@@ -85,15 +76,8 @@
static Semaphore codecSemaphore = new FIFOSemaphore(maxConcurrentCodec);
- public static void setMaxConcurrentCodec(int maxConcurrentCodec) {
- codecSemaphore = new FIFOSemaphore(maxConcurrentCodec);
- CodecCmd.maxConcurrentCodec = maxConcurrentCodec;
- }
+ static BufferedImagePool biPool = new BufferedImagePool();
- public static int getMaxConcurrentCodec() {
- return maxConcurrentCodec;
- }
-
protected final int samples;
protected final int frames;
@@ -114,7 +98,11 @@
protected final int bitsUsed;
- protected CodecCmd(Dataset ds) {
+ protected final String tsuid;
+
+ protected final int dataType;
+
+ protected CodecCmd(Dataset ds, String tsuid) {
this.samples = ds.getInt(Tags.SamplesPerPixel, 1);
this.frames = ds.getInt(Tags.NumberOfFrames, 1);
this.rows = ds.getInt(Tags.Rows, 1);
@@ -125,35 +113,68 @@
this.pixelRepresentation = ds.getInt(Tags.PixelRepresentation, 0);
this.planarConfiguration = ds.getInt(Tags.PlanarConfiguration, 0);
this.frameLength = rows * columns * samples * bitsAllocated / 8;
+ this.tsuid = tsuid;
+ switch (bitsAllocated) {
+ case 8:
+ this.dataType = DataBuffer.TYPE_BYTE;
+ break;
+ case 16:
+ this.dataType = (pixelRepresentation != 0
+ && (UIDs.JPEG2000Lossless.equals(tsuid)
+ || UIDs.JPEG2000Lossy.equals(tsuid)))
+ ? DataBuffer.TYPE_SHORT
+ : DataBuffer.TYPE_USHORT;
+ break;
+ default:
+ throw new IllegalArgumentException("bits allocated:"
+ + bitsAllocated);
+ }
}
+ public static void setMaxConcurrentCodec(int maxConcurrentCodec) {
+ codecSemaphore = new FIFOSemaphore(maxConcurrentCodec);
+ CodecCmd.maxConcurrentCodec = maxConcurrentCodec;
+ }
+
+ public static int getMaxConcurrentCodec() {
+ return maxConcurrentCodec;
+ }
+
+ public static int getMaxBufferedImagePoolSize() {
+ return biPool.getMaxSize();
+ }
+
+ public static void setMaxBufferedImagePoolSize(int maxSize) {
+ biPool.setMaxSize(maxSize);
+ }
+
+ public static int getCurrentBufferedImagePoolSize() {
+ return biPool.getPoolSize();
+ }
+
+ public static long getMaxBufferedImagePoolMemory() {
+ return biPool.getMaxMemory();
+ }
+
+ public static void setMaxBufferedImagePoolMemory(long maxMemory) {
+ biPool.setMaxMemory(maxMemory);
+ }
+
+ public static long getCurrentBufferedImagePoolMemory() {
+ return biPool.getPoolMemory();
+ }
+
public int getPixelDataLength() {
return frames * frameLength;
}
- protected BufferedImage createBufferedImage() {
- int pixelStride;
- int[] bandOffset;
- int dataType;
- int colorSpace;
- if (samples == 3) {
- pixelStride = 3;
- bandOffset = new int[] { 0, 1, 2 };
- dataType = DataBuffer.TYPE_BYTE;
- colorSpace = ColorSpace.CS_sRGB;
- } else {
- pixelStride = 1;
- bandOffset = new int[] { 0 };
- dataType = bitsAllocated == 8 ? DataBuffer.TYPE_BYTE
- : DataBuffer.TYPE_USHORT;
- colorSpace = ColorSpace.CS_GRAY;
- }
- SampleModel sm = new PixelInterleavedSampleModel(dataType, columns,
- rows, pixelStride, columns * pixelStride, bandOffset);
- ColorModel cm = new ComponentColorModel(ColorSpace
- .getInstance(colorSpace), sm.getSampleSize(), false, false,
- Transparency.OPAQUE, dataType);
- WritableRaster r = Raster.createWritableRaster(sm, new Point(0, 0));
- return new BufferedImage(cm, r, false, new Hashtable());
+ protected BufferedImage getBufferedImage() {
+ return biPool.borrowOrCreateBufferedImage(rows, columns, bitsUsed,
+ samples, planarConfiguration, dataType);
}
+
+ protected void returnBufferedImage(BufferedImage bi) {
+ biPool.returnBufferedImage(bi);
+ }
+
}
Modified: dcm4chee/dcm4chee-arc/trunk/dcm4jboss-sar/src/java/org/dcm4chex/archive/codec/CompressCmd.java
===================================================================
--- dcm4chee/dcm4chee-arc/trunk/dcm4jboss-sar/src/java/org/dcm4chex/archive/codec/CompressCmd.java 2008-06-04 14:57:04 UTC (rev 6380)
+++ dcm4chee/dcm4chee-arc/trunk/dcm4jboss-sar/src/java/org/dcm4chex/archive/codec/CompressCmd.java 2008-06-05 11:09:27 UTC (rev 6381)
@@ -39,18 +39,11 @@
package org.dcm4chex.archive.codec;
-import java.awt.color.ColorSpace;
-import java.awt.image.BandedSampleModel;
import java.awt.image.BufferedImage;
-import java.awt.image.ColorModel;
-import java.awt.image.ComponentColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferShort;
import java.awt.image.DataBufferUShort;
-import java.awt.image.PixelInterleavedSampleModel;
-import java.awt.image.Raster;
-import java.awt.image.SampleModel;
import java.awt.image.WritableRaster;
import java.io.BufferedInputStream;
import java.io.EOFException;
@@ -97,15 +90,10 @@
private static final byte[] ITEM_TAG = { (byte) 0xfe, (byte) 0xff,
(byte) 0x00, (byte) 0xe0};
- private static final int[] GRAY_BAND_OFFSETS = { 0};
-
- private static final int[] RGB_BAND_OFFSETS = { 0, 1, 2};
-
-
private static class Jpeg2000 extends CompressCmd {
public Jpeg2000(Dataset ds, String tsuid) {
- super(ds, tsuid, true);
+ super(ds, tsuid);
}
public void coerceDataset(Dataset ds) {
@@ -117,16 +105,16 @@
protected void initWriteParam(ImageWriteParam param) {
if (param instanceof J2KImageWriteParam) {
- J2KImageWriteParam j2KwParam = (J2KImageWriteParam) param;
+ J2KImageWriteParam j2KwParam = (J2KImageWriteParam) param;
j2KwParam.setWriteCodeStreamOnly(true);
}
}
- };
+ }
private static class JpegLossless extends CompressCmd {
public JpegLossless(Dataset ds, String tsuid) {
- super(ds, tsuid, false);
+ super(ds, tsuid);
}
public void coerceDataset(Dataset ds) {
@@ -143,7 +131,7 @@
private static class JpegLS extends CompressCmd {
public JpegLS(Dataset ds, String tsuid) {
- super(ds, tsuid, false);
+ super(ds, tsuid);
}
public void coerceDataset(Dataset ds) {
@@ -156,7 +144,7 @@
protected void initWriteParam(ImageWriteParam param) {
param.setCompressionType(JPEG_LS);
}
- };
+ }
public static byte[] compressFile(File inFile, File outFile, String tsuid,
int[] pxdataVR, byte[] buffer)
@@ -213,25 +201,8 @@
throw new IllegalArgumentException("tsuid:" + tsuid);
}
- protected final int dataType;
-
- protected final String tsuid;
-
- protected CompressCmd(Dataset ds, String tsuid, boolean supportSigned) {
- super(ds);
- this.tsuid = tsuid;
- switch (bitsAllocated) {
- case 8:
- this.dataType = DataBuffer.TYPE_BYTE;
- break;
- case 16:
- this.dataType = pixelRepresentation == 0 || !supportSigned ? DataBuffer.TYPE_USHORT
- : DataBuffer.TYPE_SHORT;
- break;
- default:
- throw new IllegalArgumentException("bits allocated:"
- + bitsAllocated);
- }
+ protected CompressCmd(Dataset ds, String tsuid) {
+ super(ds, tsuid);
}
public abstract void coerceDataset(Dataset ds);
@@ -242,6 +213,7 @@
throws Exception {
long t1;
ImageWriter w = null;
+ BufferedImage bi = null;
boolean codecSemaphoreAquired = false;
long end = 0;
try {
@@ -257,11 +229,9 @@
w = f.getWriterForTransferSyntax(tsuid);
ImageWriteParam wParam = w.getDefaultWriteParam();
initWriteParam(wParam);
- WritableRaster raster = Raster.createWritableRaster(
- getSampleModel(), null);
+ bi = getBufferedImage();
+ WritableRaster raster = bi.getRaster();
DataBuffer db = raster.getDataBuffer();
- BufferedImage bi = new BufferedImage(getColorModel(), raster,
- false, null);
ios.write(ITEM_TAG);
ios.writeInt(0);
for (int i = 0; i < frames; ++i) {
@@ -296,6 +266,7 @@
}
} finally {
if (w != null) w.dispose();
+ if (bi != null) biPool.returnBufferedImage(bi);
if (codecSemaphoreAquired) {
log.debug("release codec semaphore");
codecSemaphore.release();
@@ -353,28 +324,4 @@
}
}
}
-
- private SampleModel getSampleModel() {
- if (planarConfiguration == 0) {
- return new PixelInterleavedSampleModel(dataType, columns, rows,
- samples, columns * samples,
- samples == 1 ? GRAY_BAND_OFFSETS : RGB_BAND_OFFSETS);
- } else {
- return new BandedSampleModel(dataType, columns, rows, samples);
- }
- }
-
- private ColorModel getColorModel() {
-
- if (samples == 3) {
- return new ComponentColorModel(ColorSpace
- .getInstance(ColorSpace.CS_sRGB), new int[] { bitsUsed,
- bitsUsed, bitsUsed}, false, false, ColorModel.OPAQUE,
- dataType);
- } else {
- return new ComponentColorModel(ColorSpace
- .getInstance(ColorSpace.CS_GRAY), new int[] { bitsUsed},
- false, false, ColorModel.OPAQUE, dataType);
- }
- }
}
Modified: dcm4chee/dcm4chee-arc/trunk/dcm4jboss-sar/src/java/org/dcm4chex/archive/codec/DecompressCmd.java
===================================================================
--- dcm4chee/dcm4chee-arc/trunk/dcm4jboss-sar/src/java/org/dcm4chex/archive/codec/DecompressCmd.java 2008-06-04 14:57:04 UTC (rev 6380)
+++ dcm4chee/dcm4chee-arc/trunk/dcm4jboss-sar/src/java/org/dcm4chex/archive/codec/DecompressCmd.java 2008-06-05 11:09:27 UTC (rev 6381)
@@ -90,8 +90,6 @@
private final ImageInputStream iis;
- private String tsuid;
-
private int[] simpleFrameList;
public static byte[] decompressFile(File inFile, File outFile,
@@ -151,8 +149,7 @@
public DecompressCmd(Dataset ds, String tsuid, DcmParser parser)
throws IOException {
- super(ds);
- this.tsuid = tsuid;
+ super(ds, tsuid);
this.iis = parser.getImageInputStream();
this.itemParser = new ItemParser(parser);
if (samples == 3) {
@@ -179,7 +176,7 @@
t1 = System.currentTimeMillis();
ImageReaderFactory f = ImageReaderFactory.getInstance();
reader = f.getReaderForTransferSyntax(tsuid);
- bi = createBufferedImage();
+ bi = getBufferedImage();
for (int i = 0, n = getNumberOfFrames(); i < n; ++i) {
int frame = simpleFrameList != null ? (simpleFrameList[i]-1) : i;
log.debug("start decompression of frame #" + (frame + 1));
@@ -202,6 +199,8 @@
} finally {
if (reader != null)
reader.dispose();
+ if (bi != null)
+ biPool.returnBufferedImage(bi);
if (codecSemaphoreAquired) {
log.debug("release codec semaphore");
codecSemaphore.release();
Modified: dcm4chee/dcm4chee-arc/trunk/dcm4jboss-sar/src/java/org/dcm4chex/archive/mbean/CompressionService.java
===================================================================
--- dcm4chee/dcm4chee-arc/trunk/dcm4jboss-sar/src/java/org/dcm4chex/archive/mbean/CompressionService.java 2008-06-04 14:57:04 UTC (rev 6380)
+++ dcm4chee/dcm4chee-arc/trunk/dcm4jboss-sar/src/java/org/dcm4chex/archive/mbean/CompressionService.java 2008-06-05 11:09:27 UTC (rev 6381)
@@ -236,6 +236,32 @@
CodecCmd.setMaxConcurrentCodec(maxConcurrentCodec);
}
+ public final int getMaxBufferedImagePoolSize() {
+ return CodecCmd.getMaxBufferedImagePoolSize();
+ }
+
+ public final void setMaxBufferedImagePoolSize(int maxSize) {
+ CodecCmd.setMaxBufferedImagePoolSize(maxSize);
+ }
+
+ public final int getCurrentBufferedImagePoolSize() {
+ return CodecCmd.getCurrentBufferedImagePoolSize();
+ }
+
+ public final String getMaxBufferedImagePoolMemory() {
+ return FileUtils.formatSize(CodecCmd.getMaxBufferedImagePoolMemory());
+ }
+
+ public final void setMaxBufferedImagePoolMemory(String maxMemory) {
+ CodecCmd.setMaxBufferedImagePoolMemory(
+ FileUtils.parseSize(maxMemory, 0L));
+ }
+
+ public final String getCurrentBufferedImagePoolMemory() {
+ return FileUtils.formatSize(
+ CodecCmd.getCurrentBufferedImagePoolMemory());
+ }
+
public final void setTempDir( String dirPath ) {
tmpDir = new File(dirPath);
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|