Add reading alpha
This commit is contained in:
		| @@ -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; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user