DOCS: Added proper documentation to filters(.h, .c)
This commit is contained in:
@@ -2,42 +2,149 @@
|
||||
#define FILTERS_H
|
||||
#include "utils.h"
|
||||
|
||||
/**
|
||||
* @brief Packs new alpha channel
|
||||
* @details Takes a value from 0 - 255 for levels of opacity in image and packs
|
||||
* it into the first byte. 0 is transparent and 255 is fully opaque.
|
||||
* @param[in] clr Takes in a packed pixel
|
||||
* @param[in] alpha One byte value to be packed for image
|
||||
* @return unsigned int Packed color with new alpha channel.
|
||||
*/
|
||||
unsigned int
|
||||
u32_put_alpha(const unsigned int clr, const unsigned char alpha);
|
||||
|
||||
/**
|
||||
* @brief Inverts bits for color channels
|
||||
* @details Takes a packed color and inverts the RGB channel bits from 0 to 1
|
||||
* and vice versa. Then saves the alpha channel back to new packed image.
|
||||
* @param[in] clr Takes in a packed pixel
|
||||
* @return unsigned int Packed color with inverted RGB channels.
|
||||
*/
|
||||
unsigned int
|
||||
u32_invert(const unsigned int clr);
|
||||
|
||||
/**
|
||||
* @brief Inverts RED and BLUE channels
|
||||
* @details Takes a packed color and isolates the A and G channels, then shifts
|
||||
* the clr Red channel 16 Bits right and B channel 16 Bits left.
|
||||
* @param[in] clr Takes in a packed pixel
|
||||
* @return unsigned int Packed color with inverted RB channels.
|
||||
*/
|
||||
unsigned int
|
||||
u32_swap_rb(const unsigned int clr);
|
||||
|
||||
/**
|
||||
* @brief Grays pixels from RGB channels
|
||||
* @details Takes a packed color and merges RGB channels and sets all RGB
|
||||
* channels to new gray.
|
||||
* @param[in] clr Takes in a packed pixel
|
||||
* @return unsigned int Packed color with gray RGB channels.
|
||||
*/
|
||||
unsigned int
|
||||
u32_grayscale(const unsigned int clr);
|
||||
|
||||
/**
|
||||
* @brief Grays pixels from RGB channels
|
||||
* @details If greyscale value is less than Max then set color to transparent
|
||||
* and black. If greater, set color to opaque white. channels to new gray.
|
||||
* @param[in] clr Takes in a packed pixel
|
||||
* @param[in] max Max gray value for split
|
||||
* @return unsigned int Packed color with white or black RGB channels.
|
||||
*/
|
||||
unsigned int
|
||||
u32_step(const unsigned int clr, const unsigned char max);
|
||||
|
||||
/**
|
||||
* @brief Brightens Color
|
||||
* @details Uses a factor to multiply RGB channels to increase values closer to
|
||||
* 255 to raise brightness. Use x > 1 for a brighter pixel and x < 1 for a
|
||||
* darker pixel
|
||||
* @param[in] clr Takes in a packed pixel
|
||||
* @param[in] factor Used to multiply against RGB channels. Can be 0 < x > 1 but
|
||||
* NOT negative.
|
||||
* @return unsigned int Packed color with brighter or darker pixel
|
||||
*/
|
||||
unsigned int
|
||||
u32_brighten(const unsigned int clr, const float factor);
|
||||
|
||||
/**
|
||||
* @brief Combines RGB values between 2 packed colors
|
||||
* @details Takes and adds the respective RGB values between 2 colors and
|
||||
* divides by 2 to make sure each channel is below 255. So, even if 2 pixels are
|
||||
* white, the max values will stay 255.
|
||||
* @param[in] clr_a Packed Pixel A
|
||||
* @param[in] clr_b Packed Pixel B
|
||||
* @return unsigned int Packed ARGB pixel.
|
||||
*/
|
||||
unsigned int
|
||||
u32_mix(const unsigned int clr_a, const unsigned int clr_b);
|
||||
|
||||
/**
|
||||
* @brief Combines RGB values between 2 packed colors
|
||||
* @details Takes and adds the respective RGB values between 2 colors and
|
||||
* divides by 2 to make sure each channel is below 255. So, even if 2 pixels are
|
||||
* white, the max values will stay 255.
|
||||
* @param[in] clr_a Packed Pixel A
|
||||
* @param[in] clr_b Packed Pixel B
|
||||
* @return unsigned int Packed ARGB pixel.
|
||||
*/
|
||||
unsigned int
|
||||
u32_lerp(const unsigned clr_a, const unsigned int clr_b, const float ratio);
|
||||
|
||||
/**
|
||||
* @brief Returns a Packed Pixel of one Channel
|
||||
* @param[in] clr Packed Pixel
|
||||
* @param[in] keep Character of 'r', 'g', 'b', keeping the channel respectively.
|
||||
* @return unsigned int Packed Pixel with one channel kept, includes alpha auto
|
||||
*/
|
||||
unsigned int
|
||||
u32_mask(const unsigned int clr, const char keep);
|
||||
|
||||
/**
|
||||
* @brief Rotates the bits of each channel by n
|
||||
* @details Moves bits of channels left by n with the max being 8 and
|
||||
* recommended to use 0 < x < 8 instead of 8; 8 just returns the same pixel as
|
||||
* it is just rotated back to original position. Cannot be greater than 8
|
||||
* because the calculations would result in a negative.
|
||||
* @param[in] clr Packed Pixel
|
||||
* @param[in] n Amount of times to move bits to left.
|
||||
* @return unsigned int Packed Pixel with newly moved bits
|
||||
*/
|
||||
unsigned int
|
||||
u32_rotl(const unsigned int clr, const int n);
|
||||
|
||||
/**
|
||||
* @brief Raises Color Vibrance
|
||||
* @details Raises the vibrance by essentially raising specific channels higher
|
||||
* and lowering others.
|
||||
* @param[in] clr Packed Pixel
|
||||
* @param[in] factor Floating point to raise or lower vibrance by.
|
||||
* @return unsigned int Packed Pixel with one channel kept, includes alpha auto
|
||||
*/
|
||||
unsigned int
|
||||
u32_contrast(const unsigned int clr, const float factor);
|
||||
|
||||
/**
|
||||
* @brief Averages Red and Blue Channels for Green Channel
|
||||
* @param[in] clr Packed Pixel
|
||||
* @return unsigned int Packed Pixel with green pixel averaged
|
||||
*/
|
||||
unsigned int
|
||||
u32_avg_gb(const unsigned int clr);
|
||||
|
||||
/**
|
||||
* @brief Blurs image in a radiance with a box
|
||||
* @details Uses 2 loops to scan from left to right; selecting a pixel and
|
||||
* mixing all of the pixels from "radius" left to "radius" right and averaging
|
||||
* them. Then it moves to the next pixel doing the same. Then it does the second
|
||||
* loop from top to bottom doing the same principle. This can take some time
|
||||
* depending on hardware, image size, radius, etc.
|
||||
* @param[in] src_buf The image buffer to be blurred
|
||||
* @param[in] img the PPM image container
|
||||
* @param[in] radius The amount of pixels around the left and right, then top
|
||||
* and bottom to mix with the currently selected pixel
|
||||
* @return unsigned int Pointer to new created image buffer.
|
||||
*/
|
||||
unsigned int*
|
||||
box_blur(const unsigned int* src_buf, const PPM* img, const int radius);
|
||||
|
||||
|
||||
@@ -115,7 +115,8 @@ typedef struct
|
||||
/**
|
||||
* @brief Converts an int to long
|
||||
* @details Takes in 32-Bit packed color and separates the 4 color values into a
|
||||
* 64-Bit packed color for JPEG translations.
|
||||
* 64-Bit packed color. Used for bigger image calculations with one channel and
|
||||
* then dividing later.
|
||||
* @param[in] clr Takes a packed color, unsigned int
|
||||
* @return unsigned long Packed color in 4 ints instead of one
|
||||
* */
|
||||
@@ -124,8 +125,7 @@ u32to_u64(const unsigned int clr);
|
||||
|
||||
/**
|
||||
* @brief Converts a long to int
|
||||
* @details Takes in a full packed color and compresses it back into 1 ints for
|
||||
* ppm translations.
|
||||
* @details Takes in a full packed color and compresses it to 1 Byte
|
||||
* @param[in] clr Takes a packed color, unsigned long
|
||||
* @param[in] u64_div Takes a divisor to break down to raw color
|
||||
* @return unsigned int Packed color in 1 int instead of 4
|
||||
|
||||
+81
-8
@@ -1,10 +1,8 @@
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
// #include "utils.h"
|
||||
#include "image/filters.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
unsigned int
|
||||
u32_put_alpha(const unsigned int clr, const unsigned char alpha)
|
||||
{
|
||||
@@ -30,6 +28,13 @@ u32_grayscale(const unsigned int clr)
|
||||
unsigned int red = DECODE_R(clr);
|
||||
unsigned int green = DECODE_G(clr);
|
||||
unsigned int blue = DECODE_B(clr);
|
||||
/*
|
||||
* WHY: The colors use the REC 601 Standard: Lamens terms they are
|
||||
* weighed in how the human eye percieves color. So green is the largest
|
||||
* because we are more sensitive to green and least to blue.
|
||||
* The Shift_8 is to divide 256 to bring the color value back into range
|
||||
of 0 - 255
|
||||
*/
|
||||
unsigned int gray =
|
||||
((red * 77) + (green * 150) + (blue * 29)) >> SHIFT_8;
|
||||
|
||||
@@ -49,7 +54,6 @@ u32_step(const unsigned int clr, const unsigned char max)
|
||||
unsigned int
|
||||
u32_brighten(const unsigned int clr, const float factor)
|
||||
{
|
||||
unsigned int alpha = (clr & BYTE_A);
|
||||
unsigned int red = CLAMP_MAX(DECODE_R(clr) * factor);
|
||||
unsigned int green = CLAMP_MAX(DECODE_G(clr) * factor);
|
||||
unsigned int blue = CLAMP_MAX(DECODE_B(clr) * factor);
|
||||
@@ -67,8 +71,14 @@ u32_mix(const unsigned int clr_a, const unsigned int clr_b)
|
||||
}
|
||||
|
||||
unsigned int
|
||||
u32_lerp(const unsigned clr_a, const unsigned int clr_b, const float ratio)
|
||||
u32_lerp(const unsigned int clr_a, const unsigned int clr_b, const float ratio)
|
||||
{
|
||||
/*
|
||||
* A more powerful mix using floating points to more precisely and
|
||||
* smoothly mix colors from 2 pixels. Doesn't really work on PPM images
|
||||
* because they are whole number pixels. So jpeg are better because the
|
||||
* numbers result in floating point colors.
|
||||
* */
|
||||
unsigned char blue =
|
||||
((DECODE_B(clr_a) * (1 - ratio)) + ((DECODE_B(clr_b) * ratio)));
|
||||
unsigned char green =
|
||||
@@ -104,11 +114,41 @@ u32_rotl(const unsigned int clr, const int n)
|
||||
{
|
||||
if (n > 8)
|
||||
{
|
||||
return 0;
|
||||
printf(
|
||||
"ERROR: %i is greater than 8 results in black "
|
||||
"pixels, please use values less than 8\n",
|
||||
n);
|
||||
exit(10);
|
||||
}
|
||||
unsigned int red = DECODE_R(clr);
|
||||
unsigned int green = DECODE_G(clr);
|
||||
unsigned int blue = DECODE_B(clr);
|
||||
/*
|
||||
* Rotates the color channels. Essentially it moves bits left a certain
|
||||
* n and then wraps if it leaves the left to the right.
|
||||
*
|
||||
* If you input 1 to n and have:
|
||||
* 0 0 0 0 0 0 0 1 # 1
|
||||
*
|
||||
* You will get:
|
||||
* 0 0 0 0 0 0 1 0 # 2
|
||||
*
|
||||
* But this gets complex with larger numbers:
|
||||
* 0 1 0 1 1 1 0 0 # 4 + 8 + 16 + 64 = 92
|
||||
*
|
||||
* Rotating by 2 will wrap and give:
|
||||
* 0 1 1 1 0 0 0 1 # 1 + 16 + 32 + 64 = 113
|
||||
*
|
||||
* This creates a pixelated looking image of random colors while still
|
||||
* holding the original image's structure under. Almost a distored,
|
||||
* broken tv look.
|
||||
*
|
||||
* N has a max of 8 because any number after 8 results in the bits
|
||||
* shifting negatively due to the wrapping math, which cant happen and
|
||||
* just makes the pixels black. If the number is 8 it just results in
|
||||
* the pixels being the same as they are just rotated back to their
|
||||
* original spot.
|
||||
* */
|
||||
red = ((red << n) | (red >> (SHIFT_8 - n))) & BYTE;
|
||||
green = ((green << n) | (green >> (SHIFT_8 - n))) & BYTE;
|
||||
blue = ((blue << n) | (blue >> (SHIFT_8 - n))) & BYTE;
|
||||
@@ -136,6 +176,19 @@ u32_avg_gb(const unsigned int clr)
|
||||
return ENCODE_RGB(red, green, blue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Blurs column at (x,y) using -radius to radius
|
||||
* @details Starts at the top extreme and moves to the bottom extreme,
|
||||
* taking the pixel and adding each channel. Because each channel is separated
|
||||
* into their own ints, it adds each int together and at the end divides each
|
||||
* channel back below 256 and converts back to one int.
|
||||
* @param[in] src Pointer to buffer image.
|
||||
* @param[in] x Location in the image buffer for column of original pixel
|
||||
* @param[in] y Location in the image buffer for row of original pixel
|
||||
* @param[in] img Pointer to PPM container
|
||||
* @param[in] radius The value to find -extreme and +extreme to add to pixel
|
||||
* @return unsigned int Packed color with new alpha channel.
|
||||
*/
|
||||
unsigned int
|
||||
blur_col(const unsigned int* src, const int x, const int y, const PPM* img,
|
||||
const int radius)
|
||||
@@ -152,13 +205,30 @@ blur_col(const unsigned int* src, const int x, const int y, const PPM* img,
|
||||
}
|
||||
}
|
||||
|
||||
// WHY: takes the count (cnt) of pixels from column and divides the
|
||||
// point (pt) by (cnt) to get back below 256 and then converted back
|
||||
// into an int from a long
|
||||
if (cnt > 0)
|
||||
{
|
||||
return u64to_u32(pt, cnt);
|
||||
}
|
||||
|
||||
return src[y * img->width + x];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Blurs column at (x,y) using -radius to radius
|
||||
* @details Starts at the left extreme and moves to the right extreme taking the
|
||||
* pixel and adding each channel. Because each channel is separated into their
|
||||
* own ints, it adds each int together and at the end divides each channel back
|
||||
* below 256 and converts back to one int.
|
||||
* @param[in] src Pointer to buffer image.
|
||||
* @param[in] x Location in the image buffer for column of original pixel
|
||||
* @param[in] y Location in the image buffer for row of original pixel
|
||||
* @param[in] img Pointer to PPM container
|
||||
* @param[in] radius The value to find -extreme and +extreme to add to pixel
|
||||
* @return unsigned int Packed color with new alpha channel.
|
||||
*/
|
||||
unsigned int
|
||||
blur_row(const unsigned int* src, const int x, const int y, const PPM* img,
|
||||
const int radius)
|
||||
@@ -175,6 +245,9 @@ blur_row(const unsigned int* src, const int x, const int y, const PPM* img,
|
||||
}
|
||||
}
|
||||
|
||||
// WHY: takes the count (cnt) of pixels from row and divides the
|
||||
// point (pt) by (cnt) to get back below 256 and then converted back
|
||||
// into an int from a long
|
||||
if (cnt > 0)
|
||||
{
|
||||
return u64to_u32(pt, cnt);
|
||||
|
||||
+15
-8
@@ -1,3 +1,4 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "image/filters.h"
|
||||
@@ -7,6 +8,11 @@
|
||||
// #include "image/transformations.h"
|
||||
#include "image/imgio.h"
|
||||
|
||||
/*
|
||||
* Keep in mind any function that creates a new buffer and returns it can
|
||||
* overwrite the old one, however it is lost. SO create a new variable and free
|
||||
* the old one after use.
|
||||
* */
|
||||
int
|
||||
main()
|
||||
{
|
||||
@@ -15,17 +21,18 @@ main()
|
||||
//
|
||||
// };
|
||||
PPM img = {
|
||||
.name = "../IMG_1649.ppm",
|
||||
.name = "../assets/test.ppm",
|
||||
};
|
||||
|
||||
unsigned int* buf = ppm_load(img.name, &img);
|
||||
// for (int i = 0; i < img.len; i++)
|
||||
// {
|
||||
// // you need to replace the old value with the new updated value
|
||||
// buf[i] = u32_grayscale(buf[i]);
|
||||
// }
|
||||
buf = u32_rotate(buf, &img);
|
||||
ppm_save(buf, img, "../IMG_1649_new.ppm");
|
||||
for (int i = 0; i < img.len; i++)
|
||||
{
|
||||
// you need to replace the old value with the new updated value
|
||||
buf[i] = u32_contrast(buf[i], 9);
|
||||
}
|
||||
img.fmt = '3';
|
||||
// buf = u32_rotate(buf, &img);
|
||||
ppm_save(buf, img, "../assets/test_new.ppm");
|
||||
|
||||
// PPM out_2 = inherit_from_jpeg(&out_1, '6');
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user