Compare commits

..

7 Commits

Author SHA1 Message Date
35a33e2fa6 Reformat 2024-05-26 17:56:32 +01:00
1c08881dfb Ensure pthread_join succeeded before returning true 2024-05-26 17:51:28 +01:00
7593eb4732 Add release build 2024-05-26 15:54:01 +01:00
ec2835e900 Read the image in a separate thread and ensure each strip is read in its own thread (#1)
Reviewed-on: #1
Co-authored-by: Abdelrahman <said.abdelrahman89@gmail.com>
Co-committed-by: Abdelrahman <said.abdelrahman89@gmail.com>
2024-05-26 14:44:12 +00:00
53c70156a6 Update .gitignore 2024-05-26 14:52:42 +01:00
ad4b7b40aa Update .gitignore 2024-05-26 14:52:00 +01:00
aa12b62e7e Fix compile script 2024-05-26 14:51:53 +01:00
3 changed files with 149 additions and 47 deletions

25
compile
View File

@@ -1,7 +1,28 @@
#!/bin/bash
BUILD_TYPE="debug"
while [[ $# > 0 ]];do
case $1 in
--release)
BUILD_TYPE="release"
shift
;;
*|-*|--*)
echo "Unknown option $1"
exit 1
;;
esac
done
CC=clang
if [[ $BUILD_TYPE == "release" ]]; then
CFLAGS="-O3 -Wall -Werror -pedantic"
else
CFLAGS="-g -Wall -Werror -pedantic -fsanitize=address -fsanitize=undefined -DDEBUG"
fi
INCLUDES="\
-I$(find ./src -type d | xargs -I{} echo -n "-I{} ") \
$(find intern/wizapp/src -type d | xargs -I{} echo -n "-I{} ") \
@@ -13,8 +34,8 @@ LIBS="\
$(pkg-config --libs sdl2) \
"
SRC="\
$(find ./src -name *.c | xargs -I{} echo -n "{} ") \
$(find intern/wizapp/src -type f -name *.c | xargs -I{} echo -n "{} ") \
$(find ./src -name "*.c" | xargs -I{} echo -n "{} ") \
$(find intern/wizapp/src -type f -name "*.c" | xargs -I{} echo -n "{} ") \
"
OUT=tiffread

View File

@@ -4,6 +4,7 @@
#include "tiffread.h"
#include <SDL2/SDL.h>
#include <SDL2/SDL_events.h>
#include <SDL2/SDL_rect.h>
#include <SDL2/SDL_render.h>
#include <SDL2/SDL_surface.h>
#include <SDL2/SDL_video.h>
@@ -18,6 +19,8 @@
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
#define VIEW_AREA_WIDTH 700
#define VIEW_AREA_HEIGHT 500
#define AMASK 0xff000000
#define BMASK 0x00ff0000
@@ -34,6 +37,7 @@ struct point {
internal void write_debug_ppm6(const Image *img);
internal void *load_tiff_image(void *args);
internal SDL_Rect get_dest_rect(SDL_Surface *surface);
typedef struct img_thread_args ImgThreadArgs;
struct img_thread_args {
@@ -90,12 +94,7 @@ int main(int argc, char *argv[]) {
goto MAIN_DESTROY_SURFACE;
}
SDL_Rect dest = {
.h = surface->h,
.w = surface->w,
.x = (WINDOW_WIDTH - surface->w) / 2,
.y = (WINDOW_HEIGHT - surface->h) / 2,
};
SDL_Rect dest = get_dest_rect(surface);
bool running = true;
@@ -188,3 +187,16 @@ internal void *load_tiff_image(void *args) {
return surface;
}
internal SDL_Rect get_dest_rect(SDL_Surface *surface) {
f64 ratio = (f64)(surface->h) / (f64)(surface->w);
u64 width = surface->w <= VIEW_AREA_WIDTH ? surface->w : VIEW_AREA_WIDTH;
u64 height = width * ratio;
return (SDL_Rect){
.w = width,
.h = height,
.x = (WINDOW_WIDTH - width) / 2,
.y = (WINDOW_HEIGHT - height) / 2,
};
}

View File

@@ -4,8 +4,10 @@
#include "image.h"
#include "mem_arena.h"
#include <assert.h>
#include <bits/pthreadtypes.h>
#include <math.h>
#include <netinet/in.h>
#include <pthread.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
@@ -200,6 +202,7 @@ struct tiff_image {
typedef struct tiff_reader TiffReader;
struct tiff_reader {
const char *filename;
FILE *fp;
TiffHdr header;
TiffIFD ifd;
@@ -207,6 +210,17 @@ struct tiff_reader {
Pixel *pixels;
};
typedef struct strip_thread_args StripThreadArgs;
struct strip_thread_args {
FILE *fp;
const TiffStrip *strip;
u64 pixel_count;
u64 samples_per_pixel;
u64 main_samples;
TiffAlpha alpha;
Pixel *pixel_write_start;
};
internal bool read_tiff_header(TiffReader *reader);
internal bool read_ifd(TiffReader *reader, Arena *arena);
internal bool read_ifd_fields(TiffReader *reader);
@@ -214,7 +228,8 @@ internal void read_alpha(TiffReader *reader);
internal void read_bits_per_sample(TiffReader *reader);
internal bool read_image_pixels(TiffReader *reader, Arena *arena);
internal bool read_strip_data(TiffReader *reader, Arena *arena);
internal void read_strips(TiffReader *reader);
internal bool read_strips(TiffReader *reader);
internal void *read_strip(void *arg);
internal void read_strip_data_field(const TiffReader *reader,
StripDataField *field);
internal bool read_field(const TiffField *field, TiffImage *img);
@@ -231,7 +246,7 @@ Image *read_baseline_tiff(const char *file, Arena *arena) {
goto READ_BASELINE_RETURN_IMG;
}
TiffReader reader = {.fp = fopen(file, "rb")};
TiffReader reader = {.filename = file, .fp = fopen(file, "rb")};
if (!reader.fp) {
goto READ_BASELINE_RETURN_IMG;
}
@@ -534,9 +549,7 @@ internal bool read_image_pixels(TiffReader *reader, Arena *arena) {
return false;
}
read_strips(reader);
return true;
return read_strips(reader);
}
internal bool read_strip_data(TiffReader *reader, Arena *arena) {
@@ -585,31 +598,86 @@ internal bool read_strip_data(TiffReader *reader, Arena *arena) {
return true;
}
internal void read_strips(TiffReader *reader) {
internal bool read_strips(TiffReader *reader) {
u64 position = 0;
u64 main_samples = reader->img.sample_count - reader->img.extra_samples_count;
TiffAlpha alpha = reader->img.alpha;
Pixel *p;
u64 start_offset;
u64 alpha_offset;
StripThreadArgs args[reader->img.strip_count];
pthread_t threads[reader->img.strip_count];
for (u64 i = 0; i < reader->img.strip_count; ++i) {
const TiffStrip *strip = &(reader->img.strips[i]);
u64 pixel_count = strip->byte_count / reader->img.sample_count;
args[i] = (StripThreadArgs){
.fp = fopen(reader->filename, "rb"),
.strip = strip,
.pixel_count = pixel_count,
.samples_per_pixel = reader->img.sample_count,
.main_samples =
reader->img.sample_count - reader->img.extra_samples_count,
.alpha = reader->img.alpha,
.pixel_write_start = &(reader->pixels[position]),
};
for (u64 j = 0; j < strip->byte_count / reader->img.sample_count; ++j) {
p = &(reader->pixels[position]);
start_offset = strip->offset + j * reader->img.sample_count;
alpha_offset = start_offset + main_samples + alpha.sample_offset;
if (!args[i].fp) {
for (u64 j = 0; j < i; ++j) {
fclose(args[j].fp);
}
fread_with_offset(reader->fp, p, main_samples, start_offset);
return false;
}
if (alpha.type == ALPHA_TYPE_UNDEFINED) {
position += pixel_count;
}
for (u64 i = 0; i < reader->img.strip_count; ++i) {
if (pthread_create(&(threads[i]), NULL, read_strip, &(args[i])) != 0) {
for (u64 j = 0; j < i; ++j) {
pthread_cancel(threads[i]);
fclose(args[j].fp);
}
// Close the remaining files
for (u64 j = i; j < reader->img.strip_count; ++j) {
fclose(args[j].fp);
}
return false;
}
}
bool image_loaded = true;
for (u64 i = 0; i < reader->img.strip_count; ++i) {
if (pthread_join(threads[i], NULL) != 0) {
image_loaded = false;
}
fclose(args[i].fp);
}
return image_loaded;
}
internal void *read_strip(void *arg) {
StripThreadArgs *args = (StripThreadArgs *)arg;
Pixel *p;
u64 write_offset = 0;
u64 read_offset;
u64 alpha_offset;
for (u64 j = 0; j < args->pixel_count; ++j) {
p = args->pixel_write_start + write_offset;
read_offset = args->strip->offset + j * args->samples_per_pixel;
alpha_offset = read_offset + args->main_samples + args->alpha.sample_offset;
fread_with_offset(args->fp, p, args->main_samples, read_offset);
if (args->alpha.type == ALPHA_TYPE_UNDEFINED) {
p->a = 255;
} else {
fread_with_offset(reader->fp, &(p->a), 1, alpha_offset);
fread_with_offset(args->fp, &(p->a), 1, alpha_offset);
if (alpha.type == ALPHA_TYPE_UNASSOCIATED) {
if (args->alpha.type == ALPHA_TYPE_UNASSOCIATED) {
f32 a_norm = u8_normalise(p->a);
p->r = u8_denormalise(u8_normalise(p->r) * a_norm);
@@ -618,9 +686,10 @@ internal void read_strips(TiffReader *reader) {
}
}
++position;
}
++write_offset;
}
return NULL;
}
internal void read_strip_data_field(const TiffReader *reader,