Skip to content

dandominicstaicu/Image_Editor_in_C

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

33 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Copyright 2023 311CA Dan-Dominic Staicu <dando.ds11@gmail.com>

~Hinds' Law Of Computer Programming~
~3. If a program is useless, it will have to be documented.~

IMAGE EDITOR
~Murphy's First Law:  Anything that can go wrong will go wrong.~

*This program was written in C and can edit photos in format NetPBM
*Works with a set of commands inputed from STDIN 
*Can read/write text (P2, P3) or binary (P5, P6) file formats 
*Has text inteface for transforming these photo files (only .pgm, .ppm)

It has the following functions implemented byh commands:


	%LOAD a photo as a matrix in memory; if LOAD was inputed, the program tries
to open the file with the given name/at the given path; 

*if the file doesn't exist, an error is printed at STDOUT; 

*if the file coud be opened, than the program reads photo's magic-word 
dimensions, and max value (already known to be 255 in our case, so it just
steps over it) while ignoring the comments;

*if the magic word describes a binary file (P5, P6), it uses fread in order to
interpret the values as ints; it pases 1 as size_t size and size_t nmemb in
order to interpret values written on only one byte as an int value;

*if the magic word describes a text file (P2, P3), it uses fscanf in order to 
read and save the pixels' values inside a matrix;

*if the photo is Black and White (P2, P5) it uses only one matrix in order to
memorise it

*if the photo is Color (P3, P6) it uses 3 matrixes in order to memorise each
color channel in a different matrix, keeping the same column (and line) count
for all of them; it's also easier to work with a pixel's neighbors

*if the process was executed succesfuly, a succes message is printed

	The complexity of LOAD command is O(col * lines)

	The loaded photo is saved in memory as a (struct) photo_t variable which
contains variables 
	*the type of photo (2, 3, 5, 6) as an int
	*for the number of lines and columns of the photo's matrix,
	*the coordinates of selection (top right and bottom left pixels' coords)
	*a double pointer to int in case the readen matrix will be Black and white,
	so it will need only one matrix
	*a rgb_t varbaile

	rgb_t is a struct defined as 3 double pointers to int (in order to use
	them for 3 matrixes, one for each color channel, in case the photo to be 
	loaded is color) 

	%SELECT an area inside a photo; if SELECT was inputed it expects 4 coords
in order to memorise 2 points which define the selected area inside the mat

If 4 ints were inputed the still need validation;

*if they are in the wrong order (eg. y1 > y2) they need to be swaped

*if no photo was loaded, an error message is displayed and no selection is done

*if the selected area isn't valid (because the interval is [x1, x2) ), an error
is printed (eg. if x1x == x2, selection isn't valid)

*if the coords are "outside the photo", an error is displayed

*if they are correct, we save them using the real selection size (y2 - 1,
x2 - 1), and a succes message is displayed

	SELECT can also expect the ALL parameter which means the selected area is
the whole photo (same as bottom y = column cnt - 1)

	The complexity of SELECT is O(1)

	Unfortunately, parameters can be inputed wrong resulting into an Invalid
command.
~Murphy's Fourteenth Law:  If anything can't go wrong on its own, someone will
make it go wrong.~

	So, in case there are less than 4 ints readen or any other text than ALL,
the Invalid command error is printed

~Software bugs are impossible to detect by anybody except the end user.~
	
	%Create the HISTOGRAM of a Black and White photo; this comand expects two
int parameters, which are the number of stars and the count of bins;

*if no image was loaded, print no load error

*if there are less/more than 2 parameters, print invalid command error
~Failure is not an option. It comes bundled with the software.~

*if given photo is color, print black and white photo needed error

	The Histogram is created by counting the occurances of pixels in a frquency
array; these frequences are later cumulated in "bins" number of bins (one bin
including 256/bins pixel frequences); these bins are graphically represented
according to the formula star_number = (pixel_freq * stars) / value_max

	The complexity of HISTOGRAM is O(col * lin)


	%EQUALIZE a Black and White photo (applies on the whole photo, not only
on the selection)

*check if the equalization can be done (only if a photo was loaded, if that 
photo is black and white)

*create a frequency array for the occurances of every pixel inside the photo
matrix

*take every pixel from the photo and apply the formula sum / area * MAX_VAL,
where sum is the sum of the frequences of every pixel from 0 to the current
pixel, area is the area of the whole photo, in pixels, and MAX value is the
255 MAX value of our photo type; the result of this formula is clamped
between 0 and 255 in order to have only valid values inside the new photo;

*the old photo is overwritten by the new equalized one

*if equalization was done succesfully, a succes message is printed

	The complexity of EQUALIZE is O(2 * lin * col) [frq_array] + [taking
every pixel and calculating that formula] => O(lin * col)


	%ROTATE a whole photo or a square selection inside the photo

*check if any photo was loaded

*check if the rotate angle is valid (-360 < angle < 360, angle % 90 == 0);
because of these facts, we can rotate any photo 90/-90 degrees multiple times,
until it matches our given angle; the number of rotation is angle / 90 if angle
is positive or angle / 90 * (-1) if angle is negative;

*rotate a photo to right if positive, to left if negative

*if its color, every color channel has to be rotated separately

*there is only one rotating function used for both color and bw photos as it
only crops a matrix, regardless photo's type

*if it's a selection, the selection has to be square (sel_lin == sel_col)

*if the whole photo was selected, it can be rotated anyway, even if it's not
square

*when rotating to right, it writes the values from the original selection, but
it starts with the top right corner of the new matrix, and than goes down the
column and left on the line

*when rotating to left, it writes the values from the original selection, but
it starts with the bottom left corner of the new matrix, and than goes up on
the column and than right on the line

*if the rotation was done sucessfully, print a succes message

	The complexity of ROTATE is O(sel_lin * sel_col)


	%CROP the photo acording to the selection

*checks if there is any loaded photo

*creates new matrix(es) containing only the values inside the selection from
the old photo

*frees the memory where the old photo was storaged

*points to the new memory

*there is only one croping function used for both color and bw photos as it
only crops a matrix, regardless photo's type
it's applied only once if the photo is bw and 3 times if the photo is color 
(for each color channel)

	The complexity of CROP is O(sel_lin * sel_col)


	%Can APPLY an effect over a selection in a color photo

*4 types of effect

*there is only one function (**apply_kern()) that can apply any given kernel
matrix and any divide coefficient over a selection inside the photo matrix;
function kern() just overwrites the old selected matrix with the newly created
matrix (by apply_kern()) 

*checks if apply can be done (if any image was loaded, if the readen parameter
is valid)

*if you try to APPLY over an BW photo, a computer will call you Charlie Chaplin

~Some people manage by the book, even they don't know who wrote the book, or
even what book.~

	The complexity of APPLY is O(sel_lin * sel_col) as it's effect is only over
a selection

	%Can SAVE a photo

*as ascii or binary no matter if it was ascii (P2/P3) or binary (P5/P6) when
it was loaded

*default save is binary, it will save only if ascii parameter was read, which
is an optional parameter, so it checks how many parameters are read using
fgets and strtok

*creates a new file where to save or opens the existing one having the same
name and overwrites it

*for saving as text it uses fprintf and for saving as binary it uses fwrite

*fwrite has 1 and 1 as size_t size and size_t nmemb parameters, in order to
write the int value from the matrix on one byte;

*if photo was color, it prints the 3 color channel matrixes simultaneous

	The complexity of SAVE is O(lin * col)


	%(finally)EXIT the program

*prints error message if no photo was loaded, but anyway exits it

*gratefully frees all the used memory at the time it was called

	The complexity of EXIT is O(lines) as it only has to free the photo 
matrix(es)

	

	PROGRAMS' STRUCTURE
~Weinberg's Second Law: If builders built buildings the way programmers write
programs, then the first woodpecker that came along would destroy
civilization.~

	- image_editor.c is the main function
	- every command has it's own .c with it's functions and it's own .h
	- errors.c/.h has every error message inside the program
	- succes.c/.h has every succes message inside the program
	- matrix_op.c/.h has the most used functions for matrix memory (alloc and 
	free) and some checks for devensive programming
	- utils.c/.h contain some useful functions
	- photo_type.h contains the definition of the structs


VERSION CONTROL
~Murphy's Second Law:  Nothing is as easy as it looks.~
~Murphy's Third Law:  Everything takes longer than you think it will.~

commit 1: initial commit
	*added empty README

commit 2: added makefile and main file
	*added empty main image_editor.c
	*added makefile

commit 3: maybe LOAD works
	*added command input from stdin
	*created hashing for commands in order to use switch
	*created struct for memorising the loaded photo
	*implemented basic LOAD
	*can open a file
	*checks if file exists
	*error handling if doesn't exit
	*check and remember photo type
	*hashing for photo type
	*can load a photo regardless it's type

commit 4: work in progress on SAVE
	*solved memory leak of not closing the file when loading
	*added succes message for loading
	*added no image loaded error
	*implemented new PROBLEM with getchar(), 
	which cannot be called at the end of any case
	*refactor - eliminated query file
	*work in progress on SAVE

commit 5: loading and saving works with 3 known bugs
	*loading and saving working 
	*implemented (Bug) feature with loading as P6 with wrong colours
	*after reading SAVE with only one parameter an extra \n is displayed
	*names of saved documents just aren't ok

commit 6: solved bugs from LOAD and SAVE
	*solved file names bugs
	*solved colour bug

commit 7: implemented SELECT (ALL)
	*implemented SELECT
	*select splits in SELECT ALL and SELECT <coords>
	*order of coords can be descending

commit 8: implemented histogram
	*I THINK I implemented it, not sure yet, no checker was published

commit 9: EQUALIZE
	*implemented EQUALIZE
	*created function for EXIT
	*some cleaning

commit 10: working on CROP
	*redone selection logic
	*reminder to implement loading ignoring #comments
	*CROP seg fault for colour photos
	*CROP selecting +1 more pixels thant requested

commit 11: CROP and SELECT in development
	*maybe messed up crop and select

commit 12: fixed SELECT logic and CROP
	*maybe fixed CROP and SELECT

commit 13: working on APPLY
	*CHECKER WAS PUBLISHED
	*repaired select logic
	*apparantly SELECT and CROP are working
	*work in progress on apply

commit 14: refactor RGB
	*refactored logic for RGB photos
	*in order to have 3 columns in a greater matrix for each value, now it
	saves 3 matrixes with the exact number of lins and cols, one for each color channel

commit 15: APPLY in development
	*created functions for every kind of APPLY
	*implemented new BUGS
	*created mutual funcrtions to aplly any kind of kernel in the same way

commit 16: fixed APPLY
	*fixed EDGE and SHARPEN
	*fixed APPLY without parameter bug
	*TODO run with valgrind

commit 17: working on ROTATE
	*added new error messages as functions
	*rotate work in progress
	*created messages for rotate
	*cleaned up some dead code

commit 18: ROTATE for SELECT ALL working
	*rotate not working for selections on P2 P5
	*rotate not working for selections on P3 P6
	*rotate working on SELECT ALL P2 P5
	*rotate working on SELECT ALL P3 P6

commit 19: Fixed ROTATE
	*fixed bug with rotate not working on selections inside the photo

commit 20: unconditional jump at save
	*started debugging tests from checker
	*start grade = 16.6666/90 + 10 README = 26.6666
	*added freeing matrix before loading a new one
	*detected bug with uncoditional jump at save

commit 21: fixed SAVE unconditional jump
	*problem was tracked from LOAD alloc_matrix
	*changed from malloc to calloc in alloc_matrix()

commit 22: 45/110
	*fixed APPLY error message when command was ok
	*fixed 2 invalid command error messages for only one command
	*fixed BLUR and GAUSSIAN_BLUR result accucaramelldansenracy
	*fixed reading GAUSSIAN_BL only

commit 23: 85.5/110
	*fixed no load error on SAVE
	*fixed EXIT error and close the program
	*fixed SLECT error to display when x1 == x2
	*fixed invalid read size at APPLY
	*fixed no_load error at SELECT
	*fixed wrong display order at SELECT

commit 24: 93/110
	*fixed SELECT wrong parameters

commit 25: 95/110
	*fixed HISTOGRAM wrong parameters
	*cleaned some comments

commit 26: 100/110
	*fixed ROTATE read error

commit 27: 110/110 Coding Style
	*Coding Style compliant
	*added Copyright on every file

commit 28: beauty refactor and comments
	*TODO write README lol
	*refactored function structures
	*created function for some duplicated code
	*cleaner declaration of matrix
	*heavily commented code

commit 29: step over comments
	*can step over comments at load
	*minor Coding Style fixes

commit 30: README
	*written README lol
	*added quotes inside the README
~Carlson's Consolation: Nothing is ever a complete failure; it can always
serve as a bad example.~

commit 31: struct point
	*added a struct to define a 2D point
	~Murphy's Thirteenth Law:  Every solution breeds new problems.~

commit 32: Defensive alloc
	*added more defensive programming at memory allocation
~Murphy's Eleventh Law:  It is impossible to make anything foolproof because
fools are so ingenious.~

commit 33: ROTATE refactor
	*created function with parameter as function at ROTATE command

About

Homework 3 of PCLP1

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published