Read bits per sample
This commit is contained in:
		| @@ -39,6 +39,9 @@ | ||||
| #define TIFF_SHORT_BYTE_COUNT field_types[TIFF_FIELD_TYPE_SHORT].byte_count | ||||
| #define TIFF_LONG_BYTE_COUNT field_types[TIFF_FIELD_TYPE_LONG].byte_count | ||||
|  | ||||
| #define RGB_SAMPLE_COUNT 3 | ||||
| #define MINIMUM_BITS_PER_SAMPLE 8 | ||||
|  | ||||
| #define TEMP_ARENA_CAPACITY (20 * 1024 * 1024) | ||||
|  | ||||
| typedef struct tiff_reader TiffReader; | ||||
| @@ -63,6 +66,8 @@ internal TiffHdr read_tiff_header(const TiffReader *reader); | ||||
| internal TiffIFD read_ifd(const TiffReader *reader, Arena *arena); | ||||
| internal TiffImage read_ifd_fields(const TiffReader *reader); | ||||
| internal TiffAlpha read_alpha(const TiffReader *reader, TiffImage *img); | ||||
| internal TiffSampleBits read_bits_per_sample(const TiffReader *reader, | ||||
|                                              TiffImage *img); | ||||
| internal Pixel *load_image_pixels(TiffReader *reader, Arena *arena); | ||||
| internal bool read_strip_data(TiffReader *reader, Arena *arena); | ||||
| internal void read_strips(const TiffReader *reader, Pixel *buf); | ||||
| @@ -127,6 +132,11 @@ Image *read_baseline_tiff(const char *file, Arena *arena) { | ||||
|  | ||||
|   assert((reader.img.type == TIFF_IMAGE_TYPE_RGB) && | ||||
|          "Currently, only RGB images are supported"); | ||||
|   assert((reader.img.rgba_bits_per_sample.r == MINIMUM_BITS_PER_SAMPLE && | ||||
|           reader.img.rgba_bits_per_sample.g == MINIMUM_BITS_PER_SAMPLE && | ||||
|           reader.img.rgba_bits_per_sample.b == MINIMUM_BITS_PER_SAMPLE && | ||||
|           reader.img.rgba_bits_per_sample.a == MINIMUM_BITS_PER_SAMPLE) && | ||||
|          "Currently, only 8-bit images are supported"); | ||||
|  | ||||
|   reader.pixels = load_image_pixels(&reader, temp_arena); | ||||
|   if (!reader.pixels) { | ||||
| @@ -258,6 +268,7 @@ internal TiffImage read_ifd_fields(const TiffReader *reader) { | ||||
|   } | ||||
|  | ||||
|   img_out.alpha = read_alpha(reader, &img_out); | ||||
|   img_out.rgba_bits_per_sample = read_bits_per_sample(reader, &img_out); | ||||
|  | ||||
| #ifdef DEBUG | ||||
|   // clang-format off | ||||
| @@ -302,6 +313,7 @@ internal TiffAlpha read_alpha(const TiffReader *reader, TiffImage *img) { | ||||
|       alpha.type = *sample == TIFF_EXTRA_SAMPLE_ASSOCIATED_ALPHA | ||||
|                        ? ALPHA_TYPE_ASSOCIATED | ||||
|                        : ALPHA_TYPE_UNASSOCIATED; | ||||
|       alpha.sample_offset = i; | ||||
|       break; | ||||
|     } | ||||
|   } | ||||
| @@ -310,6 +322,48 @@ READ_ALPHA_RETURN: | ||||
|   return alpha; | ||||
| } | ||||
|  | ||||
| internal TiffSampleBits read_bits_per_sample(const TiffReader *reader, | ||||
|                                              TiffImage *img) { | ||||
|   TiffAlpha alpha = img->alpha; | ||||
|   u64 main_samples = img->sample_count - img->extra_samples_count; | ||||
|  | ||||
|   u64 byte_count = TIFF_SHORT_BYTE_COUNT * img->sample_count; | ||||
|   u16 bits_per_sample[img->sample_count]; | ||||
|   memset(bits_per_sample, 0, byte_count); | ||||
|  | ||||
|   if (img->bits_per_sample_offset) { | ||||
|     read_from_file_with_offset(reader->fp, bits_per_sample, byte_count, | ||||
|                                img->bits_per_sample); | ||||
|   } else { | ||||
|     memcpy(bits_per_sample, &(img->bits_per_sample), byte_count); | ||||
|   } | ||||
|  | ||||
|   TiffSampleBits bits = {0}; | ||||
|   memcpy(&bits, bits_per_sample, TIFF_SHORT_BYTE_COUNT * main_samples); | ||||
|  | ||||
|   if (main_samples < RGB_SAMPLE_COUNT) { | ||||
|     u64 count = RGB_SAMPLE_COUNT - main_samples; | ||||
|     for (u64 i = 0; i < count; ++i) { | ||||
|       u16 *value = &(((u16 *)(&bits))[main_samples + i]); | ||||
|       *value = MINIMUM_BITS_PER_SAMPLE; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if (alpha.type == ALPHA_TYPE_UNDEFINED) { | ||||
|     bits.a = MINIMUM_BITS_PER_SAMPLE; | ||||
|   } else { | ||||
|     void *alpha_sample = &(bits_per_sample[main_samples + alpha.sample_offset]); | ||||
|     memcpy(&(bits.a), alpha_sample, TIFF_SHORT_BYTE_COUNT); | ||||
|   } | ||||
|  | ||||
|   bits.r = bits.r < MINIMUM_BITS_PER_SAMPLE ? MINIMUM_BITS_PER_SAMPLE : bits.r; | ||||
|   bits.g = bits.g < MINIMUM_BITS_PER_SAMPLE ? MINIMUM_BITS_PER_SAMPLE : bits.g; | ||||
|   bits.b = bits.b < MINIMUM_BITS_PER_SAMPLE ? MINIMUM_BITS_PER_SAMPLE : bits.b; | ||||
|   bits.a = bits.a < MINIMUM_BITS_PER_SAMPLE ? MINIMUM_BITS_PER_SAMPLE : bits.a; | ||||
|  | ||||
|   return bits; | ||||
| } | ||||
|  | ||||
| internal Pixel *load_image_pixels(TiffReader *reader, Arena *arena) { | ||||
|   Pixel *buf = NULL; | ||||
|   u64 img_byte_count = | ||||
|   | ||||
| @@ -123,6 +123,14 @@ struct tiff_alpha { | ||||
|   u32 sample_offset; | ||||
| }; | ||||
|  | ||||
| typedef struct tiff_sample_bits TiffSampleBits; | ||||
| struct tiff_sample_bits { | ||||
|   u16 r; | ||||
|   u16 g; | ||||
|   u16 b; | ||||
|   u16 a; | ||||
| }; | ||||
|  | ||||
| typedef struct tiff_strip TiffStrip; | ||||
| struct tiff_strip { | ||||
|   u32 offset; | ||||
| @@ -152,6 +160,7 @@ struct tiff_image { | ||||
|   u32 extra_samples_count; | ||||
|   bool extra_samples_offset; | ||||
|   TiffAlpha alpha; | ||||
|   TiffSampleBits rgba_bits_per_sample; | ||||
|   TiffStrip *strips; | ||||
| }; | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user