Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
54a2d44a53 | ||
|
|
81c228beb8 | ||
|
|
c140c5b776 | ||
|
|
241ddd7f6d | ||
|
|
8ed07bf8db | ||
|
|
328648f57f | ||
|
|
ee2180a905 | ||
|
|
33bc2f29e6 | ||
|
|
39911cd662 | ||
|
|
d2557b84cf |
+1
-1
@@ -29,6 +29,6 @@ target_link_libraries(imgproc PUBLIC PkgConfig::TURBOJPEG)
|
||||
set_target_properties(imgproc PROPERTIES EXPORT_NAME imgproc)
|
||||
|
||||
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
|
||||
add_executable(libimg src/main.c) # Assuming you have a main.c
|
||||
add_executable(libimg src/main.c)
|
||||
target_link_libraries(libimg PRIVATE imgproc)
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2011-2026 The Bootstrap Authors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
@@ -1,20 +1,75 @@
|
||||
# LibIMG
|
||||
|
||||
_A "powerful" library that I have worked on allowing you to take a PPM image and apply filters and transformations and download the file. It also works for JPEG which you can also convert to PPM and vice versa_
|
||||
_A lightweight, fast, and minimal library designed to be powerful for my current capabilities. This is a hobby project to learn bit operations and expanded to a full processor between two types --- PPM and JPEG. It's powerful for what it is and it is weak for what it could be._
|
||||
|
||||
> [Note]
|
||||
> All documentation is in the code and files itself. So to save myself time I would recommend going through the code itself.
|
||||
|
||||
> [Warning]
|
||||
> There are a lot of changes you can make to an image but this is not an extensive library to use mainstream. I would hope you understood that already. This Is for a self made project learning bitwise for c originally and now has become bigger and cooler than expected.
|
||||
> There are a lot of changes you can make to an image but this is not an extensive library to use mainstream. I would hope you understood that already. This is for a self made project learning bitwise for c originally and now has become bigger and cooler than expected.
|
||||
|
||||
### Example
|
||||
## Prerequisites
|
||||
|
||||
1. This library does require _```libturbojpeg```_ as manually writing the functions for JPEG would take a long time to figure out and I may come back to do later.
|
||||
2. ```C23 and CMake 4.4.3```, as there are some new features from it. Tested only on my M1 Macbook for compatibility.
|
||||
|
||||
## Types
|
||||
|
||||
Available
|
||||
|
||||
1. PPM (Originally just to learn with)
|
||||
2. JPEG (Added as having only PPM felt wrong)
|
||||
|
||||
Planned
|
||||
|
||||
3. PNG (Planned)
|
||||
4. SVG (We Shall See)
|
||||
|
||||
## Installation
|
||||
|
||||
You can build manually or pull it into a project
|
||||
|
||||
_To Build_:
|
||||
|
||||
```bash
|
||||
git clone https://git.moomancer.xyz/DarthMooMancer/libimg.git
|
||||
cd libimg
|
||||
cmake -S . -B build && cmake --build build
|
||||
./build/libimg
|
||||
```
|
||||
|
||||
_To pull, use FetchContent in your ```CMakeLists.txt```:_
|
||||
|
||||
|
||||
```Make
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(imgproc
|
||||
GIT_REPOSITORY https://git.moomancer.xyz/DarthMooMancer/libimg.git
|
||||
GIT_TAG main
|
||||
GIT_SHALLOW TRUE
|
||||
)
|
||||
FetchContent_MakeAvailable(imgproc)
|
||||
target_link_libraries(<project> PRIVATE imgproc)
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
_While it is not an extensive example, it shows many of the patterns for how to use all functions throughout the codebase._
|
||||
|
||||
```c
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Functions (Specifically filters) that return unsigned int (not pointers) need
|
||||
* to be used as an input to the same point in a buffer.
|
||||
*
|
||||
* For example:
|
||||
*
|
||||
* buf[i] = u32_grayscale(buf[i]);
|
||||
*
|
||||
* The buf[i] is replaced by the output of grayscale at buf[i]
|
||||
*/
|
||||
int
|
||||
main()
|
||||
@@ -29,13 +84,14 @@ main()
|
||||
// Load the PPM image
|
||||
unsigned int* buf = ppm_load(img.name, &img);
|
||||
|
||||
// Check for null image load. In case image doesnt exist or fails to
|
||||
// Check for null image load. In case image doesn't exist or fails to
|
||||
// load
|
||||
if (!buf)
|
||||
{
|
||||
LOGERROR(ERR_BUF_NULL);
|
||||
return ERR_BUF_NULL;
|
||||
}
|
||||
|
||||
// Blur image and save to new pointer
|
||||
unsigned int* blur = box_blur(buf, &img, 20);
|
||||
|
||||
@@ -43,7 +99,8 @@ main()
|
||||
// ending or possibly leaking. Also it stays in heap and a large image
|
||||
// can take a lot of memory so better to clear anyways.
|
||||
free(buf);
|
||||
// Check for null image load. In case image doesnt exist or fails to
|
||||
|
||||
// Check for null image load. In case image doesn't exist or fails to
|
||||
// load
|
||||
if (!blur)
|
||||
{
|
||||
@@ -57,10 +114,10 @@ main()
|
||||
blur[i] = u32_rotl(blur[i], 4);
|
||||
}
|
||||
|
||||
// Take the attributes from ppm image so jpeg file can be saved
|
||||
// Take the attributes from ppm image so JPEG file can be saved
|
||||
jimg = inherit_from_ppm(&img);
|
||||
|
||||
// Saves jpeg to location specified
|
||||
// Saves JPEG to location specified
|
||||
jpeg_save(blur, &jimg, "../assets/test_2_new.jpg");
|
||||
|
||||
// Make sure to free any buffer still active
|
||||
|
||||
@@ -107,11 +107,11 @@ u32_mask(const unsigned int clr, const char keep);
|
||||
* 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.
|
||||
* @param[in] dist Distance from original position to move each bit to the left.
|
||||
* @return unsigned int Packed Pixel with newly moved bits
|
||||
*/
|
||||
unsigned int
|
||||
u32_rotl(const unsigned int clr, const int n);
|
||||
u32_rotl(const unsigned int clr, const int dist);
|
||||
|
||||
/**
|
||||
* @brief Raises Color Vibrance
|
||||
@@ -139,13 +139,13 @@ u32_avg_gb(const unsigned int clr);
|
||||
* 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] buf The image buffer to be blurred
|
||||
* @param[in] metadata 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*
|
||||
u32_box_blur(const unsigned int* src_buf, const PPM* img, const int radius);
|
||||
u32_box_blur(const unsigned int* buf, const PPM* metadata, const int radius);
|
||||
|
||||
#endif
|
||||
|
||||
+20
-21
@@ -5,67 +5,66 @@
|
||||
|
||||
/**
|
||||
* @brief Open and Fill buffer from .ppm file
|
||||
* @param [in] file Char pointer use to locate the image to be modified lays.
|
||||
* @param [in,out] m_attr PPM pointer to store image information
|
||||
* @param [in] filename Location of the image to be modified
|
||||
* @param [in,out] metadata PPM pointer to store image information
|
||||
*/
|
||||
unsigned int*
|
||||
read_ppm(const char* file, PPM* m_attr);
|
||||
read_ppm(const char* filename, PPM* metadata);
|
||||
|
||||
/**
|
||||
* @brief Open and write buffer to file
|
||||
* @param [in] buf Information of pixels
|
||||
* @param [in] img PPM pointer to store image information
|
||||
* @param [in] char Name/Location for file
|
||||
* @param [in] buffer Information of pixels
|
||||
* @param [in] metadata PPM pointer to store image information
|
||||
* @param [in] filename Name/Location for file
|
||||
*/
|
||||
int
|
||||
write_ppm(const unsigned int* buf, const PPM img, const char* name);
|
||||
write_ppm(const unsigned int* buffer, const PPM metadata, const char* filename);
|
||||
|
||||
/**
|
||||
* @brief Open and Fill buffer from .jpg file
|
||||
* @details Opens a .jpg file, creates a new buffer and extracts the pixels into
|
||||
* said buffer as integers.
|
||||
* @param [in] file Char pointer use to locate the image to be modified lays.
|
||||
* @param [in,out] m_attr JPEG pointer to store image information
|
||||
* @param [in,out] metadata JPEG pointer to store image information
|
||||
*/
|
||||
unsigned int*
|
||||
read_jpeg(JPEG* m_attr);
|
||||
read_jpeg(JPEG* metadata);
|
||||
|
||||
/**
|
||||
* @brief Open and write buffer to file
|
||||
* @param [in] buf Information of pixels
|
||||
* @param [in] attr JPEG pointer to store image information
|
||||
* @param [in] char Name/Location for file
|
||||
* @param [in] metadata JPEG pointer to store image information
|
||||
* @param [in] filename Name/Location for file
|
||||
*/
|
||||
int
|
||||
write_jpeg(const unsigned int* src_buf, const JPEG* attr, const char* name);
|
||||
write_jpeg(const unsigned int* buf, const JPEG* metadata, const char* filename);
|
||||
|
||||
/**
|
||||
* @brief Converts PPM to JPEG
|
||||
* @param [in] in Pointer to PPM container
|
||||
* @param [in] location points to file to use
|
||||
*/
|
||||
void
|
||||
transcode_to_jpeg(PPM* in);
|
||||
transcode_to_jpeg(const char* location);
|
||||
|
||||
/**
|
||||
* @brief Converts JPEG to PPM
|
||||
* @param [in] in Pointer to JPEG container
|
||||
* @param [in] location Pointer to JPEG container
|
||||
*/
|
||||
void
|
||||
transcode_to_ppm(JPEG* in);
|
||||
transcode_to_ppm(const char* location);
|
||||
|
||||
/**
|
||||
* @brief Inherits the attributes from JPEG container
|
||||
* @param [in] in Pointer to JPEG container
|
||||
* @param [in] metadata Pointer to JPEG container
|
||||
* @param [in] fmt Character for type of PPM image, binary or raw
|
||||
*/
|
||||
PPM
|
||||
inherit_from_jpeg(const JPEG* in, const char fmt);
|
||||
inherit_from_jpeg(const JPEG* metadata, const char fmt);
|
||||
|
||||
/**
|
||||
* @brief Inherits the attributes from PPM container
|
||||
* @param [in] in Pointer to PPM container
|
||||
* @param [in] metadata Pointer to PPM container
|
||||
*/
|
||||
JPEG
|
||||
inherit_from_ppm(const PPM* in);
|
||||
inherit_from_ppm(const PPM* metadata);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* @retval NULL If original buffer is invalid or if new buffer fails to create
|
||||
* */
|
||||
unsigned int*
|
||||
u32_flop(const unsigned int* buf, const PPM img);
|
||||
u32_flop(const unsigned int* buf, const int width, const int height);
|
||||
|
||||
/**
|
||||
* @brief Flips image on Y-Axis
|
||||
@@ -25,7 +25,7 @@ u32_flop(const unsigned int* buf, const PPM img);
|
||||
* @retval NULL If original buffer is invalid or if new buffer fails to create
|
||||
* */
|
||||
unsigned int*
|
||||
ppm_flip(const unsigned int* buf, const PPM img);
|
||||
u32_flip(const unsigned int* buf, const int width, const int height);
|
||||
|
||||
/**
|
||||
* @brief Rotates image on 90 Clockwise
|
||||
@@ -38,6 +38,6 @@ ppm_flip(const unsigned int* buf, const PPM img);
|
||||
* new buffer fails to create and is invalid
|
||||
* */
|
||||
unsigned int*
|
||||
u32_rotate(const unsigned int* buf, PPM* m_img);
|
||||
u32_rotate(const unsigned int* buf, PPM* metadata);
|
||||
|
||||
#endif
|
||||
|
||||
+22
-16
@@ -47,7 +47,7 @@ extern const char* error_messages[];
|
||||
* @brief Max value for any channel
|
||||
* @details For alpha channel this is the max opacity setting and 0 is fully
|
||||
* transparent, 255 is white for any color and 0 is black.
|
||||
* */
|
||||
*/
|
||||
#define MAX 255
|
||||
#define HALF_MAX \
|
||||
((int)(MAX / 2) + 1) /**< Half Max Color Value for any channel */
|
||||
@@ -70,7 +70,7 @@ extern const char* error_messages[];
|
||||
* @param[in] g The green channel stored as char and packed into int
|
||||
* @param[in] b The blue channel stored as char and packed into int
|
||||
*
|
||||
* */
|
||||
*/
|
||||
#define ENCODE_RGB(r, g, b) \
|
||||
(((unsigned int)(MAX) << SHIFT_24) | ((unsigned int)(r) << SHIFT_16) | \
|
||||
((unsigned int)(g) << SHIFT_8) | (unsigned int)(b))
|
||||
@@ -85,7 +85,7 @@ extern const char* error_messages[];
|
||||
* @param[in] g The green channel stored as char and packed into int
|
||||
* @param[in] b The blue channel stored as char and packed into int
|
||||
*
|
||||
* */
|
||||
*/
|
||||
#define ENCODE_ARGB(a, r, g, b) \
|
||||
(((unsigned int)(a) << SHIFT_24) | ((unsigned int)(r) << SHIFT_16) | \
|
||||
((unsigned int)(g) << SHIFT_8) | (unsigned int)(b))
|
||||
@@ -95,7 +95,7 @@ extern const char* error_messages[];
|
||||
* @details Takes in a value of X and checks if it is Above the Max of 255. If
|
||||
* so, then set to Max. If not, then simply set back to whatever X was before.
|
||||
* @param[in] x Color channel: char
|
||||
* */
|
||||
*/
|
||||
#define CLAMP_MAX(x) (((x) > MAX) ? MAX : (x))
|
||||
|
||||
/**
|
||||
@@ -103,14 +103,14 @@ extern const char* error_messages[];
|
||||
* @details Takes in a value of X and checks if it is Below 0. If so, then set
|
||||
* to 0. If not, then simply set back to whatever X was before.
|
||||
* @param[in] x Color channel: char
|
||||
* */
|
||||
*/
|
||||
#define CLAMP_MIN(x) (((x) < 0) ? 0 : (x))
|
||||
|
||||
/**
|
||||
* @brief Contains values for PPM Image
|
||||
* @details Can be defined with just a name and filled later with ppm_load
|
||||
* as it stores information for header of file not the pixels of the image
|
||||
* */
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
int width; /**< Image width in pixels */
|
||||
@@ -124,7 +124,7 @@ typedef struct
|
||||
* @brief Contains values for JPEG Image
|
||||
* @details Can be defined with just a name and filled later with jpeg_load as
|
||||
* it stores information for header of file not the pixels of the image
|
||||
* */
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
int width; /**< Image width in pixels */
|
||||
@@ -140,7 +140,7 @@ typedef struct
|
||||
* then dividing later.
|
||||
* @param[in] clr Takes a packed color, unsigned int
|
||||
* @return unsigned long Packed color in 4 ints instead of one
|
||||
* */
|
||||
*/
|
||||
unsigned long
|
||||
u32to_u64(const unsigned int clr);
|
||||
|
||||
@@ -150,7 +150,7 @@ u32to_u64(const unsigned int clr);
|
||||
* @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
|
||||
* */
|
||||
*/
|
||||
unsigned int
|
||||
u64to_u32(const unsigned long clr, const unsigned long u64_div);
|
||||
|
||||
@@ -158,21 +158,27 @@ u64to_u32(const unsigned long clr, const unsigned long u64_div);
|
||||
* @brief Prints quick debug info of container
|
||||
* @details Prints metadata like Name, Format, Width, Height and Length
|
||||
* important for debugging errors
|
||||
* @param[in] src Pointer to src metadata of a PPM image
|
||||
* */
|
||||
* @param[in] metadata Pointer to information of a PPM image
|
||||
*/
|
||||
void __attribute__((overloadable))
|
||||
print_attr(const PPM* src);
|
||||
print_attr(const PPM* metadata);
|
||||
|
||||
/**
|
||||
* @brief Prints quick debug info of container
|
||||
* @details Prints metadata like Name, Width, Height and Length
|
||||
* important for debugging errors
|
||||
* @param[in] src Pointer to src metadata of a JPEG image
|
||||
* */
|
||||
* @param[in] metadata Pointer to information of a JPEG image
|
||||
*/
|
||||
void __attribute__((overloadable))
|
||||
print_attr(const JPEG* src);
|
||||
print_attr(const JPEG* metadata);
|
||||
|
||||
/**
|
||||
* @brief Finds start of extension in image name
|
||||
* @details Loops through the character array starting from the end to find the
|
||||
* start of the extension.
|
||||
* @param[in] str Char array to loop through
|
||||
*/
|
||||
size_t
|
||||
find_extension(const char* n);
|
||||
find_extension(const char* str);
|
||||
|
||||
#endif
|
||||
|
||||
+35
-32
@@ -27,18 +27,16 @@ u32_swap_rb(const unsigned int clr)
|
||||
unsigned int
|
||||
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
|
||||
* WHY: The colors use the REC 601 Standard: In layman's terms they are
|
||||
* weighed in how the human eye perceives 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;
|
||||
unsigned int gray = ((DECODE_R(clr) * 77) + (DECODE_G(clr) * 150) +
|
||||
(DECODE_B(clr) * 29)) >>
|
||||
SHIFT_8;
|
||||
|
||||
return (clr & BYTE_A) | (gray << SHIFT_16) | (gray << SHIFT_8) | gray;
|
||||
}
|
||||
@@ -56,6 +54,7 @@ u32_step(const unsigned int clr, const unsigned char max)
|
||||
unsigned int
|
||||
u32_brighten(const unsigned int clr, const float factor)
|
||||
{
|
||||
// NOTE: keep definition for readability
|
||||
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);
|
||||
@@ -65,6 +64,7 @@ u32_brighten(const unsigned int clr, const float factor)
|
||||
unsigned int
|
||||
u32_mix(const unsigned int clr_a, const unsigned int clr_b)
|
||||
{
|
||||
// NOTE: keep definition for readability
|
||||
unsigned char blue = (DECODE_B(clr_a) + DECODE_B(clr_b)) / 2;
|
||||
unsigned char green = (DECODE_G(clr_a) + DECODE_G(clr_b)) / 2;
|
||||
unsigned char red = (DECODE_R(clr_a) + DECODE_R(clr_b)) / 2;
|
||||
@@ -78,9 +78,10 @@ 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
|
||||
* because they are whole number pixels. So JPEG are better because the
|
||||
* numbers result in floating point colors.
|
||||
* */
|
||||
// NOTE: keep definition for readability
|
||||
unsigned char blue =
|
||||
((DECODE_B(clr_a) * (1 - ratio)) + ((DECODE_B(clr_b) * ratio)));
|
||||
unsigned char green =
|
||||
@@ -112,9 +113,9 @@ u32_mask(const unsigned int clr, const char keep)
|
||||
}
|
||||
|
||||
unsigned int
|
||||
u32_rotl(const unsigned int clr, const int n)
|
||||
u32_rotl(const unsigned int clr, const int dist)
|
||||
{
|
||||
if (n > 8)
|
||||
if (dist > 8)
|
||||
{
|
||||
LOGERROR(ERR_INVALID_SIZE);
|
||||
return ERR_INVALID_SIZE;
|
||||
@@ -138,9 +139,9 @@ u32_rotl(const unsigned int clr, const int n)
|
||||
* 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.
|
||||
* This creates a pixilated looking image of random colors while still
|
||||
* holding the original image's structure under. Almost a distorted,
|
||||
* 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
|
||||
@@ -148,15 +149,16 @@ u32_rotl(const unsigned int clr, const int n)
|
||||
* 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;
|
||||
red = ((red << dist) | (red >> (SHIFT_8 - dist))) & BYTE;
|
||||
green = ((green << dist) | (green >> (SHIFT_8 - dist))) & BYTE;
|
||||
blue = ((blue << dist) | (blue >> (SHIFT_8 - dist))) & BYTE;
|
||||
return ENCODE_RGB(red, green, blue);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
u32_contrast(const unsigned int clr, const float factor)
|
||||
{
|
||||
// NOTE: keep definition for readability
|
||||
int red = CLAMP_MIN(CLAMP_MAX(
|
||||
(int)(factor * (float)(int)(DECODE_R(clr) - HALF_MAX)) + HALF_MAX));
|
||||
int green = CLAMP_MIN(CLAMP_MAX(
|
||||
@@ -179,7 +181,7 @@ u32_avg_gb(const unsigned int clr)
|
||||
* @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
|
||||
* into their own int, 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
|
||||
@@ -219,7 +221,7 @@ blur_col(const unsigned int* src, const int x, const int y, const PPM* img,
|
||||
* @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
|
||||
* own int, 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
|
||||
@@ -255,37 +257,38 @@ blur_row(const unsigned int* src, const int x, const int y, const PPM* img,
|
||||
}
|
||||
|
||||
unsigned int*
|
||||
u32_box_blur(const unsigned int* src_buf, const PPM* img, const int radius)
|
||||
u32_box_blur(const unsigned int* buf, const PPM* metadata, const int radius)
|
||||
{
|
||||
unsigned int* first_pass = malloc(img->len * sizeof(unsigned int));
|
||||
if (!first_pass)
|
||||
unsigned int* col_buf = malloc(metadata->len * sizeof(unsigned int));
|
||||
if (!col_buf)
|
||||
{
|
||||
LOGERROR(ERR_BUF_NULL);
|
||||
return NULL;
|
||||
}
|
||||
unsigned int* dst_buf = malloc(img->len * sizeof(unsigned int));
|
||||
unsigned int* dst_buf = malloc(metadata->len * sizeof(unsigned int));
|
||||
if (!dst_buf)
|
||||
{
|
||||
free(first_pass);
|
||||
free(col_buf);
|
||||
LOGERROR(ERR_BUF_NULL);
|
||||
return NULL;
|
||||
}
|
||||
for (int y = 0; y < img->height; y++)
|
||||
for (int y = 0; y < metadata->height; y++)
|
||||
{
|
||||
for (int x = 0; x < img->width; x++)
|
||||
for (int x = 0; x < metadata->width; x++)
|
||||
{
|
||||
first_pass[y * img->width + x] =
|
||||
blur_col(src_buf, x, y, img, radius);
|
||||
col_buf[y * metadata->width + x] =
|
||||
blur_col(buf, x, y, metadata, radius);
|
||||
}
|
||||
}
|
||||
for (int y = 0; y < img->height; y++)
|
||||
for (int y = 0; y < metadata->height; y++)
|
||||
{
|
||||
for (int x = 0; x < img->width; x++)
|
||||
for (int x = 0; x < metadata->width; x++)
|
||||
{
|
||||
dst_buf[y * img->width + x] =
|
||||
blur_row(first_pass, x, y, img, radius);
|
||||
dst_buf[y * metadata->width + x] =
|
||||
blur_row(col_buf, x, y, metadata, radius);
|
||||
}
|
||||
}
|
||||
free(first_pass);
|
||||
free(col_buf);
|
||||
free((void*)buf);
|
||||
return dst_buf;
|
||||
}
|
||||
|
||||
+98
-104
@@ -8,52 +8,52 @@
|
||||
#include "image/utils.h"
|
||||
|
||||
unsigned int*
|
||||
read_ppm(const char* file, PPM* m_attr)
|
||||
read_ppm(const char* filename, PPM* metadata)
|
||||
{
|
||||
LOG("Decoding");
|
||||
unsigned char red, green, blue;
|
||||
char fmt[3];
|
||||
int max_val;
|
||||
FILE* fptr;
|
||||
fptr = fopen(file, "r");
|
||||
fptr = fopen(filename, "r");
|
||||
if (!fptr)
|
||||
{
|
||||
LOGERROR(ERR_IMG_NAME_INVALID);
|
||||
LOG(file);
|
||||
LOG(filename);
|
||||
return NULL;
|
||||
}
|
||||
fscanf(fptr, "%s", fmt);
|
||||
m_attr->fmt = fmt[1];
|
||||
fscanf(fptr, "%d %d", &m_attr->width, &m_attr->height);
|
||||
m_attr->len = m_attr->width * m_attr->height;
|
||||
metadata->fmt = fmt[1];
|
||||
fscanf(fptr, "%d %d", &metadata->width, &metadata->height);
|
||||
metadata->len = metadata->width * metadata->height;
|
||||
fscanf(fptr, "%d", &max_val);
|
||||
fgetc(fptr);
|
||||
unsigned char* img_buf = malloc(m_attr->len * 3);
|
||||
unsigned char* img_buf = malloc(metadata->len * 3);
|
||||
if (!img_buf)
|
||||
{
|
||||
LOGERROR(ERR_BUF_NULL);
|
||||
return NULL;
|
||||
}
|
||||
unsigned int* clr_buf = malloc(m_attr->len * sizeof(unsigned int));
|
||||
unsigned int* clr_buf = malloc(metadata->len * sizeof(unsigned int));
|
||||
if (!clr_buf)
|
||||
{
|
||||
free(img_buf);
|
||||
LOGERROR(ERR_BUF_NULL);
|
||||
return NULL;
|
||||
}
|
||||
if (m_attr->fmt == '3')
|
||||
if (metadata->fmt == '3')
|
||||
{
|
||||
for (int i = 0; i < m_attr->len; i++)
|
||||
for (int i = 0; i < metadata->len; i++)
|
||||
{
|
||||
fscanf(fptr, "%hhu %hhu %hhu", &red, &green, &blue);
|
||||
clr_buf[i] = ENCODE_RGB(red, green, blue);
|
||||
}
|
||||
}
|
||||
else if (m_attr->fmt == '6')
|
||||
else if (metadata->fmt == '6')
|
||||
{
|
||||
fread(img_buf, 3, m_attr->len, fptr);
|
||||
fread(img_buf, 3, metadata->len, fptr);
|
||||
|
||||
for (int i = 0; i < m_attr->len; i++)
|
||||
for (int i = 0; i < metadata->len; i++)
|
||||
{
|
||||
red = img_buf[i * 3];
|
||||
green = img_buf[i * 3 + 1];
|
||||
@@ -69,14 +69,14 @@ read_ppm(const char* file, PPM* m_attr)
|
||||
}
|
||||
|
||||
int
|
||||
write_ppm(const unsigned int* buf, const PPM img, const char* name)
|
||||
write_ppm(const unsigned int* buf, const PPM metadata, const char* filename)
|
||||
{
|
||||
if (!buf)
|
||||
{
|
||||
LOGERROR(ERR_BUF_NULL);
|
||||
return ERR_BUF_NULL;
|
||||
}
|
||||
unsigned char* dst_buf = malloc(img.len * 3);
|
||||
unsigned char* dst_buf = malloc(metadata.len * 3);
|
||||
if (!dst_buf)
|
||||
{
|
||||
LOGERROR(ERR_BUF_NULL);
|
||||
@@ -85,14 +85,14 @@ write_ppm(const unsigned int* buf, const PPM img, const char* name)
|
||||
LOG("Encoding");
|
||||
FILE* fptr;
|
||||
|
||||
if (img.fmt == '3')
|
||||
if (metadata.fmt == '3')
|
||||
{
|
||||
fptr = fopen(name, "w");
|
||||
fptr = fopen(filename, "w");
|
||||
}
|
||||
|
||||
if (img.fmt == '6')
|
||||
if (metadata.fmt == '6')
|
||||
{
|
||||
fptr = fopen(name, "wb");
|
||||
fptr = fopen(filename, "wb");
|
||||
}
|
||||
|
||||
if (!fptr)
|
||||
@@ -102,10 +102,11 @@ write_ppm(const unsigned int* buf, const PPM img, const char* name)
|
||||
return ERR_FILE_NULL;
|
||||
}
|
||||
|
||||
fprintf(fptr, "P%c\n%d %d\n255\n", img.fmt, img.width, img.height);
|
||||
if (img.fmt == '3')
|
||||
fprintf(fptr, "P%c\n%d %d\n255\n", metadata.fmt, metadata.width,
|
||||
metadata.height);
|
||||
if (metadata.fmt == '3')
|
||||
{
|
||||
for (int i = 0; i < img.len; i++)
|
||||
for (int i = 0; i < metadata.len; i++)
|
||||
{
|
||||
fprintf(fptr, "%d %d %d ", DECODE_R(buf[i]),
|
||||
DECODE_G(buf[i]), DECODE_B(buf[i]));
|
||||
@@ -116,15 +117,15 @@ write_ppm(const unsigned int* buf, const PPM img, const char* name)
|
||||
}
|
||||
}
|
||||
|
||||
if (img.fmt == '6')
|
||||
if (metadata.fmt == '6')
|
||||
{
|
||||
for (int i = 0; i < img.len; i++)
|
||||
for (int i = 0; i < metadata.len; i++)
|
||||
{
|
||||
dst_buf[i * 3] = DECODE_R(buf[i]);
|
||||
dst_buf[i * 3 + 1] = DECODE_G(buf[i]);
|
||||
dst_buf[i * 3 + 2] = DECODE_B(buf[i]);
|
||||
}
|
||||
fwrite(dst_buf, 1, img.len * 3, fptr);
|
||||
fwrite(dst_buf, 1, metadata.len * 3, fptr);
|
||||
}
|
||||
fclose(fptr);
|
||||
free(dst_buf);
|
||||
@@ -133,41 +134,41 @@ write_ppm(const unsigned int* buf, const PPM img, const char* name)
|
||||
}
|
||||
|
||||
unsigned int*
|
||||
read_jpeg(JPEG* m_attr)
|
||||
read_jpeg(JPEG* metadata)
|
||||
{
|
||||
LOG("Decoding");
|
||||
tjhandle tjdecompress = tj3Init(TJINIT_DECOMPRESS);
|
||||
unsigned char* jpeg_buf = NULL;
|
||||
FILE* infile = fopen(m_attr->name, "rb");
|
||||
FILE* infile = fopen(metadata->name, "rb");
|
||||
if (!infile)
|
||||
{
|
||||
LOGERROR(ERR_FILE_NULL);
|
||||
return NULL;
|
||||
}
|
||||
fseek(infile, 0, SEEK_END);
|
||||
m_attr->len = ftell(infile);
|
||||
metadata->len = ftell(infile);
|
||||
fseek(infile, 0, SEEK_SET);
|
||||
jpeg_buf = (unsigned char*)malloc(m_attr->len);
|
||||
fread(jpeg_buf, 1, m_attr->len, infile);
|
||||
jpeg_buf = (unsigned char*)malloc(metadata->len);
|
||||
fread(jpeg_buf, 1, metadata->len, infile);
|
||||
fclose(infile);
|
||||
if (tj3DecompressHeader(tjdecompress, jpeg_buf, m_attr->len) < 0)
|
||||
if (tj3DecompressHeader(tjdecompress, jpeg_buf, metadata->len) < 0)
|
||||
{
|
||||
LOGERROR(ERR_JHEADER);
|
||||
LOG(tj3GetErrorStr(tjdecompress));
|
||||
free(jpeg_buf);
|
||||
return NULL;
|
||||
}
|
||||
m_attr->width = tj3Get(tjdecompress, TJPARAM_JPEGWIDTH);
|
||||
m_attr->height = tj3Get(tjdecompress, TJPARAM_JPEGHEIGHT);
|
||||
m_attr->len = m_attr->width * m_attr->height;
|
||||
metadata->width = tj3Get(tjdecompress, TJPARAM_JPEGWIDTH);
|
||||
metadata->height = tj3Get(tjdecompress, TJPARAM_JPEGHEIGHT);
|
||||
metadata->len = metadata->width * metadata->height;
|
||||
unsigned int* pixels =
|
||||
malloc(m_attr->width * m_attr->height * sizeof(unsigned int));
|
||||
malloc(metadata->width * metadata->height * sizeof(unsigned int));
|
||||
if (!pixels)
|
||||
{
|
||||
LOGERROR(ERR_BUF_NULL);
|
||||
return NULL;
|
||||
}
|
||||
tj3Decompress8(tjdecompress, jpeg_buf, m_attr->len,
|
||||
tj3Decompress8(tjdecompress, jpeg_buf, metadata->len,
|
||||
(unsigned char*)pixels, 0, TJPF_BGRA);
|
||||
tj3Destroy(tjdecompress);
|
||||
free(jpeg_buf);
|
||||
@@ -176,7 +177,7 @@ read_jpeg(JPEG* m_attr)
|
||||
}
|
||||
|
||||
int
|
||||
write_jpeg(const unsigned int* src_buf, const JPEG* attr, const char* name)
|
||||
write_jpeg(const unsigned int* buf, const JPEG* metadata, const char* filename)
|
||||
{
|
||||
LOG("Encoding");
|
||||
tjhandle tjcompress = tj3Init(TJINIT_COMPRESS);
|
||||
@@ -184,21 +185,21 @@ write_jpeg(const unsigned int* src_buf, const JPEG* attr, const char* name)
|
||||
size_t dst_size = 0;
|
||||
tj3Set(tjcompress, TJPARAM_QUALITY, 80);
|
||||
tj3Set(tjcompress, TJPARAM_SUBSAMP, TJSAMP_420);
|
||||
if (tj3Compress8(tjcompress, (unsigned char*)src_buf, attr->width, 0,
|
||||
attr->height, TJPF_BGRA, &dst_buf, &dst_size) < 0)
|
||||
if (tj3Compress8(tjcompress, (unsigned char*)buf, metadata->width, 0,
|
||||
metadata->height, TJPF_BGRA, &dst_buf, &dst_size) < 0)
|
||||
{
|
||||
LOGERROR(ERR_JHEADER);
|
||||
LOG(tj3GetErrorStr(tjcompress));
|
||||
return ERR_JHEADER;
|
||||
}
|
||||
FILE* fptr = fopen(name, "wb");
|
||||
FILE* fptr = fopen(filename, "wb");
|
||||
if (!fptr)
|
||||
{
|
||||
tj3Free(dst_buf);
|
||||
LOGERROR(ERR_FILE_NULL);
|
||||
return ERR_FILE_NULL;
|
||||
}
|
||||
if (dst_buf == NULL)
|
||||
if (!dst_buf)
|
||||
{
|
||||
tj3Free(dst_buf);
|
||||
LOGERROR(ERR_BUF_NULL);
|
||||
@@ -220,115 +221,108 @@ write_jpeg(const unsigned int* src_buf, const JPEG* attr, const char* name)
|
||||
}
|
||||
|
||||
void
|
||||
transcode_to_jpeg(PPM* in)
|
||||
transcode_to_jpeg(const char* location)
|
||||
{
|
||||
size_t length = find_extension(in->name);
|
||||
char str2[length];
|
||||
JPEG dst;
|
||||
PPM src;
|
||||
if (!location)
|
||||
{
|
||||
LOGERROR(ERR_IMG_NAME_INVALID);
|
||||
return;
|
||||
}
|
||||
size_t length = find_extension(location);
|
||||
char stem[length];
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
str2[i] = in->name[i];
|
||||
stem[i] = location[i];
|
||||
}
|
||||
char* str3 = ".jpg";
|
||||
char* result = malloc(strlen(str2) + strlen(str3) + 1);
|
||||
if (result != NULL)
|
||||
{
|
||||
strcat(result, str2);
|
||||
strcat(result, str3);
|
||||
}
|
||||
else
|
||||
char* ext = ".jpg";
|
||||
char* result = malloc(strlen(stem) + strlen(ext) + 1);
|
||||
if (!result)
|
||||
{
|
||||
LOGERROR(ERR_MALLOC_NULL);
|
||||
return;
|
||||
}
|
||||
JPEG img;
|
||||
if (!in)
|
||||
{
|
||||
LOGERROR(ERR_IMG_NULL);
|
||||
return;
|
||||
}
|
||||
unsigned int* dst = read_ppm(in->name, in);
|
||||
if (!dst)
|
||||
strcat(result, stem);
|
||||
strcat(result, ext);
|
||||
unsigned int* dst_buf = read_ppm(location, &src);
|
||||
if (!dst_buf)
|
||||
{
|
||||
LOGERROR(ERR_BUF_NULL);
|
||||
return;
|
||||
}
|
||||
img.width = in->width;
|
||||
img.height = in->height;
|
||||
write_jpeg(dst, &img, result);
|
||||
free(dst);
|
||||
dst = inherit_from_ppm(&src);
|
||||
write_jpeg(dst_buf, &dst, result);
|
||||
free(dst_buf);
|
||||
free(result);
|
||||
}
|
||||
|
||||
void
|
||||
transcode_to_ppm(JPEG* in)
|
||||
transcode_to_ppm(const char* location)
|
||||
{
|
||||
size_t length = find_extension(in->name);
|
||||
JPEG src;
|
||||
PPM dst;
|
||||
if (!location)
|
||||
{
|
||||
LOGERROR(ERR_IMG_NAME_INVALID);
|
||||
return;
|
||||
}
|
||||
src.name = (void*)location;
|
||||
size_t length = find_extension(location);
|
||||
char str2[length];
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
str2[i] = in->name[i];
|
||||
str2[i] = location[i];
|
||||
}
|
||||
char* str3 = ".ppm";
|
||||
char* result = malloc(strlen(str2) + strlen(str3) + 1);
|
||||
if (result != NULL)
|
||||
{
|
||||
strcat(result, str2);
|
||||
strcat(result, str3);
|
||||
}
|
||||
else
|
||||
if (!result)
|
||||
{
|
||||
LOGERROR(ERR_MALLOC_NULL);
|
||||
return;
|
||||
}
|
||||
PPM img;
|
||||
if (!in)
|
||||
{
|
||||
LOGERROR(ERR_IMG_NULL);
|
||||
return;
|
||||
}
|
||||
unsigned int* dst = read_jpeg(in);
|
||||
if (!dst)
|
||||
strcat(result, str2);
|
||||
strcat(result, str3);
|
||||
unsigned int* dst_buf = read_jpeg(&src);
|
||||
if (!dst_buf)
|
||||
{
|
||||
LOGERROR(ERR_BUF_NULL);
|
||||
return;
|
||||
}
|
||||
img.width = in->width;
|
||||
img.height = in->height;
|
||||
img.len = img.width * img.height;
|
||||
write_ppm(dst, img, result);
|
||||
free(dst);
|
||||
|
||||
dst = inherit_from_jpeg(&src, '6');
|
||||
write_ppm(dst_buf, dst, result);
|
||||
free(result);
|
||||
free(dst_buf);
|
||||
}
|
||||
|
||||
PPM
|
||||
inherit_from_jpeg(const JPEG* in, const char fmt)
|
||||
inherit_from_jpeg(const JPEG* metadata, const char fmt)
|
||||
{
|
||||
PPM img;
|
||||
if (!in)
|
||||
PPM image;
|
||||
if (!metadata)
|
||||
{
|
||||
LOGERROR(ERR_IMG_NULL);
|
||||
return img;
|
||||
return image;
|
||||
}
|
||||
PPM image = { .width = in->width,
|
||||
.height = in->height,
|
||||
.len = in->len,
|
||||
.fmt = fmt };
|
||||
image.width = metadata->width;
|
||||
image.height = metadata->height;
|
||||
image.len = metadata->len;
|
||||
image.fmt = fmt;
|
||||
return image;
|
||||
}
|
||||
|
||||
JPEG
|
||||
inherit_from_ppm(const PPM* in)
|
||||
inherit_from_ppm(const PPM* metadata)
|
||||
{
|
||||
JPEG blank;
|
||||
if (!in)
|
||||
JPEG image;
|
||||
if (!metadata)
|
||||
{
|
||||
LOGERROR(ERR_IMG_NULL);
|
||||
return blank;
|
||||
return image;
|
||||
}
|
||||
JPEG image = {
|
||||
.width = in->width,
|
||||
.height = in->height,
|
||||
.len = in->len,
|
||||
};
|
||||
image.width = metadata->width;
|
||||
image.height = metadata->height;
|
||||
image.len = metadata->len;
|
||||
return image;
|
||||
}
|
||||
|
||||
+2
-3
@@ -18,9 +18,8 @@
|
||||
int
|
||||
main()
|
||||
{
|
||||
PPM img;
|
||||
img.name = "../assets/IMG_1649_new.ppm";
|
||||
transcode_to_jpeg(&img);
|
||||
char img[] = "../assets/IMG_1649_new.ppm";
|
||||
transcode_to_jpeg(img);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+23
-19
@@ -6,25 +6,27 @@
|
||||
#include "image/utils.h"
|
||||
|
||||
unsigned int*
|
||||
u32_flop(const unsigned int* buf, const PPM img)
|
||||
u32_flop(const unsigned int* buf, const int width, const int height)
|
||||
{
|
||||
int len, idx;
|
||||
if (!buf)
|
||||
{
|
||||
LOGERROR(ERR_BUF_NULL);
|
||||
return NULL;
|
||||
}
|
||||
unsigned int* flip = malloc(img.len * sizeof(unsigned int));
|
||||
len = width * height;
|
||||
unsigned int* flip = malloc(len * sizeof(unsigned int));
|
||||
if (!flip)
|
||||
{
|
||||
LOGERROR(ERR_CREATION_FAIL);
|
||||
return NULL;
|
||||
}
|
||||
int idx = 0;
|
||||
for (int i = 0; i < img.height; i++)
|
||||
idx = 0;
|
||||
for (int i = 0; i < height; i++)
|
||||
{
|
||||
for (int k = img.width - 1; k >= 0; k--)
|
||||
for (int k = width - 1; k >= 0; k--)
|
||||
{
|
||||
flip[idx] = buf[(i * img.width) + k];
|
||||
flip[idx] = buf[(i * width) + k];
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
@@ -34,26 +36,28 @@ u32_flop(const unsigned int* buf, const PPM img)
|
||||
}
|
||||
|
||||
unsigned int*
|
||||
u32_flip(const unsigned int* buf, const PPM img)
|
||||
u32_flip(const unsigned int* buf, const int width, const int height)
|
||||
{
|
||||
int len, idx;
|
||||
if (!buf)
|
||||
{
|
||||
LOGERROR(ERR_BUF_NULL);
|
||||
return NULL;
|
||||
}
|
||||
unsigned int* flip = malloc(img.len * sizeof(unsigned int));
|
||||
len = width * height;
|
||||
unsigned int* flip = malloc(len * sizeof(unsigned int));
|
||||
if (!flip)
|
||||
{
|
||||
LOGERROR(ERR_FILE_NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int idx = 0;
|
||||
for (int i = img.height - 1; i >= 0; i--)
|
||||
idx = 0;
|
||||
for (int i = height - 1; i >= 0; i--)
|
||||
{
|
||||
for (int k = 0; k < img.width; k++)
|
||||
for (int k = 0; k < width; k++)
|
||||
{
|
||||
flip[idx] = buf[(i * img.width) + k];
|
||||
flip[idx] = buf[(i * width) + k];
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
@@ -63,26 +67,26 @@ u32_flip(const unsigned int* buf, const PPM img)
|
||||
}
|
||||
|
||||
unsigned int*
|
||||
u32_rotate(const unsigned int* buf, PPM* m_img)
|
||||
u32_rotate(const unsigned int* buf, PPM* metadata)
|
||||
{
|
||||
if (!buf)
|
||||
{
|
||||
LOGERROR(ERR_BUF_NULL);
|
||||
return NULL;
|
||||
}
|
||||
if (!m_img)
|
||||
if (!metadata)
|
||||
{
|
||||
LOGERROR(ERR_IMG_NULL);
|
||||
return NULL;
|
||||
}
|
||||
unsigned int* mask = malloc(m_img->len * sizeof(unsigned int));
|
||||
unsigned int* mask = malloc(metadata->len * sizeof(unsigned int));
|
||||
if (!mask)
|
||||
{
|
||||
LOGERROR(ERR_BUF_NULL);
|
||||
return NULL;
|
||||
}
|
||||
int old_width = m_img->width;
|
||||
int old_height = m_img->height;
|
||||
int old_width = metadata->width;
|
||||
int old_height = metadata->height;
|
||||
for (int row = 0; row < old_height; row++)
|
||||
{
|
||||
for (int col = 0; col < old_width; col++)
|
||||
@@ -94,8 +98,8 @@ u32_rotate(const unsigned int* buf, PPM* m_img)
|
||||
buf[(row * old_width) + col];
|
||||
}
|
||||
}
|
||||
m_img->width = old_height;
|
||||
m_img->height = old_width;
|
||||
metadata->width = old_height;
|
||||
metadata->height = old_width;
|
||||
free((void*)buf);
|
||||
return mask;
|
||||
}
|
||||
|
||||
+9
-8
@@ -37,26 +37,27 @@ u64to_u32(const unsigned long clr, const unsigned long u64_div)
|
||||
}
|
||||
|
||||
void __attribute__((overloadable))
|
||||
print_attr(const PPM* src)
|
||||
print_attr(const PPM* metadata)
|
||||
{
|
||||
printf("Name: %s\nFMT: %c\nWidth: %i, Height: %i\nLength: %i\n",
|
||||
src->name, src->fmt, src->width, src->height, src->len);
|
||||
metadata->name, metadata->fmt, metadata->width, metadata->height,
|
||||
metadata->len);
|
||||
}
|
||||
|
||||
void __attribute__((overloadable))
|
||||
print_attr(const JPEG* src)
|
||||
print_attr(const JPEG* metadata)
|
||||
{
|
||||
printf("Name: %s\nWidth: %i, Height: %i\nLength: %i\n", src->name,
|
||||
src->width, src->height, src->len);
|
||||
printf("Name: %s\nWidth: %i, Height: %i\nLength: %i\n", metadata->name,
|
||||
metadata->width, metadata->height, metadata->len);
|
||||
}
|
||||
|
||||
size_t
|
||||
find_extension(const char* n)
|
||||
find_extension(const char* str)
|
||||
{
|
||||
size_t length = strlen(n);
|
||||
size_t length = strlen(str);
|
||||
for (int i = length; i >= 0; i--)
|
||||
{
|
||||
if (n[i] == '.')
|
||||
if (str[i] == '.')
|
||||
{
|
||||
return i;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user