-
Notifications
You must be signed in to change notification settings - Fork 1
Add lossless codec(Delta + Zlib compression) and support for benchmarking #29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: base
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,5 +7,6 @@ kodak/ | |
| reconstructed/ | ||
| compressed/ | ||
| mycodec | ||
| lossless | ||
| image_data/ | ||
| images/ | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,17 +2,29 @@ CC = g++ | |
| FLAGS = -std=c++11 -O3 -fpermissive -fPIC -fopenmp | ||
| LDLFAGS =-lpng -lz -lfftw3 -lfftw3_omp | ||
|
|
||
| SRCS = driver.cpp refpng.cpp mycodec.cpp rle.cpp delta.cpp bucket.cpp color_transform.cpp compress.cpp dct.cpp utils.cpp | ||
| OBJS = $(SRCS:.cpp=.o) | ||
| TARGET = mycodec | ||
| SRCS_COMMON = refpng.cpp rle.cpp delta.cpp bucket.cpp color_transform.cpp compress.cpp dct.cpp utils.cpp | ||
| SRCS_JPEG = mycodec.cpp driver.cpp | ||
| SRCS_PNG = lossless.cpp driver_lossless.cpp | ||
|
Comment on lines
+5
to
+7
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Typo in linking flags variable impacting build. -LDLFAGS =-lpng -lz -lfftw3 -lfftw3_omp
+LDFLAGS = -lpng -lz -lfftw3 -lfftw3_omp
$(JPEG): $(COMMON_OBJS) $(JPEG_OBJS)
- $(CC) $(FLAGS) -o $(JPEG) $(COMMON_OBJS) $(JPEG_OBJS) $(LDLFAGS)
+ $(CC) $(FLAGS) -o $(JPEG) $(COMMON_OBJS) $(JPEG_OBJS) $(LDFLAGS)
$(LOSSLESS): $(COMMON_OBJS) $(PNG_OBJS)
- $(CC) $(FLAGS) -o $(LOSSLESS) $(COMMON_OBJS) $(PNG_OBJS) $(LDLFAGS)
+ $(CC) $(FLAGS) -o $(LOSSLESS) $(COMMON_OBJS) $(PNG_OBJS) $(LDFLAGS)Also applies to: 9-11, 13-18, 23-24, 26-27, 30-30 |
||
|
|
||
| all: $(TARGET) | ||
| COMMON_OBJS = $(SRCS_COMMON:.cpp=.o) | ||
| JPEG_OBJS = $(SRCS_JPEG:.cpp=.o) | ||
| PNG_OBJS = $(SRCS_PNG:.cpp=.o) | ||
|
|
||
| JPEG = mycodec | ||
| LOSSLESS = lossless | ||
|
|
||
| all: $(JPEG) $(LOSSLESS) | ||
| jpeg: $(JPEG) | ||
| png: $(LOSSLESS) | ||
|
|
||
| %.o: %.cpp | ||
| $(CC) $(FLAGS) -c $< -o $@ $(LDFLAGS) | ||
|
|
||
| $(TARGET): $(OBJS) | ||
| $(CC) $(FLAGS) -o $(TARGET) $(OBJS) $(LDLFAGS) | ||
| $(JPEG): $(COMMON_OBJS) $(JPEG_OBJS) | ||
| $(CC) $(FLAGS) -o $(JPEG) $(COMMON_OBJS) $(JPEG_OBJS) $(LDLFAGS) | ||
|
|
||
| $(LOSSLESS): $(COMMON_OBJS) $(PNG_OBJS) | ||
| $(CC) $(FLAGS) -o $(LOSSLESS) $(COMMON_OBJS) $(PNG_OBJS) $(LDLFAGS) | ||
|
|
||
| clean: | ||
| rm -f $(OBJS) $(TARGET) | ||
| rm -f $(COMMON_OBJS) $(JPEG_OBJS) $(PNG_OBJS) $(JPEG) $(LOSSLESS) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,108 @@ | ||
| #include <iostream> | ||
| #include <fstream> | ||
| #include <vector> | ||
| #include <string> | ||
| #include <sstream> | ||
| #include "refpng.h" | ||
| #include "mycodec.h" | ||
| #include "compress.h" | ||
|
|
||
| using namespace std; | ||
|
|
||
| string file_type(string filename) { | ||
| int loc = filename.find_last_of("."); | ||
| string file_type = filename.substr(loc + 1); | ||
| return file_type; | ||
| } | ||
|
|
||
| string get_filename(string filepath){ | ||
| stringstream ss(filepath); | ||
| string folder, filename; | ||
| getline(ss, folder, '/'); | ||
| getline(ss, filename, '.'); | ||
| return filename; | ||
| } | ||
|
|
||
| vector<uint8_t> read_png_image(string input_filepath) { | ||
| read_png_file(input_filepath.c_str()); | ||
| string filename = get_filename(input_filepath); | ||
|
|
||
| vector<uint8_t> image; | ||
| image.clear(); | ||
| copy_row_pointers_to_vector(image, row_pointers, width, height); | ||
| return image; | ||
| } | ||
|
|
||
| void write_png_image(vector<uint8_t>& image, string compressed_filepath, string output_filepath) { | ||
| row_pointers = copy_vector_to_row_pointers(image, width, height); | ||
| write_png_file(output_filepath.c_str()); | ||
| } | ||
|
|
||
| vector<uint8_t> read_ppm_image(string input_filepath) { | ||
| ifstream infile(input_filepath, ios::in | ios::binary); | ||
| string magic_number; | ||
| int max_color_value; | ||
| infile >> magic_number; | ||
| infile >> width >> height; // setting global values | ||
| infile >> max_color_value; | ||
|
|
||
| #ifdef debug | ||
| cout << "Reading PPM image from file: with width: " << width << " and height: " << height << endl; | ||
| cout << "Max color value: " << max_color_value << endl; | ||
| #endif | ||
|
|
||
| int num_pixels = width * height * 3; | ||
| vector<uint8_t> image(num_pixels); | ||
| infile.read((char*)&image[0], num_pixels * sizeof(uint8_t)); | ||
| infile.close(); | ||
|
|
||
| vector<vector<uint8_t>> channels = separate_channels(image, width * height); | ||
|
|
||
| // channels --> 1 --> actual red, 2 --> actual green, 0 --> actual blue | ||
|
|
||
| channels = {channels[1], channels[2], channels[0]}; | ||
| image = merge_channels(channels, width * height); | ||
|
|
||
| cout << "Number of image pixels: " << image.size() << endl; | ||
|
|
||
| return image; | ||
| } | ||
|
|
||
|
|
||
| int main(int argc, char* argv[]) { | ||
| if(argc != 4) { | ||
| cout << "Usage: " << argv[0] << " <input_file> <compressed_file> <output_file>" << endl; | ||
| return 1; | ||
| } | ||
| string input_filepath = argv[1], compressed_filepath = argv[2], output_filepath = argv[3]; | ||
| cout << "Original file size: " << (file_size(argv[1]) / 1024) << " KB" << endl; | ||
|
|
||
| omp_set_num_threads(40); | ||
| fftw_init_threads(); | ||
| fftw_plan_with_nthreads(omp_get_max_threads()); | ||
|
|
||
| if(file_type(input_filepath) == "png"){ | ||
| // Read and compress | ||
| vector<uint8_t> image = read_png_image(input_filepath); | ||
| compress_image(image, width, height, compressed_filepath); | ||
|
|
||
| // Decompress and write | ||
| vector<uint8_t> restored_image = decompress_image(compressed_filepath); | ||
| write_png_image(restored_image, compressed_filepath, output_filepath); | ||
| } else if(file_type(input_filepath) == "ppm") { | ||
| vector<uint8_t> image = read_ppm_image(input_filepath); | ||
| compress_image(image, width, height, compressed_filepath); | ||
|
|
||
| // Decompress and write | ||
| vector<uint8_t> restored_image = decompress_image(compressed_filepath); | ||
| write_png_image(restored_image, compressed_filepath, output_filepath); | ||
| } else { | ||
| cout << "Input file is not a PNG or PPM image." << endl; | ||
| return 1; | ||
| } | ||
|
|
||
| fftw_cleanup_threads(); | ||
|
|
||
|
|
||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| #include "mycodec.h" | ||
| #include "compress.h" | ||
|
|
||
| using namespace std; | ||
|
|
||
| /* | ||
| Ideas: | ||
| 1. RLE encoding: <intensity[0,255], count>: a) directly including all channels --> image blows up to 4MB, b) for each channel separately | ||
| 2. RGB to YCbCr conversion | ||
| 3. Bucketing CbCr values into 128 buckets and representing each intensity in 7 bits using bitsets --> lossy | ||
| 4. ZLib compression | ||
| 5. DCT + Quantization | ||
| */ | ||
|
|
||
| // Combination 1: Bucketing + Delta + ZLib (RLE worsens compression) | ||
| string compress_image(vector<uint8_t>& image, int width, int height, string filepath) { | ||
| image = delta_encode<uint8_t> (image); | ||
| vector<char> buffer = write_vec_to_buffer<uint8_t>(image, width, height, filepath); | ||
| compress(buffer, filepath); | ||
| return filepath; | ||
| } | ||
|
|
||
| vector<uint8_t> decompress_image(string filename) { | ||
| vector<char> buffer = decompress1(filename); | ||
| vector<uint8_t> image = read_vec_from_buffer<uint8_t>(buffer); | ||
| image = delta_decode<uint8_t>(image); | ||
| return image; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Enhance input validation and error handling in main script
The main script logic could be improved with:
Here's a suggested improvement: