Computer Graphics Project #1 Image Processing and Editing
This project is maintained by debowin
Command Line Image Editor
A small number of starter images are included with the code, but you can find more in your personal collection or online (https://www.google.com/imghp). The images you use must be one of the supported formats (.bmp, .jpg/.jpeg, .png, .tga).
Original Mangekyō Sharingan | Mangekyō Sharingan++ |
---|---|
Original | Kamui |
---|---|
The program runs on the command line and performs operation in the order that they appear in the arguments. For example, to increase the brightness of the image in.bmp by 10%, and save the result in the image out.bmp, you would type:
image -input in.bmp -brightness 1.1 -output out.bmp
Notice the input parameter must appear first. Remember, everything happens in the order specified. First the input, then the brightness change, then the writing to the specified output file.
For several of the filters, there is more than one corresponding argument. To see the complete list of options, type:
image –help
Usage: image -input <filename> [-option [arg ...] ...] -output <filename>
-help
-input <file>
-output <file>
-noise <factor>
-brightness <factor>
-contrast <factor>
-saturation <factor>
-crop <x> <y> <width> <height>
-extractChannel <channel no>
-quantize <nbits>
-randomDither <nbits>
-blur <maskSize>
-sharpen <maskSize>
-edgeDetect
-orderedDither <nbits>
-FloydSteinbergDither <nbits>
-scale <sx> <sy>
-rotate <angle>
-fun
-sampling <method no>
If you specify more than one option, the options are processed in the order that they are encountered. For example,
image -input in.bmp -contrast 0.8 -scale 0.5 0.5 –output out.bmp
would first decrease the contrast of the input image by 20%, and then scale down the result by 50% in both x and y directions. It is also possible to specify -output multiple times, to save out intermediate results:
image -input in.bmp -blur 5 -output blurred.bmp -edgeDetect -output edges.bmp -rotate 30 -output allCombined.bmp
Image CPP File here.
Image Executable File here.
Original | Brigther (1.5) | Darker (0.5) |
---|---|---|
Original | High Contrast (1.5) | Low Contrast (0.5) | Negative Contrast (-1) |
---|---|---|---|
Original | High Saturation (2) | Low Saturation (0.5) | Negative Saturation (-1) |
---|---|---|---|
Original | More Noise (0.75) | Less Noise (0.25) |
---|---|---|
Original | Extract Green (1) |
---|---|
Original | Cropped (243 281 252 104) |
---|---|
Original | Quantize (2) |
---|---|
Original | Random Dithered (2) |
---|---|
Original | Ordered Dithered (2) |
---|---|
Original | Floyd Steinberg Dithered (2) |
---|---|
Original | Blurred (7) |
---|---|
Original | Sharpened (11) |
---|---|
Original | Edge Detections |
---|---|
Original | Scale (2 3) |
---|---|
Original | Sampling (0) |
---|---|
with Scale (0.25 0.40)
Original | Sampling (1) |
---|---|
with Scale (0.25 0.40)
Original | Sampling (2) |
---|---|
with Scale (0.25 0.40)
Original | Rotate (30) | Rotate (150) |
---|---|---|
Original | Swirl |
---|---|
Original | Combined Filter |
---|---|
image -input fruitsplus.jpg -blur 5 -contrast 1.5 -sampling 2 -rotate 30 -fun -randomDither 2 -output allCombined.png
Random Dither - I wasn’t sure how to apply it for arbitrary bit depth so I broke the current bit depth into Most Significant and Least Significant portions and generated a random number between 0 and the LSB’s maximum value. Then I checked if this number was less than or greater than the Least Significant portion. If it was lesser, I increased the value of the Most Significant portion by one to retain in my new bit depth representation.
Quantization - Taking remainders and quotients the regular way was making the code look dirty and unintelligible so I moved to bit-wise arithmetic for rounding operations.
Brightness Reduction - Had to reset the alpha value to pixel’s original value because pixel arithmetic in case of a <1 factor was reducing it, leading to a translucent image.
Random Noise - In this case, I used a Noise Pixel with random values between -256 and 256 instead of 0 to 256 so that the noisy image doesn’t become too bright.
Blur - I created a generic Gaussian1D kernel creator function that can be used to create a kernel of any size. I also used a variable sigma = size/2 to make the blurring even smoother for higher values of n. I used this to apply blurring two times, once for each dimension.
Edge Detection - Read about the Sobel Filter that has impressive edge detection. Used a 3x3 Sobel Filter after darkening the image and scaling it down and back up for being able to detect larger and darker edges. (more prominent ones)
Rotation - Was unable to get it to rotate it in place till I realized that I needed to add the center coordinates to each pixel’s old coordinates(u, v) when we were inverse mapping.
Fun - Realizing the trick about rotation got me thinking towards a differential spinning warp. So I came up with two approaches to rotate pixels differently. One twists them more the farther from the center they are, and one that does the opposite. Finally, I decided to go with the latter for which I had to take care of the division by zero in case of the middle pixel i.e radius = 0 by adding a tiny value to the square-root. I also had to do a memcpy to copy my result Image to the original Image since I was forced by the header file to use a void return type for the fun function and we were only allowed to change the image.cpp file.
Sampling - For bilinear interpolation, it took me some time to arrive at the idea of chaining the interpolations for the upper and lower neighboring pixels. For Gaussian sampling, I realized I couldn’t use a kernel after repeated failures of trying to do so. To this end, I wrote a utility function that gives the value of the gaussian term for any x and y and sigma and used it for convolution.