**Deadline: May 31th, 23:55** ===== Introduction ===== Similar to the first assignment, we will perform some image manipulations. You do not need to have worked on the first assignment in order to work on this one, but you should read [[fp:assig-01|its statement]] to understand the basic ideas behind the image formats used. ===== Tasks (total 1p) ===== ===== 1. Common transformations (0.4p) ===== 1.1. **scaling (0.2p)** * Scaling takes two factors (vertical and horizontal) and produces a new image with dimensions equal to that of the original multiplied by the given factor; scaling an image with height ''h'' and width ''w'' with a vertical factor ''vf'' and an horizontal factor ''hf'' results in a new image with height ''h * vf'' and width ''w * hf''. * We will employ a very simple scaling method: * if a factor is greater than 1, we'll duplicate some lines/columns * if a factor is smaller than 1, we'll eliminate some lines/columns * To obtain a decent visual effect, you should envision that each element (column or line) ''i'' is associated with the value ''i * f'' (where ''f'' is the scaling factor). If this value is an integer, you should remove/duplicate the element * For example, with a vertical scaling factor of ''0.5'' you should remove every other line * With a vertical scaling factor of ''1.25'' you should duplicate every fourth line 1.2. **stamping (0.2p)** * We want to paste a small version of an image on top of another one * Your function takes a target image, a stamp image, the coordinates of the stamp's top-left corner and a scaling factor (hint: you should apply ''scale'' on it) * For example, the result of stamping the second image on the first one at coordinates ''(240, 180)'' with scaling factor ''(0.3, 0.3)'': {{:fp:stampex.png|}} ===== 2. Type-specific transformations (0.6p) ===== 2.1 **superimposition (0.15p)** * Superimposing an image on top of another with a transparency factor ''alpha'' (between ''0'' and ''1'') means combining the values of each corresponding pixel pairs using weights ''alpha'' and (1 - ''alpha'') * For example, the result of superimposing the second image on top of the first with a transparency factor of 0.3 is: {{:fp:superimposeex.png?750|}} 2.2 **contrast (0.15p)** * We want to adjust the contrast of an image with a contrast factor. * You can use the algorithm presented [[https://www.dfstudios.co.uk/articles/programming/image-programming-algorithms/image-processing-algorithms-part-5-contrast-adjustment/|here]]: given a contrast level ''c'', you first calculate a correction factor: $math[f = \frac{259\cdot(c + 255)}{255\cdot(259 - c)}]; then, for each pixel you change its color value to $math[f\cdot(oldValue - 128) + 128] (for RGB images, you need to this on all three color channels). * Also make sure that all resulting new values are in the range 0-255! 2.3 **bordering (0.15p)** * Add a solid border with a given thickness around the image, on each side * The color of the border should be the average color of the image (so you need to calculate that first) 2.4 **blur (0.15p)** * We will implement the simplest form of blurring: each new pixel will be the arithmetic mean of the original pixel and the pixel directly below it. * For the last line, for which there are no pixels below, you can use any of these approaches: * leave it as is * consider a "dummy" line of all 0s below it For all the tasks listed above you **do not** need to implement any sanity check on the inputs; you can safely assume all inputs are valid. For example, you can assume that all lists of lists you work with are valid two-dimensional matrices (no line is longer or shorter than the others); all color values are between 0 and 255; for superimposing, the images are the same size etc. You can download the starting code {{:fp:helpercode2.zip|here}}. Unpack the archive and look in the folder ''skel/''. Write the implementations in the files ''Common.hs'', ''Greyscale.hs'' and ''Color.hs''; the function types are already provided. You can ignore all the other haskell source files in that folder, they are only needed if you intend to test it on real ''Netpbm'' images. For the transformations provided, the specific implementation techniques presented are suggestions; if you wish to use algorithms with greater complexity but better results (e.g. for scaling, blur), feel free to do so. ==== Mixing integers and floating numbers ==== Much like Java (and unlike C), the type-system in Haskell is very strict and does not allow mixing integers and floating points numbers in a single operation (such as adding an ''Int'' and a ''Float'' together). In order to get around this, you need to use explicit casts: * ''fromIntegral'' takes an integer and returns a number suitable for operations with a floating point number; for example if ''x :: Int'' and ''y :: Int'', you can perform ''fromIntegral x * y'' * ''round'', ''floor'', ''ceiling'' - these functions convert a floating point number ''y'' back to an integer; ''floor'' gives the greatest integer smaller than ''y''; ''ceiling'' results gives the smallest integer greater than ''y''; ''round'' gives the nearest integer in any direction ==== Usage ==== To run the provided helper code and test your functionality, you first need to select which function you want to test out. For that, you need to edit one or two lines in the file ''Main.hs''. * for single image transformations, edit line 13. The following example will configure it to scale an image with a vertical factor of 2 and an horizontal factor of 0.3: * myTransform img = scale (2, 0.3) img * for transformations that require two images, line 16 is relevant. The following example will configure it to stamp a pciture scaled with a vertical and horizontal factor of 0.3, at coordinates 260, 140: * myTransform2 img1 img2 = stamp (260, 140) (0.3, 0.3) img1 img2 After having edited ''Main.hs'' you can run it; depending on the number of arguments, it will choose an appropriate type of transformation (single/multiple image); it also correctly chooses between greyscale/RGB functions based on the actual filetype. To run the file you need the ''runhaskell'' binary (or ''runghc''; both should come with the haskell platform), then run it from a shell: # Runs the single-image transformation set on line 13 on the image in file "./input.ppm"; the result is written to "./out.ppm". runhaskell Main.sh ./input.ppm ./out.ppm # Runs the mask transformation set on line 16 on the images in files "./input1.ppm" and "./input2.ppm"; the result is written to "./out.ppm". runhaskell Main.hs ./image1.ppm ./image2.ppm ./out.ppm The folder ''res/'' contains several greyscale and RGB images. ==== Scoring ==== The assignment is worth 1 point; 0.4p for the common transformations; 0.3p for greyscale and 0.3p for RGB. ==== Assignment 1 redo ==== You can also send any (and even //all//) tasks from the first assignment that you didn't manage to solve in time, for half the points. So if you did not submit anything for the first assignment and you now submit a complete solution, you will receive 0.5 points. If you do so, please specify this in the README. ==== Submission ==== For submitting you should create a zip archive of the three files you modified: ''Common.hs'', ''Greyscale.hs'' and ''Color.hs'' and a ''README''. The ''README'' should contain a succinct high-level presentation of your work. The archive name should be ''LASTNAME_Firstname_FP_A1.zip'' (if you have multiple firstnames, separate them by an underline "_"). Upload the archive to [[https://curs.upb.ro/mod/assign/view.php?id=300279|the corresponding activity]] on moodle.