/******************************************************************************* * Copyright (c) 2016 Weasis Team and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Nicolas Roduit - initial API and implementation *******************************************************************************/ package org.weasis.core.api.image.op; import java.awt.Rectangle; import java.awt.image.DataBuffer; import java.awt.image.Raster; import java.awt.image.RenderedImage; import java.awt.image.WritableRaster; import java.util.Map; import javax.media.jai.ColormapOpImage; import javax.media.jai.ImageLayout; import javax.media.jai.RasterAccessor; import javax.media.jai.RasterFormatTag; import com.sun.media.jai.util.ImageUtil; final class RectifyUShortToShortDataOpImage extends ColormapOpImage { /** * Constructor. * * @param source * The source image. * @param layout * The destination image layout. */ public RectifyUShortToShortDataOpImage(RenderedImage source, Map config, ImageLayout layout) { super(source, layout, config, true); // Set flag to permit in-place operation. permitInPlaceOperation(); // Initialize the colormap if necessary. initializeColormapOperation(); } /** * Transform the colormap according to the rescaling parameters. Should never go through this function. */ @Override protected void transformColormap(byte[][] colormap) { for (int b = 0; b < 3; b++) { byte[] map = colormap[b]; int mapSize = map.length; for (int i = 0; i < mapSize; i++) { map[i] = ImageUtil.clampRoundByte((map[i] & 0xFF)); } } } /** * Operation to correct signed images (9-15 bits) read by imageio codecs. * * @param sources * Cobbled sources, guaranteed to provide all the source data necessary for computing the rectangle. * @param dest * The tile containing the rectangle to be computed. * @param destRect * The rectangle within the tile to be computed. */ @Override protected void computeRect(Raster[] sources, WritableRaster dest, Rectangle destRect) { RasterFormatTag srcTag = new RasterFormatTag(getSampleModel(), DataBuffer.TYPE_USHORT | 1024); RasterFormatTag dstTag = new RasterFormatTag(dest.getSampleModel(), DataBuffer.TYPE_SHORT | 1024); Rectangle srcRect = mapDestRect(destRect, 0); RasterAccessor dst = new RasterAccessor(dest, destRect, dstTag, getColorModel()); RasterAccessor src = new RasterAccessor(sources[0], srcRect, srcTag, getSourceImage(0).getColorModel()); switch (dst.getDataType()) { case DataBuffer.TYPE_SHORT: computeRectShort(src, dst); break; } /* Do not clamp dst data. */ dst.copyDataToRaster(); } private void computeRectShort(RasterAccessor src, RasterAccessor dst) { int dstWidth = dst.getWidth(); int dstHeight = dst.getHeight(); int dstBands = dst.getNumBands(); int dstLineStride = dst.getScanlineStride(); int dstPixelStride = dst.getPixelStride(); int[] dstBandOffsets = dst.getBandOffsets(); short[][] dstData = dst.getShortDataArrays(); int srcLineStride = src.getScanlineStride(); int srcPixelStride = src.getPixelStride(); int[] srcBandOffsets = src.getBandOffsets(); short[][] srcData = src.getShortDataArrays(); for (int b = 0; b < dstBands; b++) { short[] d = dstData[b]; short[] s = srcData[b]; if (s.length == d.length) { System.arraycopy(s, 0, d, 0, d.length); } else { int dstLineOffset = dstBandOffsets[b]; int srcLineOffset = srcBandOffsets[b]; for (int h = 0; h < dstHeight; h++) { int dstPixelOffset = dstLineOffset; int srcPixelOffset = srcLineOffset; dstLineOffset += dstLineStride; srcLineOffset += srcLineStride; for (int w = 0; w < dstWidth; w++) { d[dstPixelOffset] = s[srcPixelOffset]; dstPixelOffset += dstPixelStride; srcPixelOffset += srcPixelStride; } } } } } }