All Downloads are FREE. Search and download functionalities are using the official Maven repository.

it.tidalwave.imageio.rawprocessor.PipelineArtifact Maven / Gradle / Ivy

The newest version!
/***********************************************************************************************************************
 *
 * jrawio - a Java(TM) Image I/O SPI Provider for Camera Raw files
 * Copyright (C) 2003-2011 by Tidalwave s.a.s.
 *
 ***********************************************************************************************************************
 *
 * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations under the License.
 *
 ***********************************************************************************************************************
 *
 * WWW: http://jrawio.rawdarkroom.org
 * SCM: https://kenai.com/hg/jrawio~src
 *
 **********************************************************************************************************************/
package it.tidalwave.imageio.rawprocessor;

import javax.annotation.Nonnull;
import java.awt.image.BufferedImage;
import it.tidalwave.imageio.util.Lookup;
import it.tidalwave.imageio.util.Lookup.NotFoundException;
import it.tidalwave.imageio.util.Logger;
import it.tidalwave.imageio.tiff.IFD;
import it.tidalwave.imageio.tiff.TIFFMetadataSupport;
import it.tidalwave.imageio.raw.RAWImageReadParam;
import it.tidalwave.imageio.raw.RAWMetadataSupport;
import it.tidalwave.imageio.raw.Source;
import javax.annotation.Nullable;

/***********************************************************************************************************************
 *
 * @author  Fabrizio Giudici
 * @version $Id: PipelineArtifact.java,v 89379a3cf877 2011/02/28 23:54:05 fabrizio $
 *
 **********************************************************************************************************************/
public class PipelineArtifact // FIXME: refactor with Lookup
  {
    private final static String CLASS = PipelineArtifact.class.getName();
    private final static Logger logger = Logger.getLogger(CLASS);
    
    private final static char[] CHARS = { 'R', 'G', 'B', 'C', 'M', 'Y', 'W' };

    protected BufferedImage image;
    
    protected RAWMetadataSupport rawMetadata;
    
    private int[] cfaPattern;
    
    protected double[] coefficients = { 1, 1, 1, 1, 1, 1, 1, 1 };
    
    private double blackLevel = 0; // should use a different value for each channel
    
    protected Curve curve;
    
    /** The angle that the image was rotated to. */
    private int rotation;

    private final Lookup lookup;
    
    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    public PipelineArtifact (final @Nullable BufferedImage image,
                             final @Nonnull RAWMetadataSupport rawMetadata,
                             final @Nonnull RAWImageReadParam readParam)
      {
        this.image = image;
        this.rawMetadata = rawMetadata;
        lookup = Lookup.fixed(image, rawMetadata, readParam, readParam.lookup(Source.class));
        cfaPattern = computeCFAPattern();
      }

    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    public  T lookup (final @Nonnull Class type)
      throws NotFoundException
      {
        return lookup.lookup(type);
      }

    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    public void setImage (BufferedImage image)
      {
        this.image = image;  
        // TODO: should update metadata width and height!
      }
    
    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    public BufferedImage getImage()
      {
        return image;
      }
    
    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    public RAWMetadataSupport getRAWMetadata()
      {
        return rawMetadata;
      }
    
    /*******************************************************************************************************************
     *
     * Sets the curve.
     *
     * @param  curve  the curve
     *
     ******************************************************************************************************************/
    public void setCurve (Curve curve)
      {
        this.curve = curve;  
      }
    
    /*******************************************************************************************************************
     *
     * Returns the curve.
     *
     * @return  the curve
     *
     ******************************************************************************************************************/
    public Curve getCurve()
      {
        return curve;   
      }
    
    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    public void setRotation (int rotation)
      {
        this.rotation = rotation;  
      }
    
    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    public int getRotation()
      {
        return rotation;  
      }
    
    /*******************************************************************************************************************
     *
     * Sets the black level.
     *
     * @param  blackLevel  the black level
     *
     ******************************************************************************************************************/
    public void setBlackLevel (double blackLevel)
      {
        this.blackLevel = blackLevel;  
      }
    
    /*******************************************************************************************************************
     *
     * Returns the black level.
     *
     * @return  the black level
     *
     ******************************************************************************************************************/
    public double getBlackLevel()
      {
        return blackLevel;  
      }
    
    /*******************************************************************************************************************
     *
     * Returns the coefficient for the given channel.
     *
     * @param  channel  the channel
     * @return          the coefficient
     *
     ******************************************************************************************************************/
    private double getCoefficient (int channel)
      {
        return coefficients[channel];  
      }
    
    /*******************************************************************************************************************
     *
     * Returns the red coefficient.
     *  
     * @return  the red coefficient
     *
     ******************************************************************************************************************/
    public double getRedCoefficient()
      {
        return getCoefficient(0);  
      }
    
    /*******************************************************************************************************************
     *
     * Returns the green coefficient.
     *  
     * @return  the green coefficient
     *
     ******************************************************************************************************************/
    public double getGreenCoefficient()
      {
        return getCoefficient(1);  
      }
    
    /*******************************************************************************************************************
     *
     * Returns the blue coefficient.
     *  
     * @return  the blue coefficient
     *
     ******************************************************************************************************************/
    public double getBlueCoefficient()
      {
        return getCoefficient(2);  
      }
    
    /*******************************************************************************************************************
     *
     * Multiplies the red coefficient by the given value.
     *
     * @param  value  the multiplier
     *
     ******************************************************************************************************************/
    public void multiplyRedCoefficient (double value)
      {
        multiplyRGBCoefficient(0, value);    
      }
    
    /*******************************************************************************************************************
     *
     * Multiplies the green coefficient by the given value.
     *
     * @param  value  the multiplier
     *
     ******************************************************************************************************************/
    public void multiplyGreenCoefficient (double value)
      {
        multiplyRGBCoefficient(1, value);    
      }
    
    /*******************************************************************************************************************
     *
     * Multiplies the blue coefficient by the given value.
     *
     * @param  value  the multiplier
     *
     ******************************************************************************************************************/
    public void multiplyBlueCoefficient (double value)
      {
        multiplyRGBCoefficient(2, value);    
      }
    
    /*******************************************************************************************************************
     *
     * Multiplies a given channel coefficient by the given value. The channel
     * parameter can be 0,1,2,... to mean R,G,B,...
     *
     * @param  channel  the channel to multiply
     * @param  value    the multiplier
     *
     ******************************************************************************************************************/
    private void multiplyRGBCoefficient (int channel, double value)
      {
        coefficients[channel] *= value;
        logger.finer ("Coefficient[%d] = %f - has been multiplied by %f", channel, coefficients[channel], value);
      }
    
    /*******************************************************************************************************************
     *
     * Multiplies a given channel coefficient by the given value. The cfaIndex 
     * parameters refers to the channel at the given position in the CFA matrix.
     *
     * @param  channel  the channel to multiply
     * @param  value    the multiplier
     *
     ******************************************************************************************************************/
    public void multiplyCFACoefficient (int cfaIndex, double value)
      {
        int channel = cfaPattern[cfaIndex];
        coefficients[channel] *= value;
        logger.finer ("Coefficient[%d] = %f - has been multiplied by %f", channel, coefficients[channel], value);
      }
    
    /*******************************************************************************************************************
     * 
     * Retrieves the CFA pattern for the current model. This method should be 
     * overridden for non-TIFF based RAW formats.
     * 
     * @return  the CFA pattern
     * 
     *******************************************************************************/
    public int[] getCFAPattern()
      {
        return (cfaPattern != null) ? cfaPattern.clone() : null;
      }
    
    /*******************************************************************************************************************
     * 
     * Returns the CFA pattern as a string (e.g. "GRBG").
     *
     * @return  the CFA pattern
     * 
     *******************************************************************************/
    public String getCFAPatternAsString()
      {
        StringBuffer buffer = new StringBuffer();

        for (int i = 0; i < cfaPattern.length; i++)
          {
            buffer.append(CHARS[cfaPattern[i]]);
          }

        return buffer.toString();
      }
    
    /*******************************************************************************************************************
     * 
     * Computes the CFA pattern as an array of indexes. This method first searches 
     * in the EXIF directory, then in the raster directory.
     *
     * @return  the CFA pattern
     * 
     *******************************************************************************/
    private int[] computeCFAPattern()
      {
        TIFFMetadataSupport metadata = (TIFFMetadataSupport)rawMetadata;
        IFD rasterIFD = metadata.getRasterIFD();
        IFD exifIFD = metadata.getExifIFD();
        int[] result = new int[] { 0, 1, 1, 2};
        
        if ((exifIFD != null) && exifIFD.isEXIFCFAPatternAvailable())
          {
            byte[] cfaPattern = exifIFD.getEXIFCFAPattern();    
            
            for (int i = 0; i < result.length; i++)
              {
                result[i] = cfaPattern[4 + i];  
              }
          }
        
        if ((rasterIFD != null) && rasterIFD.isCFAPatternAvailable())
          {
            byte[] cfaPattern = rasterIFD.getCFAPattern();    
            
            for (int i = 0; i < result.length; i++)
              {
                result[i] = cfaPattern[i];  
              }
          }
        
        return result;
      }  
  }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy