Navigation Menu

Skip to content

Commit

Permalink
#397 Extended image spec parser with replace-colors filters
Browse files Browse the repository at this point in the history
  • Loading branch information
ishubin committed May 5, 2016
1 parent 6185adc commit 271afad
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 57 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
@@ -1,6 +1,12 @@
# Change log # Change log
All changes to Galen Framework project will be documented in this file All changes to Galen Framework project will be documented in this file



## [2.3.0][Unknown]
### Added
- Added replace-colors filter to image spec


## [2.2.5][2015-04-14] ## [2.2.5][2015-04-14]
- Fixed #318 Path was incorrectly resolved when loading js scripts - Fixed #318 Path was incorrectly resolved when loading js scripts


Expand Down
Expand Up @@ -22,6 +22,7 @@
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;


import com.galenframework.rainbow4j.colorscheme.ColorClassifier;
import com.galenframework.rainbow4j.colorscheme.GradientColorClassifier; import com.galenframework.rainbow4j.colorscheme.GradientColorClassifier;
import com.galenframework.rainbow4j.colorscheme.SimpleColorClassifier; import com.galenframework.rainbow4j.colorscheme.SimpleColorClassifier;
import com.galenframework.specs.colors.ColorRange; import com.galenframework.specs.colors.ColorRange;
Expand Down Expand Up @@ -62,31 +63,34 @@ public List<ColorRange> read(StringCharReader reader) {
throw new SyntaxException("No color defined"); throw new SyntaxException("No color defined");
} }


if (colorText.contains("-")) {
//parsing gradients
List<Color> colors = asList(colorText.split("-")).stream()
.map(String::trim)
.filter(text -> !text.isEmpty())
.map(this::parseColor)
.collect(Collectors.toList());

colorRanges.add(new ColorRange(colorText, new GradientColorClassifier(colorText, colors), range));
} else {
//single color
Color color = parseColor(colorText);
colorRanges.add(new ColorRange(colorText, new SimpleColorClassifier(colorText, color), range));
}



ColorClassifier colorClassifier = parseColorClassifier(colorText);
colorRanges.add(new ColorRange(colorText, colorClassifier, range));
} }
return colorRanges; return colorRanges;
} }


private String toHexColor(Color color) { public static ColorClassifier parseColorClassifier(String colorText) {
return String.format("#%02x%02x%02x", color.getRed(), color.getGreen(), color.getBlue()); if (colorText.contains("-")) {
return parseGradientClassifier(colorText);
} else {
Color color = parseColor(colorText);
return new SimpleColorClassifier(colorText, color);
}
}

public static GradientColorClassifier parseGradientClassifier(String colorText) {
//parsing gradients
List<Color> colors = asList(colorText.split("-")).stream()
.map(String::trim)
.filter(text -> !text.isEmpty())
.map(ExpectColorRanges::parseColor)
.collect(Collectors.toList());

return new GradientColorClassifier(colorText, colors);
} }


private Color parseColor(String colorText) { public static Color parseColor(String colorText) {
if (colorText.startsWith("#")) { if (colorText.startsWith("#")) {
if (colorText.length() == 4) { if (colorText.length() == 4) {
return Color.decode(convertShortHandNotation(colorText)); return Color.decode(convertShortHandNotation(colorText));
Expand All @@ -101,7 +105,7 @@ private Color parseColor(String colorText) {
else throw new SyntaxException("Unknown color: " + colorText); else throw new SyntaxException("Unknown color: " + colorText);
} }


private String convertShortHandNotation(String colorText) { private static String convertShortHandNotation(String colorText) {
char r = colorText.charAt(1); char r = colorText.charAt(1);
char g = colorText.charAt(2); char g = colorText.charAt(2);
char b = colorText.charAt(3); char b = colorText.charAt(3);
Expand Down
Expand Up @@ -21,6 +21,7 @@
import com.galenframework.parser.SyntaxException; import com.galenframework.parser.SyntaxException;
import com.galenframework.rainbow4j.ImageHandler; import com.galenframework.rainbow4j.ImageHandler;
import com.galenframework.rainbow4j.Rainbow4J; import com.galenframework.rainbow4j.Rainbow4J;
import com.galenframework.rainbow4j.colorscheme.ColorClassifier;
import com.galenframework.rainbow4j.filters.*; import com.galenframework.rainbow4j.filters.*;
import com.galenframework.specs.SpecImage; import com.galenframework.specs.SpecImage;
import com.galenframework.parser.StringCharReader; import com.galenframework.parser.StringCharReader;
Expand All @@ -31,12 +32,18 @@
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;


import java.awt.*;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;


import static com.galenframework.parser.ExpectColorRanges.parseColor;
import static com.galenframework.parser.ExpectColorRanges.parseColorClassifier;
import static com.galenframework.parser.ExpectColorRanges.parseGradientClassifier;
import static java.util.Collections.singletonList;

public class SpecImageProcessor implements SpecProcessor { public class SpecImageProcessor implements SpecProcessor {
@Override @Override
public Spec process(StringCharReader reader, String contextPath) { public Spec process(StringCharReader reader, String contextPath) {
Expand Down Expand Up @@ -116,44 +123,80 @@ private ImageFilter parseImageFilter(String filterText, String contextPath) {




if ("mask".equals(filterName)) { if ("mask".equals(filterName)) {
String imagePath = reader.getTheRest().trim(); return parseMaskFilter(contextPath, reader);
} else if ("replace-colors".equals(filterName)) {
return parseReplaceColorsFilter(reader);
} else {
return parseSimpleFilter(reader, filterName);
}
}


if (imagePath.isEmpty()) { private ImageFilter parseReplaceColorsFilter(StringCharReader reader) {
throw new SyntaxException("Mask filter image path is not defined"); List<ColorClassifier> classifiers = new LinkedList<>();
Color replaceColor = null;

boolean isCollectingClassifiers = true;

while (reader.hasMore()) {
String word = reader.readWord();
if (word.equals("with")) {
isCollectingClassifiers = false;
} else {
if (isCollectingClassifiers) {
classifiers.add(parseColorClassifier(word));
} else {
replaceColor = parseColor(word);
}
} }
}


String fullImagePath = imagePath; if (replaceColor == null) {
throw new SyntaxException("Replace color was not specified");
}
return new ReplaceColorsFilter(singletonList(new ReplaceColorsDefinition(replaceColor, classifiers)));
}


if (contextPath != null && !contextPath.isEmpty()) { private ImageFilter parseSimpleFilter(StringCharReader reader, String filterName) {
fullImagePath = contextPath + File.separator + imagePath; Double value = new ExpectNumber().read(reader);
} if ("contrast".equals(filterName)) {
try { return new ContrastFilter(value.intValue());
}
else if ("blur".equals(filterName)) {
return new BlurFilter(value.intValue());
}
else if ("denoise".equals(filterName)) {
return new DenoiseFilter(value.intValue());
}
else if ("saturation".equals(filterName)) {
return new SaturationFilter(value.intValue());
}
else if ("quantinize".equals(filterName)) {
return new QuantinizeFilter(value.intValue());
} else {
throw new SyntaxException("Unknown image filter: " + filterName);
}
}


InputStream stream = GalenUtils.findMandatoryFileOrResourceAsStream(fullImagePath); private ImageFilter parseMaskFilter(String contextPath, StringCharReader reader) {
String imagePath = reader.getTheRest().trim();


return new MaskFilter(new ImageHandler(Rainbow4J.loadImage(stream))); if (imagePath.isEmpty()) {
} catch (IOException exception) { throw new SyntaxException("Mask filter image path is not defined");
throw new SyntaxException("Couldn't load " + fullImagePath, exception); }
}
} else { String fullImagePath = imagePath;
Double value = new ExpectNumber().read(reader);
if ("contrast".equals(filterName)) { if (contextPath != null && !contextPath.isEmpty()) {
return new ContrastFilter(value.intValue()); fullImagePath = contextPath + File.separator + imagePath;
} }
else if ("blur".equals(filterName)) { try {
return new BlurFilter(value.intValue());
} InputStream stream = GalenUtils.findMandatoryFileOrResourceAsStream(fullImagePath);
else if ("denoise".equals(filterName)) {
return new DenoiseFilter(value.intValue()); return new MaskFilter(new ImageHandler(Rainbow4J.loadImage(stream)));
} } catch (IOException exception) {
else if ("saturation".equals(filterName)) { throw new SyntaxException("Couldn't load " + fullImagePath, exception);
return new SaturationFilter(value.intValue());
}
else if ("quantinize".equals(filterName)) {
return new QuantinizeFilter(value.intValue());
}
} }
throw new SyntaxException("Unknown image filter: " + filterName);
} }


private Rect parseRect(String text) { private Rect parseRect(String text) {
Expand Down
Expand Up @@ -23,9 +23,7 @@
import static com.galenframework.specs.Side.TOP; import static com.galenframework.specs.Side.TOP;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.*;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;


import java.awt.*; import java.awt.*;
import java.io.IOException; import java.io.IOException;
Expand All @@ -36,7 +34,7 @@


import com.galenframework.rainbow4j.colorscheme.GradientColorClassifier; import com.galenframework.rainbow4j.colorscheme.GradientColorClassifier;
import com.galenframework.rainbow4j.colorscheme.SimpleColorClassifier; import com.galenframework.rainbow4j.colorscheme.SimpleColorClassifier;
import com.galenframework.rainbow4j.filters.MaskFilter; import com.galenframework.rainbow4j.filters.*;
import com.galenframework.specs.*; import com.galenframework.specs.*;
import com.galenframework.specs.colors.ColorRange; import com.galenframework.specs.colors.ColorRange;
import junit.framework.Assert; import junit.framework.Assert;
Expand All @@ -45,9 +43,6 @@
import com.galenframework.parser.SyntaxException; import com.galenframework.parser.SyntaxException;
import com.galenframework.speclang2.specs.SpecReader; import com.galenframework.speclang2.specs.SpecReader;


import com.galenframework.rainbow4j.filters.BlurFilter;
import com.galenframework.rainbow4j.filters.DenoiseFilter;
import com.galenframework.rainbow4j.filters.SaturationFilter;
import org.hamcrest.Matchers; import org.hamcrest.Matchers;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterMethod;
Expand Down Expand Up @@ -1095,6 +1090,33 @@ public void shouldReadSpec_image_toleranceAndErrorRate_fromConfig() throws IOExc
System.getProperties().remove("galen.spec.image.error"); System.getProperties().remove("galen.spec.image.error");
} }


@Test
public void shouldReadSpec_image_replaceColors() throws IOException {
SpecImage specImage = (SpecImage) readSpec("image file image.png, filter replace-colors #000-#333 #f0f0f0 #a0a0a0-#a0b0a0-#a0b0c0 with #111");

assertThat(specImage.getOriginalFilters().size(), is(1));
assertThat(specImage.getOriginalFilters().get(0), is(instanceOf(ReplaceColorsFilter.class)));

ReplaceColorsFilter filter = (ReplaceColorsFilter) specImage.getOriginalFilters().get(0);

assertThat(filter.getReplaceColorsDefinitions().size(), is(1));
ReplaceColorsDefinition replaceColorsDefinitions = filter.getReplaceColorsDefinitions().get(0);
assertThat(replaceColorsDefinitions.getReplaceColor(), is(new Color(17, 17, 17)));

assertThat(replaceColorsDefinitions.getColorClassifiers().size(), is(3));
assertThat(replaceColorsDefinitions.getColorClassifiers().get(0), instanceOf(GradientColorClassifier.class));
GradientColorClassifier gradient = (GradientColorClassifier) replaceColorsDefinitions.getColorClassifiers().get(0);
assertThat(gradient.getName(), is("#000-#333"));

assertThat(replaceColorsDefinitions.getColorClassifiers().get(1), instanceOf(SimpleColorClassifier.class));
SimpleColorClassifier simple = (SimpleColorClassifier) replaceColorsDefinitions.getColorClassifiers().get(1);
assertThat(simple.getName(), is("#f0f0f0"));

assertThat(replaceColorsDefinitions.getColorClassifiers().get(2), instanceOf(GradientColorClassifier.class));
gradient = (GradientColorClassifier) replaceColorsDefinitions.getColorClassifiers().get(2);
assertThat(gradient.getName(), is("#a0a0a0-#a0b0a0-#a0b0c0"));
}

@Test @Test
public void shouldReadSpec_component() throws IOException { public void shouldReadSpec_component() throws IOException {
SpecComponent spec = (SpecComponent)readSpec("component some.spec"); SpecComponent spec = (SpecComponent)readSpec("component some.spec");
Expand Down

0 comments on commit 271afad

Please sign in to comment.