fix handling of hsl and linear rgb (%-values)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1745412 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
1afe952ca9
commit
334ec509fa
@ -384,7 +384,7 @@ public class DrawPaint {
|
||||
*
|
||||
* @returns the RGB Color object
|
||||
*/
|
||||
private static Color HSL2RGB(double h, double s, double l, double alpha) {
|
||||
public static Color HSL2RGB(double h, double s, double l, double alpha) {
|
||||
// we clamp the values, as it possible to come up with more than 100% sat/lum
|
||||
// (see links in applyColorTransform() for more info)
|
||||
s = Math.max(0, Math.min(100, s));
|
||||
@ -491,5 +491,34 @@ public class DrawPaint {
|
||||
|
||||
return new double[] {h, s * 100, l * 100};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert sRGB float component [0..1] from sRGB to linear RGB [0..100000]
|
||||
*
|
||||
* @see Color#getRGBColorComponents(float[])
|
||||
*/
|
||||
public static int srgb2lin(float sRGB) {
|
||||
// scRGB has a linear gamma of 1.0, scale the AWT-Color which is in sRGB to linear RGB
|
||||
// see https://en.wikipedia.org/wiki/SRGB (the reverse transformation)
|
||||
if (sRGB <= 0.04045d) {
|
||||
return (int)Math.rint(100000d * sRGB / 12.92d);
|
||||
} else {
|
||||
return (int)Math.rint(100000d * Math.pow((sRGB + 0.055d) / 1.055d, 2.4d));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert linear RGB [0..100000] to sRGB float component [0..1]
|
||||
*
|
||||
* @see Color#getRGBColorComponents(float[])
|
||||
*/
|
||||
public static float lin2srgb(int linRGB) {
|
||||
// color in percentage is in linear RGB color space, i.e. needs to be gamma corrected for AWT color
|
||||
// see https://en.wikipedia.org/wiki/SRGB (The forward transformation)
|
||||
if (linRGB <= 0.0031308d) {
|
||||
return (float)(linRGB / 100000d * 12.92d);
|
||||
} else {
|
||||
return (float)(1.055d * Math.pow(linRGB / 100000d, 1.0d/2.4d) - 0.055d);
|
||||
}
|
||||
}
|
||||
}
|
@ -30,6 +30,7 @@ import org.apache.poi.util.POILogger;
|
||||
import org.apache.xmlbeans.XmlObject;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTColor;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTHslColor;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveFixedPercentage;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetColor;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTScRgbColor;
|
||||
@ -122,9 +123,7 @@ public class XSLFColor {
|
||||
int h = hsl.getHue2();
|
||||
int s = hsl.getSat2();
|
||||
int l = hsl.getLum2();
|
||||
// This conversion is not correct and differs from PowerPoint.
|
||||
// TODO: Revisit and improve.
|
||||
color = Color.getHSBColor(h / 60000f, s / 100000f, l / 100000f);
|
||||
color = DrawPaint.HSL2RGB(h / 60000d, s / 1000d, l / 1000d, 1d);
|
||||
} else if (ch instanceof CTPresetColor) {
|
||||
CTPresetColor prst = (CTPresetColor)ch;
|
||||
String colorName = prst.getVal().toString();
|
||||
@ -143,13 +142,11 @@ public class XSLFColor {
|
||||
CTColor ctColor = theme.getCTColor(colorRef);
|
||||
if(ctColor != null) color = toColor(ctColor, null);
|
||||
} else if (ch instanceof CTScRgbColor) {
|
||||
// same as CTSRgbColor but with values expressed in percents
|
||||
// color in percentage is in linear RGB color space, i.e. needs to be gamma corrected for AWT color
|
||||
CTScRgbColor scrgb = (CTScRgbColor)ch;
|
||||
int r = scrgb.getR();
|
||||
int g = scrgb.getG();
|
||||
int b = scrgb.getB();
|
||||
color = new Color(255 * r / 100000, 255 * g / 100000, 255 * b / 100000);
|
||||
color = new Color(DrawPaint.lin2srgb(scrgb.getR()), DrawPaint.lin2srgb(scrgb.getG()), DrawPaint.lin2srgb(scrgb.getB()));
|
||||
} else if (ch instanceof CTSRgbColor) {
|
||||
// color in sRGB color space, i.e. same as AWT Color
|
||||
CTSRgbColor srgb = (CTSRgbColor)ch;
|
||||
byte[] val = srgb.getVal();
|
||||
color = new Color(0xFF & val[0], 0xFF & val[1], 0xFF & val[2]);
|
||||
@ -190,24 +187,11 @@ public class XSLFColor {
|
||||
if (fill.isSetSrgbClr()) {
|
||||
fill.unsetSrgbClr();
|
||||
}
|
||||
|
||||
CTSRgbColor rgb = fill.addNewSrgbClr();
|
||||
|
||||
float[] rgbaf = color.getRGBComponents(null);
|
||||
int r = color.getRed(), g = color.getGreen(), b = color.getBlue();
|
||||
if (rgbaf[0]*255f == r && rgbaf[1]*255f == g && rgbaf[2]*255f == b) {
|
||||
rgb.setVal(new byte[]{(byte)r, (byte)g, (byte)b });
|
||||
} else {
|
||||
rgb.addNewRed().setVal((int)(100000 * rgbaf[0]));
|
||||
rgb.addNewGreen().setVal((int)(100000 * rgbaf[1]));
|
||||
rgb.addNewBlue().setVal((int)(100000 * rgbaf[2]));
|
||||
}
|
||||
|
||||
// alpha (%)
|
||||
if (rgbaf.length == 4 && rgbaf[3] < 1f) {
|
||||
rgb.addNewAlpha().setVal((int)(100000 * rgbaf[3]));
|
||||
if (fill.isSetScrgbClr()) {
|
||||
fill.unsetScrgbClr();
|
||||
}
|
||||
|
||||
|
||||
if (fill.isSetHslClr()) {
|
||||
fill.unsetHslClr();
|
||||
}
|
||||
@ -220,13 +204,41 @@ public class XSLFColor {
|
||||
fill.unsetSchemeClr();
|
||||
}
|
||||
|
||||
if (fill.isSetScrgbClr()) {
|
||||
fill.unsetScrgbClr();
|
||||
}
|
||||
|
||||
if (fill.isSetSysClr()) {
|
||||
fill.unsetSysClr();
|
||||
}
|
||||
|
||||
float[] rgbaf = color.getRGBComponents(null);
|
||||
boolean addAlpha = (rgbaf.length == 4 && rgbaf[3] < 1f);
|
||||
CTPositiveFixedPercentage alphaPct;
|
||||
|
||||
// see office open xml part 4 - 5.1.2.2.30 and 5.1.2.2.32
|
||||
if (isInt(rgbaf[0]) && isInt(rgbaf[1]) && isInt(rgbaf[2])) {
|
||||
// sRGB has a gamma of 2.2
|
||||
CTSRgbColor rgb = fill.addNewSrgbClr();
|
||||
|
||||
byte rgbBytes[] = { (byte)color.getRed(), (byte)color.getGreen(), (byte)color.getBlue() };
|
||||
rgb.setVal(rgbBytes);
|
||||
alphaPct = (addAlpha) ? rgb.addNewAlpha() : null;
|
||||
} else {
|
||||
CTScRgbColor rgb = fill.addNewScrgbClr();
|
||||
rgb.setR(DrawPaint.srgb2lin(rgbaf[0]));
|
||||
rgb.setG(DrawPaint.srgb2lin(rgbaf[1]));
|
||||
rgb.setB(DrawPaint.srgb2lin(rgbaf[2]));
|
||||
alphaPct = (addAlpha) ? rgb.addNewAlpha() : null;
|
||||
}
|
||||
|
||||
// alpha (%)
|
||||
if (alphaPct != null) {
|
||||
alphaPct.setVal((int)(100000 * rgbaf[3]));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true, if this is an integer color value
|
||||
*/
|
||||
private static boolean isInt(float f) {
|
||||
return Math.abs((f*255f) - Math.rint(f*255f)) < 0.00001f;
|
||||
}
|
||||
|
||||
private int getRawValue(String elem) {
|
||||
|
@ -40,10 +40,13 @@ import javax.imageio.ImageIO;
|
||||
import org.apache.poi.POIDataSamples;
|
||||
import org.apache.poi.POIXMLDocumentPart;
|
||||
import org.apache.poi.POIXMLDocumentPart.RelationPart;
|
||||
import org.apache.poi.sl.draw.DrawPaint;
|
||||
import org.apache.poi.sl.usermodel.PaintStyle;
|
||||
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
|
||||
import org.apache.poi.sl.usermodel.PictureData;
|
||||
import org.apache.poi.sl.usermodel.PictureData.PictureType;
|
||||
import org.apache.poi.sl.usermodel.ShapeType;
|
||||
import org.apache.poi.sl.usermodel.VerticalAlignment;
|
||||
import org.apache.poi.xslf.usermodel.DrawingParagraph;
|
||||
import org.apache.poi.xslf.usermodel.DrawingTextBody;
|
||||
import org.apache.poi.xslf.usermodel.XMLSlideShow;
|
||||
@ -56,6 +59,7 @@ import org.apache.poi.xslf.usermodel.XSLFShape;
|
||||
import org.apache.poi.xslf.usermodel.XSLFSlide;
|
||||
import org.apache.poi.xslf.usermodel.XSLFSlideLayout;
|
||||
import org.apache.poi.xslf.usermodel.XSLFSlideMaster;
|
||||
import org.apache.poi.xslf.usermodel.XSLFTextRun;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
@ -478,25 +482,39 @@ public class TestXSLFBugs {
|
||||
|
||||
@Test
|
||||
public void bug58217() throws IOException {
|
||||
Color fillColor = new Color(1f,1f,0f,0.1f);
|
||||
Color lineColor = new Color(25.3f/255f,1f,0f,0.4f);
|
||||
Color textColor = new Color(1f,1f,0f,0.6f);
|
||||
|
||||
XMLSlideShow ppt1 = new XMLSlideShow();
|
||||
XSLFSlide sl = ppt1.createSlide();
|
||||
XSLFAutoShape as = sl.createAutoShape();
|
||||
as.setShapeType(ShapeType.STAR_10);
|
||||
as.setAnchor(new Rectangle2D.Double(100,100,300,300));
|
||||
as.setFillColor(new Color(1f,1f,0f,0.1f));
|
||||
as.setLineColor(new Color(1f,1f,0f,0.4f));
|
||||
as.setFillColor(fillColor);
|
||||
as.setLineColor(lineColor);
|
||||
as.setText("Alpha");
|
||||
as.getTextParagraphs().get(0).getTextRuns().get(0).setFontColor(new Color(1f,1f,0f,0.6f));
|
||||
as.setVerticalAlignment(VerticalAlignment.MIDDLE);
|
||||
as.setHorizontalCentered(true);
|
||||
XSLFTextRun tr = as.getTextParagraphs().get(0).getTextRuns().get(0);
|
||||
tr.setFontSize(32d);
|
||||
tr.setFontColor(textColor);
|
||||
XMLSlideShow ppt2 = XSLFTestDataSamples.writeOutAndReadBack(ppt1);
|
||||
ppt1.close();
|
||||
sl = ppt2.getSlides().get(0);
|
||||
as = (XSLFAutoShape)sl.getShapes().get(0);
|
||||
SolidPaint ps = (SolidPaint)as.getFillStyle().getPaint();
|
||||
assertEquals(10000, ps.getSolidColor().getAlpha());
|
||||
ps = (SolidPaint)as.getStrokeStyle().getPaint();
|
||||
assertEquals(40000, ps.getSolidColor().getAlpha());
|
||||
ps = (SolidPaint)as.getTextParagraphs().get(0).getTextRuns().get(0).getFontColor();
|
||||
assertEquals(60000, ps.getSolidColor().getAlpha());
|
||||
checkColor(fillColor, as.getFillStyle().getPaint());
|
||||
checkColor(lineColor, as.getStrokeStyle().getPaint());
|
||||
checkColor(textColor, as.getTextParagraphs().get(0).getTextRuns().get(0).getFontColor());
|
||||
ppt2.close();
|
||||
}
|
||||
|
||||
private static void checkColor(Color expected, PaintStyle actualStyle) {
|
||||
assertTrue(actualStyle instanceof SolidPaint);
|
||||
SolidPaint ps = (SolidPaint)actualStyle;
|
||||
Color actual = DrawPaint.applyColorTransform(ps.getSolidColor());
|
||||
float expRGB[] = expected.getRGBComponents(null);
|
||||
float actRGB[] = actual.getRGBComponents(null);
|
||||
assertArrayEquals(expRGB, actRGB, 0.0001f);
|
||||
}
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ public class TestXSLFColor {
|
||||
c.setLum2(50000);
|
||||
|
||||
XSLFColor color = new XSLFColor(xml, null, null);
|
||||
assertEquals(new Color(128, 00, 00), color.getColor());
|
||||
assertEquals(Color.BLUE, color.getColor());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
Loading…
Reference in New Issue
Block a user