Add reading alpha
This commit is contained in:
parent
3e3c4d27fe
commit
f0d4108a64
@ -27,6 +27,9 @@
|
|||||||
#define NULL_TIFF_IMAGE ((TiffImage){0})
|
#define NULL_TIFF_IMAGE ((TiffImage){0})
|
||||||
#define IS_NULL_IMAGE(IMG) (IMG.type == TIFF_IMAGE_TYPE_INVALID)
|
#define IS_NULL_IMAGE(IMG) (IMG.type == TIFF_IMAGE_TYPE_INVALID)
|
||||||
|
|
||||||
|
#define NULL_TIFF_ALPHA ((TiffAlpha){0})
|
||||||
|
#define IS_NULL_ALPHA(ALPHA) (ALPHA.type == ALPHA_TYPE_UNDEFINED)
|
||||||
|
|
||||||
#define INVALID_SAMPLE_COUNT 0
|
#define INVALID_SAMPLE_COUNT 0
|
||||||
#define INVALID_ROWS_PER_STRIP 0
|
#define INVALID_ROWS_PER_STRIP 0
|
||||||
#define INVALID_STRIP_COUNT 0
|
#define INVALID_STRIP_COUNT 0
|
||||||
@ -59,6 +62,7 @@ struct strip_data_field {
|
|||||||
internal TiffHdr read_tiff_header(const TiffReader *reader);
|
internal TiffHdr read_tiff_header(const TiffReader *reader);
|
||||||
internal TiffIFD read_ifd(const TiffReader *reader, Arena *arena);
|
internal TiffIFD read_ifd(const TiffReader *reader, Arena *arena);
|
||||||
internal TiffImage read_ifd_fields(const TiffReader *reader);
|
internal TiffImage read_ifd_fields(const TiffReader *reader);
|
||||||
|
internal TiffAlpha read_alpha(const TiffReader *reader, TiffImage *img);
|
||||||
internal Pixel *load_image_pixels(TiffReader *reader, Arena *arena);
|
internal Pixel *load_image_pixels(TiffReader *reader, Arena *arena);
|
||||||
internal bool read_strip_data(TiffReader *reader, Arena *arena);
|
internal bool read_strip_data(TiffReader *reader, Arena *arena);
|
||||||
internal void read_strips(const TiffReader *reader, Pixel *buf);
|
internal void read_strips(const TiffReader *reader, Pixel *buf);
|
||||||
@ -253,11 +257,14 @@ internal TiffImage read_ifd_fields(const TiffReader *reader) {
|
|||||||
goto READ_FIELDS_RETURN_IMAGE;
|
goto READ_FIELDS_RETURN_IMAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
img_out.alpha = read_alpha(reader, &img_out);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
// clang-format off
|
// clang-format off
|
||||||
printf("SIZE (width, height) : %u, %u\n", img_out.image_width, img_out.image_length);
|
printf("SIZE (width, height) : %u, %u\n", img_out.image_width, img_out.image_length);
|
||||||
printf("SAMPLES (bits per sample, count, is offset) : %u, %u, %u\n", img_out.bits_per_sample, img_out.sample_count, img_out.bits_per_sample_offset);
|
printf("SAMPLES (bits per sample, count, is offset) : %u, %u, %u\n", img_out.bits_per_sample, img_out.sample_count, img_out.bits_per_sample_offset);
|
||||||
printf("EXTRA SAMPLES (samples, count, is offset) : %u, %u, %u\n", img_out.extra_samples, img_out.extra_samples_count, img_out.extra_samples_offset);
|
printf("EXTRA SAMPLES (samples, count, is offset) : %u, %u, %u\n", img_out.extra_samples, img_out.extra_samples_count, img_out.extra_samples_offset);
|
||||||
|
printf("ALPHA (type, offset) : %u, %u\n", img_out.alpha.type, img_out.alpha.sample_offset);
|
||||||
printf("SAMPLES PER PIXEL : %u\n", img_out.sample_count);
|
printf("SAMPLES PER PIXEL : %u\n", img_out.sample_count);
|
||||||
printf("PHOTOMETRIC INTERPRETATION : %u\n", img_out.photometric_interpretation);
|
printf("PHOTOMETRIC INTERPRETATION : %u\n", img_out.photometric_interpretation);
|
||||||
printf("ROWS PER STRIP (rows, strip count) : %u, %u\n", img_out.rows_per_strip, img_out.strip_count);
|
printf("ROWS PER STRIP (rows, strip count) : %u, %u\n", img_out.rows_per_strip, img_out.strip_count);
|
||||||
@ -270,6 +277,39 @@ READ_FIELDS_RETURN_IMAGE:
|
|||||||
return img_out;
|
return img_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal TiffAlpha read_alpha(const TiffReader *reader, TiffImage *img) {
|
||||||
|
TiffAlpha alpha = NULL_TIFF_ALPHA;
|
||||||
|
u16 samples[img->extra_samples_count];
|
||||||
|
|
||||||
|
if (img->extra_samples_count == 0) {
|
||||||
|
goto READ_ALPHA_RETURN;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 byte_count = TIFF_SHORT_BYTE_COUNT * img->extra_samples_count;
|
||||||
|
memset(samples, 0, byte_count);
|
||||||
|
|
||||||
|
if (img->extra_samples_offset) {
|
||||||
|
read_from_file_with_offset(reader->fp, samples, byte_count,
|
||||||
|
img->extra_samples);
|
||||||
|
} else {
|
||||||
|
memcpy(samples, &(img->extra_samples), byte_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u32 i = 0; i < img->extra_samples_count; ++i) {
|
||||||
|
u16 *sample = &(samples[i]);
|
||||||
|
if (*sample == TIFF_EXTRA_SAMPLE_ASSOCIATED_ALPHA ||
|
||||||
|
*sample == TIFF_EXTRA_SAMPLE_UNASSOCIATED_ALPHA) {
|
||||||
|
alpha.type = *sample == TIFF_EXTRA_SAMPLE_ASSOCIATED_ALPHA
|
||||||
|
? ALPHA_TYPE_ASSOCIATED
|
||||||
|
: ALPHA_TYPE_UNASSOCIATED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
READ_ALPHA_RETURN:
|
||||||
|
return alpha;
|
||||||
|
}
|
||||||
|
|
||||||
internal Pixel *load_image_pixels(TiffReader *reader, Arena *arena) {
|
internal Pixel *load_image_pixels(TiffReader *reader, Arena *arena) {
|
||||||
Pixel *buf = NULL;
|
Pixel *buf = NULL;
|
||||||
u64 img_byte_count =
|
u64 img_byte_count =
|
||||||
@ -345,17 +385,27 @@ internal bool read_strip_data(TiffReader *reader, Arena *arena) {
|
|||||||
|
|
||||||
internal void read_strips(const TiffReader *reader, Pixel *buf) {
|
internal void read_strips(const TiffReader *reader, Pixel *buf) {
|
||||||
u64 position = 0;
|
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;
|
||||||
|
|
||||||
for (u64 i = 0; i < reader->img.strip_count; ++i) {
|
for (u64 i = 0; i < reader->img.strip_count; ++i) {
|
||||||
const TiffStrip *strip = &(reader->img.strips[i]);
|
const TiffStrip *strip = &(reader->img.strips[i]);
|
||||||
|
|
||||||
for (u64 j = 0; j < strip->byte_count / reader->img.sample_count; ++j) {
|
for (u64 j = 0; j < strip->byte_count / reader->img.sample_count; ++j) {
|
||||||
Pixel *p = &(buf[position]);
|
p = &(buf[position]);
|
||||||
|
start_offset = strip->offset + j * reader->img.sample_count;
|
||||||
|
alpha_offset = start_offset + main_samples + alpha.sample_offset;
|
||||||
|
|
||||||
read_from_file_with_offset(reader->fp, p, reader->img.sample_count,
|
read_from_file_with_offset(reader->fp, p, main_samples, start_offset);
|
||||||
strip->offset + j * reader->img.sample_count);
|
|
||||||
|
|
||||||
if (reader->img.sample_count == 3) {
|
if (alpha.type == ALPHA_TYPE_UNDEFINED) {
|
||||||
p->a = 255;
|
p->a = 255;
|
||||||
|
} else {
|
||||||
|
read_from_file_with_offset(reader->fp, &(p->a), 1, alpha_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
++position;
|
++position;
|
||||||
|
@ -111,6 +111,18 @@ struct IFD {
|
|||||||
u32 next_ifd;
|
u32 next_ifd;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ALPHA_TYPE_UNDEFINED = 0,
|
||||||
|
ALPHA_TYPE_ASSOCIATED,
|
||||||
|
ALPHA_TYPE_UNASSOCIATED,
|
||||||
|
} AlphaType;
|
||||||
|
|
||||||
|
typedef struct tiff_alpha TiffAlpha;
|
||||||
|
struct tiff_alpha {
|
||||||
|
AlphaType type;
|
||||||
|
u32 sample_offset;
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct tiff_strip TiffStrip;
|
typedef struct tiff_strip TiffStrip;
|
||||||
struct tiff_strip {
|
struct tiff_strip {
|
||||||
u32 offset;
|
u32 offset;
|
||||||
@ -139,6 +151,7 @@ struct tiff_image {
|
|||||||
u32 extra_samples;
|
u32 extra_samples;
|
||||||
u32 extra_samples_count;
|
u32 extra_samples_count;
|
||||||
bool extra_samples_offset;
|
bool extra_samples_offset;
|
||||||
|
TiffAlpha alpha;
|
||||||
TiffStrip *strips;
|
TiffStrip *strips;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user