Tuesday, 30 August 2011

My new shirt

After the summer holiday and some unfinished projects I am back with new articles. This one will touch a lighter topic than the previous ones: there will be less programming, and a bit more art :) But don't be afraid, the next article will be about a game I've made and which needs only some polishing now.

My girlfriend has bought some textile paint recently, six different colors in little buckets. It aroused my creative self, it made me want to do something with it - especially when I saw how beautiful images she painted on the clothes she was making. So I decided I would use that textile paint to make a nice shirt for myself.

The paint was given, I needed a light colored shirt to paint on, and a "good motive" that I would gladly wear. I found an old plain white shirt in my wardrobe, it was perfect for my needs. I like the style of the clothes that Cyberdog makes, so I browsed their site, found this design, and knew that I wanted to copy it:

I started to convert this image to include only the drawing. First I cut out the interesting part:

As you can see luckily the relief of the model girl did not distort the image considerably. My plan was to print this image to paper, then put it under the shirt, and follow the lines with my brush to get the best result. But before that I wanted to clear the background of the image to white. On the first hand it saves tint when printing, and on the other hand the image picture would be clearer under the textile. The white shirt is not fully transparent obviously, so I wanted to get rid of every misleading noise.

I was trying to somehow convert the grey-scale background to white, and leave the black shapes untouched. Converting to 2 color black-and-white was not a good solution, because the antialiased forms became too sharp, pixelized. I tried everything I could think of in Gimp, Photoshop, IrfanView, but I couldn't find a function or plugin that would do what I needed. Googling did not help either. I really did not want to clean it up by hand. At that point I thought that if I can not find a tool to solve my problem then I'll make one - I'm a programmer after all :)

So at first I collected my expectations concerning the new tool:
  • convert the grey background to white
  • leave the black shapes untouched
  • keep most of the edges antialiased
  • leave non-grey colours untouched (this was important because I was planning to convert other images which were coloured)

The hard thing is to decide if a grey pixel is part of the background or it is part of an antialiased edge. I used a threshold value to decide the problem: if the pixel is grey, and it's darker than the threshold then keep it's original color, otherwise make it white. I used an other threshold parameter to decide if a pixel is grey or it's another color: if the difference between the RGB components of the pixel was lower than the threshold, it was considered grey and dealt with as described previously, otherwise it was considered to be another color. Maybe there is a plugin/program which does roughly this and I just could not find it - I would be glad to hear about it.

The implementation is a short Python script. I used PySFML for loading, saving images and accessing their pixels. It is a bit overkill for this purpose, but I was already familiar with this library, it was easy to use, and it was already installed on my machine so I could start scripting immediately. I think the code will be easy to understand after the explanation:

from sfml import sf greyness = 20 lightness = 500 def convert(pixel): r = pixel.r g = pixel.g b = pixel.b if abs(r-g) + abs(r-b) + abs(g-b) < greyness and r+g+b > lightness : return sf.Color(255,255,255) else: return pixel img = sf.Image() img.LoadFromFile( 'input.png' ) w = img.GetWidth() h = img.GetHeight() for j in range(h): for i in range(w): pixel = img.GetPixel(i,j) img.SetPixel(i,j, convert(pixel)) img.SaveToFile( 'output.png' )

Here is the result of using the script on the previous image:

It's not "perfect", there are many grey pixels littered around in the background, but I was satisfied with the result, it's much better than the original after all. My expectations were more-or less accomplished, most of the background was converted to white, it was now economical to print and did not contain much distracting parts.

I printed the image in A4 size, realized it was too small, so printed it again on two A4 pages. I glued them together and onto a wooden panel. I put the whole stuff into the shirt and then smoothed and pinned the shirt onto it. The first A4 sized copy was good for reference. I covered a part of the floor with newspaper as a workplace, gathered the black paint, the brush, some test-cloth and a cushion for my knees - everything was ready to paint :)

I took some photos as I progressed:

I worked in two turns on two days, the whole process took about five hours. The paint was quite thick so I could only paint short dashes. When I finished painting I was tired as hell from kneeling on the ground for hours. My mind was tired too, since I had to concentrate hard to paint all those minute details as exactly as possible. But at the same time I was extremely satisfied and proud of my work, I haven't felt similarly for a long time. When I started I didn't really believe I could make it. It was not finished yet (it needed ironing to fix the paint and I planned to cut the sleeves off), but I was through the hardest part.

Here is an image of the final product:

Ordering a shirt from Cyberdog would have been much less work. So was all this hard work worth it? Absolutely. I had much fun during the whole process; now I can enjoy the fruits of my work; and I have a nice shirt I can proudly wear, and tell everyone who asks about it that I made it myself with my two hands :)

This happens when fashion meets programming. I hope that this little multidisciplinar excursion was not too boring. As I have already said, next time I'll be back with a more hardcore topic.

P.S. I hope it's not a copyright infringement that I used the picture from Cyberdog.