Tag: Programming

  • 6 Signs of Over-Engineering

     

    tangled mess
    Credit: Flickr / Martin LaBar

    Sub parts of the Thing are described as “shared” or “reusable”… but no-one else is using them.

    The Thing has lots of unit tests, but few (or no) integration tests because they are so much harder to write.

    No one can explain clearly what the Thing does, because the generalised use case has obfuscated the actual problem it was originally supposed to solve.

    It would be helpful to see a UML diagram of the Thing, because no one can even begin to map the dependencies in their head. Or on paper.

    More time is spent worrying about elaborate corner cases than use cases.

    The word “framework”.

  • My Completely Unscientific GitHub Survey

    I was a software engineer without a GitHub account. I know, shocking, because everyone is supposed to have one – and actually the reason why I had to get resulted in me receiving a set of questions which assumed I would have a GitHub account, but Twitter account was optional.

    I didn’t have a GitHub account because I had never felt any need for one, and my reaction to needing one was slight panic, because I had this impression that it was a space where women got harassed. Of course, this is a statement that could be applied to The Internet in general, and I Internet a lot. Or Twitter, and I tweet a lot. But those things I would feel a sense of loss to do without.

    Also, I really had my fill of men patronising me and assuming I didn’t know what I was talking about during University, and it’s not like this experience has stopped since then. I don’t need to put myself in a position for men to make me feel like I shouldn’t be an engineer. The voice in my head is doing a perfectly adequate job, and does not need a chorus line.

    Anyway, I thought about why I had GitHub pegged as a Bad Space, and I came up with three main things:

    And so I tweeted.

    I have to get a github account. I've so far avoided it in part as my impression is that it's a place where women are harassed. Am I wrong?

    Pleased to say that I got replies from 6 women saying that their experience has been fine.

    Which is obviously completely unscientific, and not a representative sample. But it was enough to quash the feeling of dread I had. So hey, now I have a GitHub account.

  • My Inspiration App: App Concept

    Rules of being creative #7
    Credit: deviantArt / BlackLuna

    My app idea – a place to collect things that inspire, that can be found searching their tags, location, or type. I understand that people can and do use any number of other apps for this – Twitter favourites, for example, this is just supposed to be a purely happy and motivating place on our most intimate device – the phone.

    This has probably done elsewhere (I haven’t looked) but fulfils certain requirements that make it (I think) a good first project.

    Why This Project

    • Tapping into share intent. I like the idea of an app being an expansion pack for other apps – something that is possible on Android, but not so much on iOS. I want to build the kind of app that I could only build on Android.
    • Visually minimal, content is king. I care a lot about how things look, but have pretty minimal UX skills myself. Therefore, less UX the better.

    Components to Figure Out

    • Storage. Inspirations need to be stored (offline experience – do not plan on starting with a server) and searchable by tags (although ideally free text search on associated notes, too).
    • Subscribe. This is the initial way in for data, subscribe to the share intent and find ways to extract different kind of content – images, text (snippets, web pages, emails), people, places. Are there other intents that I want to subscribe to? Also need to be able to create something without an intent – just a note to self, or comment in conversation.
    • Sync. I’m not initially aiming to have a server and sync across devices (nice add on, though, if this project keeps interesting me), but I don’t want all data to be lost when the user gets a new phone. I think I can use the standard backup for this, but I am not sure – need to investigate.
    • Display. Obvious – if the user can’t see it, whatever data is there doesn’t matter. I want users to be able to look for tags, or just a random “I feel low, inspire me!”.
  • Getting Set Up on Android

    I used the event Programming Languages I’ve Been Meaning To Try But Haven’t Gotten Around To Yet at the Stripe offices (organised by Star Simpson) in San Francisco to get going on Android.

    Aside – I love the concept of this event. Great opportunity to hang out with your laptop, the only goal being to suck less at something by the end of the day. I would love to do this every month. Lots of women about, which was great! And I loved the Stripe offices – they have real Dr Pepper!

    I think I was in the spirit rather than the actual definition of the event because I’m familiar with Java (I even have readability in the kind written at work). And actually I’ve been doing some Android programming, but what I haven’t done – but want to – is write an Android app from scratch. I plan to do a bunch of posts on my experiences, from application concept to… however far I get.

    I started by downloading the SDK bundle – this comes with Eclipse and is all set up and ready to go. Really easy!

    Then I went through the Building Your First app tutorial, I made the default list-detail view and got it running on the emulator and my phone (much faster than the emulator).

    Then I gave Android Studio a go, as one of my friends said it was a lot faster.

    I just imported the existing project from Eclipse (even though it didn’t really do anything). Again, I got it running on the emulator (still slow) and the device (not noticeably faster than from Eclipse).

    I’m not completely sure which one to use, I’m used to Eclipse but Android Studio seems pretty easy. I think it should be be fine to switch between them though, so I will give Android Studio a go for a while.

    Some Gotcha’s

    • Don’t forget to start the Android emulator before trying to run your application.
    • Getting to Developer mode on a physical Android requires going to settings, about phone, and then tapping “build number” until it says “you are now a developer” – 7 times. You’ll then probably want to turn on USB debugging in the Developer Options menu that appears in settings.
    • I set a high minimum version to make things easier (didn’t matter in this, but will later when I’m making my actual app) – make sure your device is meeting this! I hadn’t used that Android in a while, so the OS was out of date.

     

  • More Experiments Around RGB Averaging

    I decided to replicate the showing/hiding the dominant hues in images with showing/hiding around the average RGB values instead.

    I created a class called RGBColor (just holds red, green, and blue values), similar to the one I created called HSBColor. I could have used the java.awt.Color class, but that insists on a range of 0-1 for the values, and I wanted to avoid conversions between that and the 0-255 that Processing uses by default. Or, better, allow me to set the colorMode to be in range 1-100, so that my tolerances were percentages – I found this made it easier to pick good values there.

    Images Showing Colors Around “Average” RGB

    Images Hiding Colors Around “Average” RGB

    Source Code

    package ui;
    
    import model.RGBColor;
    import color.ColorHelper;
    import processing.core.PApplet;
    import processing.core.PImage;
    
    @SuppressWarnings("serial")
    public class AverageRGBImageViewApplet extends PApplet {
    
    	PImage img;
    	static final int rgbTolerance = 50;  // Adjust this.
    
    	public void setup() {
    		size(640,480);
    		background(0);
    		img = loadImage(/* Your image file here */);
    		colorMode(RGB, 100);
    		processImage();
    	}
    
    	public void draw() {
    		image(img, 0, 0, 640, 480);
    	}
    
    	private void processImage() {
    		RGBColor color = ColorHelper.rgbColorFromImage(img, this);
    
    		for (int i = 0; i < img.pixels.length; i++) {
    			int pixel = img.pixels[i];
    			RGBColor pxColor =
    				new RGBColor(red(pixel), green(pixel), blue(pixel));
    			// Adjust this conditional to show/hide around average rgb.
    			if (!rgbInRange(color, pxColor, rgbTolerance)) {
    				float brightness = brightness(pixel);
    				img.pixels[i] = color(brightness);
    			}
    		}
    	}
    
    	private boolean rgbInRange(RGBColor colorA, RGBColor colorB, int tolerance) {
    		return Math.abs(colorA.r - colorB.r) < tolerance &&
    			Math.abs(colorA.g - colorB.g) < tolerance &&
    			Math.abs(colorA.b - colorB.b) < tolerance;
    	}
    }

    ColorHelper.java

    package color;
    
    import processing.core.PApplet;
    import processing.core.PImage;
    import model.RGBColor;
    
    public class ColorHelper {
    
    	public static RGBColor rgbColorFromImage(PImage img, PApplet applet) {
    		img.loadPixels();
    		int numberOfPixels = img.pixels.length;
    		float totalRed = 0f;
    		float totalGreen = 0f;
    		float totalBlue = 0f;
    
    		for (int i = 0; i < numberOfPixels; i++) {
    			int pixel = img.pixels[i];
    			totalRed += applet.red(pixel);
    			totalGreen += applet.green(pixel);
    			totalBlue += applet.blue(pixel);
    		}
    
    		// Calculate final rgb values.
    		float r = totalRed / numberOfPixels;
    		float g = totalGreen / numberOfPixels;
    		float b = totalBlue / numberOfPixels;
    		return new RGBColor(r, g, b);
    	}
    }
  • Eliminating the Dominant Hue from an Image

    I thought it would be interesting to invert the idea of showing only the dominant hue, and show everything but that instead. I used the exact same code, but inverted the if statement so:

    if (!hueInRange(hue, lower, upper))

    became

    if (hueInRange(hue, lower, upper))

    Effect is as follows, as with most of these, my favourite effect is on the painting – does it work better because it is a more studied use of color? I’m going to make something that will compare and contrast the effects, and allow me to loop through pictures so I can look for interesting results.

  • Folders of Images, Compare and Contrast

    Now I’ve experimented with things, I wanted to make something that would allow me to compare different effects on the same photo, and loop through a folder of pictures looking for nice effects.

    I overrode mousePressed() to change the image on click.

    The big challenge here was running out of Java Heap space once I had more than one image being processed – most of the images are around 2MB each. This meant I couldn’t just read in the image 3 times and manipulate it (or not manipulate it), and even drawing the original first then manipulating it meant I had two manipulated images. I tried a few things here, starting with just increasing the heap size, to no avail. Eventually what I did was resize the image down to the size I was going to display, and creating new images of that size, and then copying the pixels over.

    That resolved the issue, except when looping through the images and taking screenshots – I have no idea why this would affect things. For the most part, it worked fine though.

    It’s nice to compare the effects side-by-side, see the different bits that are highlighted, depending on the effect. Sometimes it just looks like the weather is completely different. I really love the night-time photos, and the effect that makes them black and white… apart from the lights. Including in this post my favourites and those I found most interesting.

    One suggestion I’ve had is to ignore pixels that are at extremes in saturation/brightness (i.e. close to black or white), but having looked at the effects on more images, I’m not convinced that is going to make things better.

     img 1
    img 2

    img 3
    img 4
    img 5
    img 6
    img 7
    img 8
    img 9
    img 10
    img 11
    img 12
    img 13
    img 14
    img 15
    img 16
    img 17
    img 18
    img 19
    img 20
    img 21
    img 22
    img 23
    img 24
    img 25
    img 26
    img 27
    img 28
    img 29
    img 30
    img 31
    img 32
    img 33
    img 34
    img 35
    img 36
    img 37
    img 38
    img 39
    img 40

    Source Code

    ColorHelper.java

    package color;
    
    import processing.core.PApplet;
    import processing.core.PImage;
    import model.HSBColor;
    
    public class ColorHelper {
    
    	public static HSBColor hsbColorFromImage(PImage img, PApplet applet, int hueRange) {
    		img.loadPixels();
    		int numberOfPixels = img.pixels.length;
    		int[] hues = new int[hueRange];
    		float[] saturations = new float[hueRange];
    		float[] brightnesses = new float[hueRange];
    
    		for (int i = 0; i < numberOfPixels; i++) {
    			int pixel = img.pixels[i];
    			int hue = Math.round(applet.hue(pixel));
    			float saturation = applet.saturation(pixel);
    			float brightness = applet.brightness(pixel);
    			hues[hue]++;
    			saturations[hue] += saturation;
    			brightnesses[hue] += brightness;
    		}
    
    		// Find the most common hue.
    		int hueCount = hues[0];
    		int hue = 0;
    		for (int i = 1; i < hues.length; i++) {
     			if (hues[i] > hueCount) {
    				hueCount = hues[i];
    				hue = i;
    			}
    		}
    
    		// Return the color to display.
    		float s = saturations[hue] / hueCount;
    		float b = brightnesses[hue] / hueCount;
    		return new HSBColor(hue, s, b);
    	}
    }

    CompareAndContrastHue.java

    package ui;
    
    import java.io.File;
    
    import color.ColorHelper;
    import model.HSBColor;
    import processing.core.PApplet;
    import processing.core.PImage;
    
    @SuppressWarnings("serial")
    public class CompareAndContrastHue extends PApplet {
    
    	int fileIndex = 0;
    	private String[] fileNames;
    	private static String filePath = "../data/images/";
    
    	static final int hueRange = 320;
    	static final int hueTolerance = 40;
    	private static final int imageWidth = 384;
    	private static final int imageHeight = 268;
    
    	public void setup() {
    		size(3*imageWidth, imageHeight);
    		background(0);
    		noLoop();
    		colorMode(HSB, hueRange - 1);
    		// Read in images.
    		File dir = new File(filePath);
    		fileNames = dir.list();
    		nextFileIndex();
    	}
    
    	public void draw() {
    		PImage img = loadImage(filePath + fileNames[fileIndex]);
    		img.loadPixels();
    		img.resize(imageWidth, imageHeight);
    		HSBColor color = ColorHelper.hsbColorFromImage(img, this, hueRange);
    		image(img, imageWidth, 0, imageWidth, imageHeight);
    
    		// Display image only showing dominant hue.
    		drawImage(createImage(imageWidth, imageHeight, HSB), img.pixels, color,
    				0, 0, imageWidth, imageHeight, false);
    
    		// Display image excluding dominant hue.
    		drawImage(createImage(imageWidth, imageHeight, HSB), img.pixels, color,
    				2 * imageWidth, 0, imageWidth, imageHeight, true);
    	}
    
    	public void mousePressed() {
    		nextFileIndex();
    		redraw();
    	}
    
    	private void drawImage(PImage img, int[] pixels, HSBColor color,
    			int x, int y, int width, int height, boolean showDominantHue) {
    		img.loadPixels();
    		// Manipulate photo, grayscale any pixel that isn't close to that hue.
    		for (int i = 0; i < img.pixels.length; i++) {
    			int pixel = pixels[i];
    			float hue = hue(pixel);
    			if (hueInRange(hue, color.h, hueTolerance) == showDominantHue) {
    				float brightness = brightness(pixel);
    				img.pixels[i] = color(brightness);
    			} else {
    				img.pixels[i] = pixel;
    			}
    		}
    		image(img, x, y, width, height);
    	}
    
    	private void nextFileIndex() {
    		while (true) {
    			fileIndex++;
    			if (fileIndex < fileNames.length) {
    				if (fileNames[fileIndex].toLowerCase().contains(".jpg")) {
    					break;
    				}
    			} else {
    				fileIndex = 0;
    			}
    		}
    	}
    
    	private static boolean hueInRange(float hueA, float hueB, int tolerance) {
    		return Math.abs(hueA - hueB) < tolerance;
    	}
    }
  • Visualising A Photo Series

    Whenever I’m scrolling through pictures I’ve taken, it seem like they are in sections – here’s when I was near the beach, he’s the park, the night sky and fireworks. I thought if you visualised the way that the dominant colors changed, patterns would emerge.

    I found the perfect layout for this, the sunflower layout, and then did nothing about it for… a long time. I claim the craziness of work and life. Also, I knew nothing about color, and had no idea how I would go about extracting the dominant color from an image.

    But I did some research and figured it out, the trick was working with hues rather than RGB values.

    And voila, here is another way to see the story of my trip to North Korea.

    Sunflower Visualization from Photos Taken in North Korea
    Sunflower Visualization from Photos Taken in North Korea

    Maybe the main thing I can see from this experiment is that I don’t take as colorful photos as I like to imagine I do. Also, that I took a lot of photos in North Korea (the major bottleneck to my blog posts about it).

    So I put together another collection of images – almost everything I’ve taken since mid-June aside from in North Korea, including the shipwreck, my trips to Tasmania, Queenstown (skiing!), Hong Kong, Tokyo and photos I’d taken around Sydney and visualised that with the result below.

    Sunflower visualization from photos taken between mid-June and late-August (aside from NK)
    Sunflower visualization from photos taken between mid-June and late-August (aside from NK)

    This is where I discovered that it doesn’t work well with panoramas (I had recently discovered the panorama feature on my iPhone and had taken a few, typically at 5-7MB in size) which threw an exception, because it was out of Java heap space. I’d need to make the code more efficient to process panoramas – for now, I just left them out.

    I’d like to add more to it, maybe clicking on an element in the layout could bring up the photo, with only the dominant color (with some tolerance) exposed. Maybe animate it with the image that’s being processed displayed alongside. I’d love to pull in my most recent pictures on Twitter and display them this way. I think, how many images are needed to create something cool looking may make that prohibitive, though. For now, I’m happy that I’ve got something working.

    Processing one image like this doesn’t take a noticeable amount of time, however this first (NK) one is made from 1048 images, and 2.26GB of data. On my 13″ Macbook pro… it takes a while.

    Note – I made an HSBColor class that just holds hue, saturation, and brightness.

     

    Source Code

     

    import java.io.File;
    
    import processing.core.PApplet;
    import processing.core.PImage;
    
    @SuppressWarnings("serial")
    public class SunflowerImages extends PApplet {
    
    	private static String filePath = "../data/nkimages/";
    	private String[] fileNames;
    
    	static final int hueRange = 320;
    	private static final int radius = 9;
    	private static final int scale = 7;
    
    	private static final double goldenangle = Math.PI * (3 - Math.sqrt(5));
    
    	private static final int wh = 500;
    
    	public void setup() {
    		size(wh, wh);
    		background(0);
    		noLoop();
    		colorMode(HSB, hueRange - 1);
    		// Read in images.
    		File dir = new File(filePath);
    		fileNames = dir.list();
    	}
    
    	public void draw() {
    		int n = 0;
    		double a = 0;
    
    		for (String file : fileNames) {
    			PImage img = loadImage(filePath + file);
    			if (img == null) {
    				continue;
    			}
    			print("processing image: " + file + "\n");
    
    			double h = Math.sqrt(n)*scale;
    			double x = wh/2 + Math.sin(a) * h;
    			double y = wh/2 + Math.cos(a) * h;
    
    			stroke(100);
    			HSBColor color = extractColorFromImage(img);
    			fill(color.h, color.s, color.b);
    			ellipse((float) x, (float) y, radius, radius);
    
    			a+=goldenangle;
    			n++;
    		}
    	}
    
    		private HSBColor extractColorFromImage(PImage img) {
    			img.loadPixels();
    			int numberOfPixels = img.pixels.length;
    			int[] hues = new int[hueRange];
    			float[] saturations = new float[hueRange];
    			float[] brightnesses = new float[hueRange];
    
    			for (int i = 0; i < numberOfPixels; i++) {
    				int pixel = img.pixels[i];
    				int hue = Math.round(hue(pixel));
    				float saturation = saturation(pixel);
    				float brightness = brightness(pixel);
    				hues[hue]++;
    				saturations[hue] += saturation;
    				brightnesses[hue] += brightness;
    			}
    
    			// Find the most common hue.
    			int hueCount = hues[0];
    			int hue = 0;
    			for (int i = 1; i < hues.length; i++) {
     				if (hues[i] > hueCount) {
    					hueCount = hues[i];
    					hue = i;
    				}
    			}
    
    			// Return the color to display.
    			float s = saturations[hue] / hueCount;
    			float b = brightnesses[hue] / hueCount;
    			return new HSBColor(hue, s, b);
    		}
    }
  • Showing Only the Dominant Hue In an Image

    Having extracted the dominant hue from the images, we can manipulate the image such that pixels that are not (or close to) the dominant hue are instead made grayscale.

    I converted to grayscale using the brightness of the image in the HSB. This worked really nicely.

    From my earlier experiments I decided on a hue range of 320 (320 buckets).

    I varied the tolerance (from 1 – 20) of how far away from the dominant hue we would show on the same four images, with varying results of aesthetic pleasingness. How dominant the dominant color in the image is really varies the effect. One of them, pretty much didn’t work at all until I hit a tolerance of about 55 – at which point, 1/3 of the spectrum.

    import processing.core.PApplet;
    import processing.core.PImage;
    
    @SuppressWarnings("serial")
    public class DominantHueImageViewApplet extends PApplet {
    
    	PImage img;
    	static final int hueRange = 320; 
    	static final int hueTolerance = 10;  // Adjust this.
    
    	public void setup() {
    		size(640,480);
    		background(0);
    		img = loadImage("" /* Your image goes here */);
    		colorMode(HSB, (hueRange - 1));
    		processImage();
    	}
    
    	public void draw() {
    		image(img, 0, 0, 640, 480);
    	}
    
    	private void processImage() {
    		img.loadPixels();
    		int numberOfPixels = img.pixels.length;
    		int[] hues = new int[hueRange];
    		float[] saturations = new float[hueRange];
    		float[] brightnesses = new float[hueRange];
    
    		for (int i = 0; i < numberOfPixels; i++) {
    			int pixel = img.pixels[i];
    			int hue = Math.round(hue(pixel));
    			float saturation = saturation(pixel);
    			float brightness = brightness(pixel);
    			hues[hue]++;
    			saturations[hue] += saturation;
    			brightnesses[hue] += brightness;
    		}
    
    		// Find the most common hue.
    		int hueCount = hues[0];
    		int dominantHue = 0;
    		for (int i = 1; i < hues.length; i++) {
     			if (hues[i] > hueCount) {
    				hueCount = hues[i];
    				dominantHue = i;
    			}
    		}
    
    		// Manipulate photo, grayscale any pixel that isn't close to that hue.
    		int lower = dominantHue - hueTolerance;
    		int upper = dominantHue + hueTolerance;
    		print("dominentHue" + dominantHue);
    		for (int i = 0; i < numberOfPixels; i++) {
    			int pixel = img.pixels[i];
    			float hue = hue(pixel);
    			if (!hueInRange(hue, lower, upper)) {
    				float brightness = brightness(pixel);
    				img.pixels[i] = color(brightness);
    			}
    		}
    	}
    
    	private static boolean hueInRange(float hue, int lower, int upper) {
    	        // Should compensate for it being circular here - can go around.
                    return hue < upper && hue > lower;
    	}
    }