Here are few of the screenshots of the application.
Comments, Suggestions and Criticisms welcome 😀
Here are few of the screenshots of the application.
Comments, Suggestions and Criticisms welcome 😀
Being selected as a GSOC student is one of the best thing that has happened to me in life. Not only being selected, but selected as a student learning under the two most admired people by me i.e. Mathieu Virbel and Thomas Hansen was the reason for my double joy. I thought that being a GSOC student will benefit me in getting a better job in the future. Man was I surprised as I progressed through the programme. So in this blogpost I will be summarizing how I learnt new things, altered my previous plans, made new plans to adjust to the schedule.
Phase 1 (Till Midterms)
This OO based programming was pretty new to me. Plus NUIPaint is my first actual application that I have coded. So I had very little idea how to start and where to start? So I set out building the UI as I provided the Mock-ups. But little did I know starting with UI is not a good way of software engineering. Mathieu suggested that I start building pymt widgets first and then integrate them one after another. So this was lesson number one for me “Modular Coding => Better Structure and better to handle”.
In my first phase I built several UI widgets, they are as follows
Descriptions of some of these and how I created them, I have already posted in my previous blogs.
With these widgets plus a simple implementation of layering system, I closed the Phase 1 of the project. So in the next phase I decided to integrate all these and focus on building the application aspect of the project.
Phase 2 (Post Midterms):
So I passed the midterms with the blessings from my mentorsJ, in this phase I wanted to focus more on the application aspects like building the layering system, GLSL filters, Natural Colour Mixing, smudging, windowing, cut/copy/paste and others.
One more important feature I have implemented in layering is Layer ordering using gestures. Double tapping on a Layer takes it one level higher than its neighbour. Similarly holding one finger on the layer and double tapping on the same layer with another finger takes it one level lower.
The sheer size of this project was overlooked by me during the initial proposal writing phase and there are several other aspects like focusing on development of reusable widgets for PyMT lead me to have shortage of time. But I’m very keen on continuing this project even after the GSOC, and take it to the next iteration and make it a truly complete pymt app.
As for my satisfaction about this Project. It’s been a really great experience for me, I have learned some really high technical stuff, I feel that now I have a better understanding about how the software engineering process works. And of course I really thank my Gurus(mentors) for teaching me and always being there to answer my questions and clear my doubt.
In my next blog post i’ll post a series of Screenshot of how NUIPaint looks as of now. Cheers!
One thing which really fascinated me from really long is use of Pixel shaders to do interesting things in OpenGL. I’ve been trying to decipher the mystery of GLSL from a long time now, this interest in GPU based computation was sparked especially from Thomas’s Example apps in the PyMT trunk( Mandelbrot and Shadowing in Pictures example), although I never understood how it works back then (or might be because I never put much effort in understanding it).
GL Shading Language is a extension to OpenGL using which we can directly compute pixel and graphics on the GPU instead of the CPU. This provides us with tremendous performance benifits since pixel transformations run in parallel. The scope of Pixel shaders is amazing, some of us sometimes dont know how they achieve those stunning effects in latest computer games. Most of the effects like
are all done utilizing the pixel shader capabilities of your graphics card. So I started out by searching some tutorials on the net and there are several good references that i found out.
GLSL is all about pixel manipulation, usually involving usage of neighboring pixel colors, distance etc etc. Its mathematics. But there are a lot of free GLSL code available online using which you can learn and implement your won shaders.
Once I learnt the basics of GLSL, I decided to put effort to further learn this technology and implement it in NUIPaint as filters. I found out that some common filters like Gaussian Blur, Sharpening, Embossing etc belong to a common group of shaders called as Convolutions Filters. These vary only by a single matrix called as Convolution Matrix. Its very interesting, for more details please check this link http://www.ozone3d.net/tutorials/image_filtering.php .
I implemented a separate class called Filters which will later be added into PyMT core. This class has several functions which take in texture as input, apply GLSL filters to it and return the transformed textures back. In total i implement 7 kinds of filters
Here is a set of screenshots of the Filtered images.
It works much faster than regular CPU based filters like the ones in Python Imaging Library. If you want to use the glsl filters then here is the link to the source code, each filters vertex and fragment shaders are in separate functions, so you can easily use it in your programs. If you want to use the Filter class into your software then wait for the induction of the class into PyMT core soon 🙂
When discussing with Mathieu Virbel about the possibilities of implementing layering system in NUIPaint, he introduced me to this world of Design patterns. He gave this Wikipedia link and asked me to identify the pattern which is similar to the layer system I thought about. Even though I had a idea about implementing layering system, I failed to identify the right pattern. He then directed me to this pattern called Facade.
Voila its was very similar to the structure I had in my mind. Then I realized how important it is to learn this important concept of Design Patterns eventhough I had heard the name in college 😛 I had never given much interest to it. Now I realise its potential.
So i planned to implement three main classes.
This method of using layer manager as facade works pretty well. Next problem was to create a UI for accessing the Layer Manager features like creation of layers, deletion of layers and even handling layer sorting. So I implemented a new class called LayerList Manager. This class provides UI to create new layers, delete multiple layers in a form of kinetic scrolling list.
Below is a UML class diagram of the Layering system that I did
I really thank my bro Prashanth Patali and Mathieu for all the guidance they gave me in correcting this UML Diagrams, I’m now confident enough to draw the UML’s 🙂
Sorry for the delayed blog post, I’ve been busy shifting our house and getting adjusted to the environment here. First of all I would like to say that i passed the mid terms. Now im coding for the next milestone, The Final Evaluation. I will be writing about a report about my mid terms and a complete blogpost on Layering system that I implemented, how my mentor Matheiu showed me ideas to think in terms of software engineering. He guided me about using Design Patterns for layering system. Stay tuned for that blog 🙂
It’s been long since I last posted about my GSOC work, so today I’ll be writing about how I achieved the color picker. There are several points that comes to the mind when we thing about the colorpicker.
There is a humongous list of resources available for Color pickers especially AJAX based, but my problem was different, I wanted a Quarter Circle Color Picker 🙂 , nowhere in the internet did i find one single open-source quarter circle color pickers, but hey no pain no gain :), so I set out to create a Opengl rendered quarter circle color picker with algorithmic based color picking.
1. Rendering the Gradient Circle
So my first goal was to create a opengl rendered quarter circle, well its very easy to generate a single color circles in opengl like the ones that I have used in my previous widgets, Rendering a gradient one is a very hard task. I know that opengl allows to blend colors by specifying different colors at different vertices of a polygon, but how can one do the same in a circle ?!!, circle has no vertex edges.
I did not find any way to get around this problem using Circle render, so the alternative solution was to render thin triangles and arrange it in the form of a fan, and when i looked around the net for this one, to my surprise there was one opening call to make such a polygon using triangle fan.
def drawPartialCircle(pos=(0,0), radius=100): with gx_begin(GL_TRIANGLE_FAN): glColor3f(0,0,1) glVertex2f(0,0) for angle in range (90,185,5): glColor3f(sin(radians(angle-90))*sqrt(2),cos(radians(angle-90))*sqrt(2),0) glVertex2f(int(cos(radians(angle))*radius),int(sin(radians(angle))*radius))
So in the above algorithm i’ve chosen the angle range from 90 to 185 because i want it to appear at the bottom right corner. So what the algoritm does it,
If you have any queries regarding this algo, feel free to comment.
2. Calculating color at the touch point
I used the similar sine cos formula to calculate the RGB values, The R and G values varies according to the angle made by the line joining the center and the touch point with the horizontal line. Whereas the blue value is a function of the distance touch point from the center. So here goes the algorithm
def calculate_color(self): b = 1-self.point_distance/self.size r = (sin(radians(self.point_angle))-b)*sqrt(2) g = (cos(radians(self.point_angle))-b)*sqrt(2)
where self.size is the radius of the circle.
3. Hue and Saturation
As you can see in the rendered quarter circle above there is no range of black nor white, so this posed a new challenge to use a slider to make a hue saturation variation, HSV[Hue, Saturation, Value] is an alernative representation of RGB color space, something similar to Rectangular to Polar coordinates conversion.
Since I need to vary the color from White>>Color>>Black, the variation has to be done in two steps
Thomas (My mentor) pointed me to this really nifty function in core python rgb_to_hsv and hsv_to_rgb , which converts between the colorspaces with ease. So I divide the slider into two portions lower limit to middle value for saturation, middle value to upper limit for Value. I chose to take 2 as the maximum range of the slider, so it varies from 0 to 2, and middle i get 1. I developed the following algorithm.
value = rgb_to_hsv(self.slider.slider_color,self.slider.slider_color,self.slider.slider_color)
h,s,v = value,value,value
if self.slider._value <= 1.0: s = self.slider._value else: v = 2-self.slider._value self.slider.slider_color = hsv_to_rgb(h,s,v) [/sourcecode] Overall this entire widget was very complex to build, but I got to learn alot from this tiny project. If you have queries regarding any of the algorithm that I developed, or if you have suggestions of better algorithm, or anything at all feel free to comment :), it will definitely help me make this project better
At first I thought it would be very simple to code a circular menu, as there was already a scatterwidget in pymt which would rotate on a gesture, I can shut of translation and scaling gesture and make a simple circular menu out of it, but then how does a rotation work ? well you need two points to rotate a scatter widget to find the angle of rotation, so using a scatterwidget was ruled out.
So i started with a sketch book, and started deciding how my Circular Menu should work and look. Here are the few pointers I noted down
I started with the angle calculation. I thought of the following logical algorithm
The angle calculation can be easily done using pymt’s awesome Vector class, tito showed me how I can use it to do alot of vector calculations which really simplies most of the things i want to do like angle calculation, before using Vector class I intially wrote my own angle calculation code using trignometrics 😛 .
Next problem was to arrange the widgets on the circumference. I remembered from my Highschool Trigonometrics that we can find the point on the circumference of a circle given a angle theta using the formula
P(x,y) = (radius*cos(theta), radius*sin(theta))
This worked brilliantly. It arranged the widgets around the Widget in a circular manner, and this would rotate the icons along with the widget. Here is the screenshot of the final widget and here is the final code.