pdfHTML: Colourblindness example

This is a code example of iText PDF, discover more.

8th March 2017
iText PDF

Switch code for this example

ColourBlindBlockCssApplier.java
/*
    This file is part of the iText (R) project.
    Copyright (c) 1998-2018 iText Group NV
    Authors: iText Software.

    For more information, please contact iText Software at this address:
    sales@itextpdf.com
 */
package com.itextpdf.samples.pdfHTML.ColourBlindness;

import com.itextpdf.html2pdf.attach.ITagWorker;
import com.itextpdf.html2pdf.attach.ProcessorContext;
import com.itextpdf.html2pdf.css.CssConstants;
import com.itextpdf.html2pdf.css.apply.impl.BlockCssApplier;
import com.itextpdf.kernel.colors.WebColors;
import com.itextpdf.styledxmlparser.node.IStylesContainer;

import java.util.Map;

/**
 * Css applier extending from a blockcssapplier that transforms standard colours into the ones colourblind people see
 */
public class ColourBlindBlockCssApplier extends BlockCssApplier {
    private static final double RGB_MAX_VAL = 255.0;
    private String colourBlindness = ColourBlindnessTransforms.PROTANOPIA;

    /**
     * Set the from of colour blindness to simulate.
     * Accepted values are Protanopia, Protanomaly, Deuteranopia, Deuteranomaly, Tritanopia, Tritanomaly, Achromatopsia, Achromatomaly.
     * Default value is Protanopia
     * @param colourBlindness
     */
    public void setColourBlindness(String colourBlindness){
        this.colourBlindness = colourBlindness;
    }

    @Override
    public void apply(ProcessorContext context, IStylesContainer stylesContainer, ITagWorker tagWorker){
        Map cssStyles = stylesContainer.getStyles();
        if(cssStyles.containsKey(CssConstants.COLOR)){
            String newColor = TransformColor(cssStyles.get(CssConstants.COLOR));
            cssStyles.put(CssConstants.COLOR,newColor);
            stylesContainer.setStyles(cssStyles);
        }
        if(cssStyles.containsKey(CssConstants.BACKGROUND_COLOR)){
            String newColor = TransformColor(cssStyles.get(CssConstants.BACKGROUND_COLOR));
            cssStyles.put(CssConstants.BACKGROUND_COLOR,newColor);
            stylesContainer.setStyles(cssStyles);
        }
        super.apply(context, stylesContainer,tagWorker);

    }

    private String TransformColor(String originalColor){
        //Array creation is a bit clumsy, could do with some cleaning
        float[] rgbaColor = WebColors.getRGBAColor(originalColor);
        float[] rgbColor = {rgbaColor[0],rgbaColor[1],rgbaColor[2]};
        float[] newColourRgb = ColourBlindnessTransforms.simulateColourBlindness(colourBlindness,rgbColor);
        float[] newColourRgba = {newColourRgb[0],newColourRgb[1],newColourRgb[2],rgbaColor[3]};
        double[] newColorArray = scaleColorFloatArray(newColourRgba);
        String newColorString = "rgba("+(int) newColorArray[0]+","+(int)newColorArray[1]+","+(int)newColorArray[2]+","+newColorArray[3]+")";
        return newColorString;
    }

    private double[] scaleColorFloatArray(float[] colors){
        double red = (colors[0]*RGB_MAX_VAL);
        double green =  (colors[1]*RGB_MAX_VAL);
        double blue =  (colors[2]*RGB_MAX_VAL);
        double[] res = {red,green, blue, (double) colors[3]};
        return res;
    }


}
ColourBlindSpanTagCssApplier.java
/*
    This file is part of the iText (R) project.
    Copyright (c) 1998-2018 iText Group NV
    Authors: iText Software.

    For more information, please contact iText Software at this address:
    sales@itextpdf.com
 */
package com.itextpdf.samples.pdfHTML.ColourBlindness;

import com.itextpdf.html2pdf.attach.ITagWorker;
import com.itextpdf.html2pdf.attach.ProcessorContext;
import com.itextpdf.html2pdf.css.CssConstants;
import com.itextpdf.html2pdf.css.apply.impl.SpanTagCssApplier;
import com.itextpdf.kernel.colors.WebColors;
import com.itextpdf.styledxmlparser.node.IStylesContainer;

import java.util.Map;

public class ColourBlindSpanTagCssApplier extends SpanTagCssApplier {

    private static final double RGB_MAX_VAL = 255.0;
    private String colourBlindness = ColourBlindnessTransforms.PROTANOPIA;

    /**
     * Set the from of colour blindness to simulate.
     * Accepted values are Protanopia, Protanomaly, Deuteranopia, Deuteranomaly, Tritanopia, Tritanomaly, Achromatopsia, Achromatomaly.
     * Default value is Protanopia
     * @param colourBlindness
     */
    public void setColourBlindness(String colourBlindness){
        this.colourBlindness = colourBlindness;
    }

    @Override
    public void apply(ProcessorContext context, IStylesContainer stylesContainer, ITagWorker tagWorker){
        Map cssStyles = stylesContainer.getStyles();
        if(cssStyles.containsKey(CssConstants.COLOR)){
            String newColor = TransformColor(cssStyles.get(CssConstants.COLOR));
            cssStyles.put(CssConstants.COLOR,newColor);
            stylesContainer.setStyles(cssStyles);
        }
        if(cssStyles.containsKey(CssConstants.BACKGROUND_COLOR)){
            String newColor = TransformColor(cssStyles.get(CssConstants.BACKGROUND_COLOR));
            cssStyles.put(CssConstants.BACKGROUND_COLOR,newColor);
            stylesContainer.setStyles(cssStyles);
        }
        super.apply(context, stylesContainer,tagWorker);

    }

    private String TransformColor(String originalColor){
        //Array creation is a bit clumsy, could do with some cleaning
        float[] rgbaColor = WebColors.getRGBAColor(originalColor);
        float[] rgbColor = {rgbaColor[0],rgbaColor[1],rgbaColor[2]};
        float[] newColourRgb = ColourBlindnessTransforms.simulateColourBlindness(colourBlindness,rgbColor);
        float[] newColourRgba = {newColourRgb[0],newColourRgb[1],newColourRgb[2],rgbaColor[3]};
        double[] newColorArray = scaleColorFloatArray(newColourRgba);
        String newColorString = "rgba("+(int) newColorArray[0]+","+(int)newColorArray[1]+","+(int)newColorArray[2]+","+newColorArray[3]+")";
        return newColorString;
    }

    private double[] scaleColorFloatArray(float[] colors){
        double red = (colors[0]*RGB_MAX_VAL);
        double green =  (colors[1]*RGB_MAX_VAL);
        double blue =  (colors[2]*RGB_MAX_VAL);
        double[] res = {red,green, blue, (double) colors[3]};
        return res;
    }
}
ColourBlindnessCssApplierFactory.java
/*
    This file is part of the iText (R) project.
    Copyright (c) 1998-2018 iText Group NV
    Authors: iText Software.

    For more information, please contact iText Software at this address:
    sales@itextpdf.com
 */
package com.itextpdf.samples.pdfHTML.ColourBlindness;


import com.itextpdf.html2pdf.css.apply.ICssApplier;
import com.itextpdf.html2pdf.css.apply.impl.DefaultCssApplierFactory;
import com.itextpdf.html2pdf.html.TagConstants;
import com.itextpdf.styledxmlparser.node.IElementNode;

public class ColourBlindnessCssApplierFactory extends DefaultCssApplierFactory {

    private String toSimulate;

    public ColourBlindnessCssApplierFactory(String toSimulate){
        this.toSimulate = toSimulate;
    }
    @Override
    public ICssApplier getCustomCssApplier(IElementNode tag) {
        if(tag.name().equals(TagConstants.DIV)){
            ColourBlindBlockCssApplier applier =  new ColourBlindBlockCssApplier();
            applier.setColourBlindness(toSimulate);
            return applier;
        }

        if(tag.name().equals(TagConstants.SPAN)){
            ColourBlindSpanTagCssApplier applier =  new ColourBlindSpanTagCssApplier();
            applier.setColourBlindness(toSimulate);
            return applier;
        }

        return null;
    }
}
ColourBlindnessTransforms.java
/*
    This file is part of the iText (R) project.
    Copyright (c) 1998-2018 iText Group NV
    Authors: iText Software.

    For more information, please contact iText Software at this address:
    sales@itextpdf.com
 */
package com.itextpdf.samples.pdfHTML.ColourBlindness;

public class ColourBlindnessTransforms {
/*
        Normal:{ R:[100, 0, 0], G:[0, 100, 0], B:[0, 100, 0]},
        Protanopia:{ R:[56.667, 43.333, 0], G:[55.833, 44.167, 0], B:[0, 24.167, 75.833]},
        Protanomaly:{ R:[81.667, 18.333, 0], G:[33.333, 66.667, 0], B:[0, 12.5, 87.5]},
        Deuteranopia:{ R:[62.5, 37.5, 0], G:[70, 30, 0], B:[0, 30, 70]},
        Deuteranomaly:{ R:[80, 20, 0], G:[25.833, 74.167, 0], B:[0, 14.167, 85.833]},
        Tritanopia:{ R:[95, 5, 0], G:[0, 43.333, 56.667], B:[0, 47.5, 52.5]},
        Tritanomaly:{ R:[96.667, 3.333, 0], G:[0, 73.333, 26.667], B:[0, 18.333, 81.667]},
        Achromatopsia:{ R:[29.9, 58.7, 11.4], G:[29.9, 58.7, 11.4], B:[29.9, 58.7, 11.4]},
        Achromatomaly:{ R:[61.8, 32, 6.2], G:[16.3, 77.5, 6.2], B:[16.3, 32.0, 51.6]}
*/
    public static final String PROTANOPIA = "Protanopia";
    private static float[][] PROTANOPIA_TRANSFORM = {{0.5667f,0.43333f,0},{0.55833f,0.44167f,0},{0,0.24167f,0.75833f}};

    public static final String PROTANOMALY = "Protanomaly";
    private static float[][] PROTANOMALY_TRANSFORM = {{0.81667f,0.18333f,0},{0.33333f,0.66667f,0},{0,0.125f,0.875f}};

    public static final String DEUTERANOPIA = "Deuteranopia";
    private static float[][] DEUTERANOPIA_TRANSFORM = {{0.625f,0.375f,0},{0.70f,0.30f,0},{0,0.30f,0.70f}};

    public static final String DEUTERANOMALY = "Deuteranomaly";
    private static float[][] DEUTERANOMALY_TRANSFORM = {{0.80f,0.20f,0},{0.25833f,0.74167f,0},{0,0.14167f,0.85833f}};

    public static final String TRITANOPIA = "Tritanopia";
    private static float[][] TRITANOPIA_TRANSFORM = {{0.95f,0.05f,0},{0,0.43333f,0.56667f},{0,0.475f,0.525f}};

    public static final String TRITANOMALY = "Tritanomaly";
    private static float[][] TRITANOMALY_TRANSFORM = {{0.96667f,0.0333f,0},{0,0.73333f,0.26667f},{0,0.18333f,0.81667f}};

    public static final String ACHROMATOPSIA = "Achromatopsia";
    private static float[][] ACHROMATOPSIA_TRANSFORM = {{0.299f,0.587f,0.114f},{0.299f,0.587f,0.114f},{0.299f,0.587f,0.114f}};

    public static final String ACHROMATOMALY = "Achromatomaly";
    private static float[][] ACHROMATOMALY_TRANSFORM = {{0.618f,0.32f,0.062f},{0.163f,0.775f,0.062f},{0.299f,0.587f,0.114f}};


    //Protanopia:{ R:[56.667, 43.333, 0], G:[55.833, 44.167, 0], B:[0, 24.167, 75.833]}
    public static float[] simulateProtanopia(float[] originalRgb){
        int nrOfChannels = 3; //R, G, B
        float[] result = new float[nrOfChannels];
        for(int i = 0; i
Contact

Still have questions? 

We're happy to answer your questions. Reach out to us and we'll get back to you shortly.

Contact us
Stay updated

Join 11,000+ subscribers and become an iText PDF expert by staying up to date with our new products, updates, tips, technical solutions and happenings.

Subscribe Now