Switch internal reading functions to directly manipulate reader object
This commit is contained in:
		| @@ -40,7 +40,7 @@ | |||||||
| #define TIFF_LONG_BYTE_COUNT field_types[TIFF_FIELD_TYPE_LONG].byte_count | #define TIFF_LONG_BYTE_COUNT field_types[TIFF_FIELD_TYPE_LONG].byte_count | ||||||
|  |  | ||||||
| #define RGB_SAMPLE_COUNT 3 | #define RGB_SAMPLE_COUNT 3 | ||||||
| #define MINIMUM_BITS_PER_SAMPLE 8 | #define MIN_BITS_PER_SAMPLE 8 | ||||||
|  |  | ||||||
| #define TEMP_ARENA_CAPACITY (20 * 1024 * 1024) | #define TEMP_ARENA_CAPACITY (20 * 1024 * 1024) | ||||||
|  |  | ||||||
| @@ -62,15 +62,14 @@ struct strip_data_field { | |||||||
|   u16 type_byte_count; |   u16 type_byte_count; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| internal TiffHdr read_tiff_header(const TiffReader *reader); | internal void read_tiff_header(TiffReader *reader); | ||||||
| internal TiffIFD read_ifd(const TiffReader *reader, Arena *arena); | internal void read_ifd(TiffReader *reader, Arena *arena); | ||||||
| internal TiffImage read_ifd_fields(const TiffReader *reader); | internal void read_ifd_fields(TiffReader *reader); | ||||||
| internal TiffAlpha read_alpha(const TiffReader *reader, TiffImage *img); | internal void read_alpha(TiffReader *reader); | ||||||
| internal TiffSampleBits read_bits_per_sample(const TiffReader *reader, | internal void read_bits_per_sample(TiffReader *reader); | ||||||
|                                              TiffImage *img); | internal void 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(TiffReader *reader); | ||||||
| internal void read_strip_data_field(const TiffReader *reader, | internal void read_strip_data_field(const TiffReader *reader, | ||||||
|                                     StripDataField *field); |                                     StripDataField *field); | ||||||
| internal bool read_field(const TiffField *field, TiffImage *img); | internal bool read_field(const TiffField *field, TiffImage *img); | ||||||
| @@ -115,30 +114,30 @@ Image *read_baseline_tiff(const char *file, Arena *arena) { | |||||||
|     goto READ_BASELINE_FILE_CLEANUP; |     goto READ_BASELINE_FILE_CLEANUP; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   reader.header = read_tiff_header(&reader); |   read_tiff_header(&reader); | ||||||
|   if (IS_NULL_HEADER(reader.header)) { |   if (IS_NULL_HEADER(reader.header)) { | ||||||
|     goto READ_BASELINE_DESTROY_ARENA; |     goto READ_BASELINE_DESTROY_ARENA; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   reader.ifd = read_ifd(&reader, temp_arena); |   read_ifd(&reader, temp_arena); | ||||||
|   if (IS_NULL_IFD(reader.ifd)) { |   if (IS_NULL_IFD(reader.ifd)) { | ||||||
|     goto READ_BASELINE_DESTROY_ARENA; |     goto READ_BASELINE_DESTROY_ARENA; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   reader.img = read_ifd_fields(&reader); |   read_ifd_fields(&reader); | ||||||
|   if (IS_NULL_IMAGE(reader.img)) { |   if (IS_NULL_IMAGE(reader.img)) { | ||||||
|     goto READ_BASELINE_DESTROY_ARENA; |     goto READ_BASELINE_DESTROY_ARENA; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   assert((reader.img.type == TIFF_IMAGE_TYPE_RGB) && |   assert((reader.img.type == TIFF_IMAGE_TYPE_RGB) && | ||||||
|          "Currently, only RGB images are supported"); |          "Currently, only RGB images are supported"); | ||||||
|   assert((reader.img.rgba_bits_per_sample.r == MINIMUM_BITS_PER_SAMPLE && |   assert((reader.img.rgba_bits_per_sample.r == MIN_BITS_PER_SAMPLE && | ||||||
|           reader.img.rgba_bits_per_sample.g == MINIMUM_BITS_PER_SAMPLE && |           reader.img.rgba_bits_per_sample.g == MIN_BITS_PER_SAMPLE && | ||||||
|           reader.img.rgba_bits_per_sample.b == MINIMUM_BITS_PER_SAMPLE && |           reader.img.rgba_bits_per_sample.b == MIN_BITS_PER_SAMPLE && | ||||||
|           reader.img.rgba_bits_per_sample.a == MINIMUM_BITS_PER_SAMPLE) && |           reader.img.rgba_bits_per_sample.a == MIN_BITS_PER_SAMPLE) && | ||||||
|          "Currently, only 8-bit images are supported"); |          "Currently, only 8-bit images are supported"); | ||||||
|  |  | ||||||
|   reader.pixels = load_image_pixels(&reader, temp_arena); |   load_image_pixels(&reader, temp_arena); | ||||||
|   if (!reader.pixels) { |   if (!reader.pixels) { | ||||||
|     goto READ_BASELINE_DESTROY_ARENA; |     goto READ_BASELINE_DESTROY_ARENA; | ||||||
|   } |   } | ||||||
| @@ -156,71 +155,69 @@ READ_BASELINE_RETURN_IMG: | |||||||
|   return img_out; |   return img_out; | ||||||
| } | } | ||||||
|  |  | ||||||
| internal TiffHdr read_tiff_header(const TiffReader *reader) { | internal void read_tiff_header(TiffReader *reader) { | ||||||
|   TiffHdr header = NULL_TIFF_HEADER; |   reader->header = NULL_TIFF_HEADER; | ||||||
|   read_from_file_with_offset(reader->fp, &header, sizeof(TiffHdr), 0); |   read_from_file_with_offset(reader->fp, &(reader->header), sizeof(TiffHdr), 0); | ||||||
|  |  | ||||||
|   switch (header.order) { |   switch (reader->header.order) { | ||||||
|   case TIFF_ORDER_LITTLE_ENDIAN: |   case TIFF_ORDER_LITTLE_ENDIAN: | ||||||
|     if (IS_BIG_ENDIAN) { |     if (IS_BIG_ENDIAN) { | ||||||
|       header.magic = htons(header.magic); |       reader->header.magic = htons(reader->header.magic); | ||||||
|       header.first_ifd_offset = htonl(header.first_ifd_offset); |       reader->header.first_ifd_offset = htonl(reader->header.first_ifd_offset); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     break; |     break; | ||||||
|   case TIFF_ORDER_BIG_ENDIAN: |   case TIFF_ORDER_BIG_ENDIAN: | ||||||
|     if (IS_LITTLE_ENDIAN) { |     if (IS_LITTLE_ENDIAN) { | ||||||
|       header.magic = ntohs(header.magic); |       reader->header.magic = ntohs(reader->header.magic); | ||||||
|       header.first_ifd_offset = ntohl(header.first_ifd_offset); |       reader->header.first_ifd_offset = ntohl(reader->header.first_ifd_offset); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     break; |     break; | ||||||
|   default: |   default: | ||||||
|     return NULL_TIFF_HEADER; |     reader->header = NULL_TIFF_HEADER; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if (header.magic != TIFF_MAGIC) { |   if (reader->header.magic != TIFF_MAGIC) { | ||||||
|     return NULL_TIFF_HEADER; |     reader->header = NULL_TIFF_HEADER; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   return header; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| internal TiffIFD read_ifd(const TiffReader *reader, Arena *arena) { | internal void read_ifd(TiffReader *reader, Arena *arena) { | ||||||
|   TiffIFD ifd = NULL_TIFF_IFD; |   reader->ifd = NULL_TIFF_IFD; | ||||||
|   read_from_file_with_offset(reader->fp, &(ifd.count), sizeof(ifd.count), |   read_from_file_with_offset(reader->fp, &(reader->ifd.count), | ||||||
|  |                              sizeof(reader->ifd.count), | ||||||
|                              reader->header.first_ifd_offset); |                              reader->header.first_ifd_offset); | ||||||
|  |  | ||||||
|   switch (reader->header.order) { |   switch (reader->header.order) { | ||||||
|   case TIFF_ORDER_LITTLE_ENDIAN: |   case TIFF_ORDER_LITTLE_ENDIAN: | ||||||
|     if (IS_BIG_ENDIAN) { |     if (IS_BIG_ENDIAN) { | ||||||
|       ifd.count = htons(ifd.count); |       reader->ifd.count = htons(reader->ifd.count); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     break; |     break; | ||||||
|   case TIFF_ORDER_BIG_ENDIAN: |   case TIFF_ORDER_BIG_ENDIAN: | ||||||
|     if (IS_LITTLE_ENDIAN) { |     if (IS_LITTLE_ENDIAN) { | ||||||
|       ifd.count = ntohs(ifd.count); |       reader->ifd.count = ntohs(reader->ifd.count); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     break; |     break; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   u64 field_byte_count = sizeof(TiffField) * ifd.count; |   u64 field_byte_count = sizeof(TiffField) * reader->ifd.count; | ||||||
|   ifd.fields = (TiffField *)wapp_mem_arena_alloc(arena, field_byte_count); |   reader->ifd.fields = | ||||||
|   if (!(ifd.fields)) { |       (TiffField *)wapp_mem_arena_alloc(arena, field_byte_count); | ||||||
|     return NULL_TIFF_IFD; |   if (!(reader->ifd.fields)) { | ||||||
|  |     reader->ifd = NULL_TIFF_IFD; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   fread(ifd.fields, field_byte_count, 1, reader->fp); |   fread(reader->ifd.fields, field_byte_count, 1, reader->fp); | ||||||
|   fread(&(ifd.next_ifd), sizeof(ifd.next_ifd), 1, reader->fp); |   fread(&(reader->ifd.next_ifd), sizeof(reader->ifd.next_ifd), 1, reader->fp); | ||||||
|  |  | ||||||
|   return ifd; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| internal TiffImage read_ifd_fields(const TiffReader *reader) { | internal void read_ifd_fields(TiffReader *reader) { | ||||||
|   TiffImage img_out = NULL_TIFF_IMAGE; |   reader->img = NULL_TIFF_IMAGE; | ||||||
|   img_out.type = TIFF_IMAGE_TYPE_BILEVEL; |   reader->img.type = TIFF_IMAGE_TYPE_BILEVEL; | ||||||
|  |  | ||||||
|   for (u64 i = 0; i < reader->ifd.count; ++i) { |   for (u64 i = 0; i < reader->ifd.count; ++i) { | ||||||
|     TiffField *field = &(reader->ifd.fields[i]); |     TiffField *field = &(reader->ifd.fields[i]); | ||||||
| @@ -256,122 +253,149 @@ internal TiffImage read_ifd_fields(const TiffReader *reader) { | |||||||
|       break; |       break; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (!read_field(field, &img_out)) { |     if (!read_field(field, &(reader->img))) { | ||||||
|       img_out = NULL_TIFF_IMAGE; |       reader->img = NULL_TIFF_IMAGE; | ||||||
|       goto READ_FIELDS_RETURN_IMAGE; |       return; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if (!validate_image_type(&img_out)) { |   if (!validate_image_type(&(reader->img))) { | ||||||
|     img_out = NULL_TIFF_IMAGE; |     reader->img = NULL_TIFF_IMAGE; | ||||||
|     goto READ_FIELDS_RETURN_IMAGE; |     return; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   img_out.alpha = read_alpha(reader, &img_out); |   read_alpha(reader); | ||||||
|   img_out.rgba_bits_per_sample = read_bits_per_sample(reader, &img_out); |   read_bits_per_sample(reader); | ||||||
|  |  | ||||||
| #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", reader->img.image_width, reader->img.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", reader->img.bits_per_sample, reader->img.sample_count, reader->img.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", reader->img.extra_samples, reader->img.extra_samples_count, reader->img.extra_samples_offset); | ||||||
|   printf("ALPHA (type, offset)                          :   %u, %u\n", img_out.alpha.type, img_out.alpha.sample_offset); |   printf("ALPHA (type, offset)                          :   %u, %u\n", reader->img.alpha.type, reader->img.alpha.sample_offset); | ||||||
|   printf("SAMPLES PER PIXEL                             :   %u\n", img_out.sample_count); |   printf("SAMPLES PER PIXEL                             :   %u\n", reader->img.sample_count); | ||||||
|   printf("PHOTOMETRIC INTERPRETATION                    :   %u\n", img_out.photometric_interpretation); |   printf("PHOTOMETRIC INTERPRETATION                    :   %u\n", reader->img.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", reader->img.rows_per_strip, reader->img.strip_count); | ||||||
|   printf("STRIP OFFSETS (offsets, is offset)            :   %u, %u\n", img_out.strip_offsets.long_val, img_out.strip_offsets_offset); |   printf("STRIP OFFSETS (offsets, is offset)            :   %u, %u\n", reader->img.strip_offsets.long_val, reader->img.strip_offsets_offset); | ||||||
|   printf("STRIP BYTES (byte count, is offset)           :   %u, %u\n", img_out.strip_byte_counts.long_val, img_out.strip_byte_counts_offset); |   printf("STRIP BYTES (byte count, is offset)           :   %u, %u\n", reader->img.strip_byte_counts.long_val, reader->img.strip_byte_counts_offset); | ||||||
|   // clang-format on |   // clang-format on | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| READ_FIELDS_RETURN_IMAGE: |  | ||||||
|   return img_out; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| internal TiffAlpha read_alpha(const TiffReader *reader, TiffImage *img) { | internal void read_alpha(TiffReader *reader) { | ||||||
|   TiffAlpha alpha = NULL_TIFF_ALPHA; |   reader->img.alpha = NULL_TIFF_ALPHA; | ||||||
|   u16 samples[img->extra_samples_count]; |   u16 samples[reader->img.extra_samples_count]; | ||||||
|  |  | ||||||
|   if (img->extra_samples_count == 0) { |   if (reader->img.extra_samples_count == 0) { | ||||||
|     goto READ_ALPHA_RETURN; |     reader->img.alpha = NULL_TIFF_ALPHA; | ||||||
|  |     return; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   u64 byte_count = TIFF_SHORT_BYTE_COUNT * img->extra_samples_count; |   u64 byte_count = TIFF_SHORT_BYTE_COUNT * reader->img.extra_samples_count; | ||||||
|   memset(samples, 0, byte_count); |   memset(samples, 0, byte_count); | ||||||
|  |  | ||||||
|   if (img->extra_samples_offset) { |   if (reader->img.extra_samples_offset) { | ||||||
|     read_from_file_with_offset(reader->fp, samples, byte_count, |     read_from_file_with_offset(reader->fp, samples, byte_count, | ||||||
|                                img->extra_samples); |                                reader->img.extra_samples); | ||||||
|  |  | ||||||
|  |     switch (reader->header.order) { | ||||||
|  |     case TIFF_ORDER_BIG_ENDIAN: | ||||||
|  |       if (IS_LITTLE_ENDIAN) { | ||||||
|  |         for (u64 i = 0; i < reader->img.extra_samples_count; ++i) { | ||||||
|  |           samples[i] = ntohs(samples[i]); | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  |     case TIFF_ORDER_LITTLE_ENDIAN: | ||||||
|  |       if (IS_BIG_ENDIAN) { | ||||||
|  |         for (u64 i = 0; i < reader->img.extra_samples_count; ++i) { | ||||||
|  |           samples[i] = htons(samples[i]); | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  |     } | ||||||
|   } else { |   } else { | ||||||
|     memcpy(samples, &(img->extra_samples), byte_count); |     memcpy(samples, &(reader->img.extra_samples), byte_count); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   for (u32 i = 0; i < img->extra_samples_count; ++i) { |   for (u32 i = 0; i < reader->img.extra_samples_count; ++i) { | ||||||
|     u16 *sample = &(samples[i]); |     u16 *sample = &(samples[i]); | ||||||
|     if (*sample == TIFF_EXTRA_SAMPLE_ASSOCIATED_ALPHA || |     if (*sample == TIFF_EXTRA_SAMPLE_ASSOCIATED_ALPHA || | ||||||
|         *sample == TIFF_EXTRA_SAMPLE_UNASSOCIATED_ALPHA) { |         *sample == TIFF_EXTRA_SAMPLE_UNASSOCIATED_ALPHA) { | ||||||
|       alpha.type = *sample == TIFF_EXTRA_SAMPLE_ASSOCIATED_ALPHA |       reader->img.alpha.type = *sample == TIFF_EXTRA_SAMPLE_ASSOCIATED_ALPHA | ||||||
|                        ? ALPHA_TYPE_ASSOCIATED |                                    ? ALPHA_TYPE_ASSOCIATED | ||||||
|                        : ALPHA_TYPE_UNASSOCIATED; |                                    : ALPHA_TYPE_UNASSOCIATED; | ||||||
|       alpha.sample_offset = i; |       reader->img.alpha.sample_offset = i; | ||||||
|       break; |       break; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
| READ_ALPHA_RETURN: |  | ||||||
|   return alpha; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| internal TiffSampleBits read_bits_per_sample(const TiffReader *reader, | internal void read_bits_per_sample(TiffReader *reader) { | ||||||
|                                              TiffImage *img) { |   TiffAlpha alpha = reader->img.alpha; | ||||||
|   TiffAlpha alpha = img->alpha; |   u64 main_samples = reader->img.sample_count - reader->img.extra_samples_count; | ||||||
|   u64 main_samples = img->sample_count - img->extra_samples_count; |  | ||||||
|  |  | ||||||
|   u64 byte_count = TIFF_SHORT_BYTE_COUNT * img->sample_count; |   u64 byte_count = TIFF_SHORT_BYTE_COUNT * reader->img.sample_count; | ||||||
|   u16 bits_per_sample[img->sample_count]; |   u16 bits_per_sample[reader->img.sample_count]; | ||||||
|   memset(bits_per_sample, 0, byte_count); |   memset(bits_per_sample, 0, byte_count); | ||||||
|  |  | ||||||
|   if (img->bits_per_sample_offset) { |   if (reader->img.bits_per_sample_offset) { | ||||||
|     read_from_file_with_offset(reader->fp, bits_per_sample, byte_count, |     read_from_file_with_offset(reader->fp, bits_per_sample, byte_count, | ||||||
|                                img->bits_per_sample); |                                reader->img.bits_per_sample); | ||||||
|  |  | ||||||
|  |     switch (reader->header.order) { | ||||||
|  |     case TIFF_ORDER_BIG_ENDIAN: | ||||||
|  |       if (IS_LITTLE_ENDIAN) { | ||||||
|  |         for (u64 i = 0; i < reader->img.sample_count; ++i) { | ||||||
|  |           bits_per_sample[i] = ntohs(bits_per_sample[i]); | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  |     case TIFF_ORDER_LITTLE_ENDIAN: | ||||||
|  |       if (IS_BIG_ENDIAN) { | ||||||
|  |         for (u64 i = 0; i < reader->img.sample_count; ++i) { | ||||||
|  |           bits_per_sample[i] = htons(bits_per_sample[i]); | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  |     } | ||||||
|   } else { |   } else { | ||||||
|     memcpy(bits_per_sample, &(img->bits_per_sample), byte_count); |     memcpy(bits_per_sample, &(reader->img.bits_per_sample), byte_count); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   TiffSampleBits bits = {0}; |   TiffSampleBits *bits = &(reader->img.rgba_bits_per_sample); | ||||||
|   memcpy(&bits, bits_per_sample, TIFF_SHORT_BYTE_COUNT * main_samples); |   *bits = (TiffSampleBits){0}; | ||||||
|  |   memcpy(bits, bits_per_sample, TIFF_SHORT_BYTE_COUNT * main_samples); | ||||||
|  |  | ||||||
|   // Set missing samples if image doesn't have all RGB samples |   // Set missing samples if image doesn't have all RGB samples | ||||||
|   if (main_samples < RGB_SAMPLE_COUNT) { |   if (main_samples < RGB_SAMPLE_COUNT) { | ||||||
|     u64 count = RGB_SAMPLE_COUNT - main_samples; |     u64 count = RGB_SAMPLE_COUNT - main_samples; | ||||||
|     for (u64 i = 0; i < count; ++i) { |     for (u64 i = 0; i < count; ++i) { | ||||||
|       u16 *value = &(((u16 *)(&bits))[main_samples + i]); |       u16 *value = &(((u16 *)(&bits))[main_samples + i]); | ||||||
|       *value = MINIMUM_BITS_PER_SAMPLE; |       *value = MIN_BITS_PER_SAMPLE; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if (alpha.type == ALPHA_TYPE_UNDEFINED) { |   if (alpha.type == ALPHA_TYPE_UNDEFINED) { | ||||||
|     bits.a = MINIMUM_BITS_PER_SAMPLE; |     bits->a = MIN_BITS_PER_SAMPLE; | ||||||
|   } else { |   } else { | ||||||
|     void *alpha_sample = &(bits_per_sample[main_samples + alpha.sample_offset]); |     void *alpha_sample = &(bits_per_sample[main_samples + alpha.sample_offset]); | ||||||
|     memcpy(&(bits.a), alpha_sample, TIFF_SHORT_BYTE_COUNT); |     memcpy(&(bits->a), alpha_sample, TIFF_SHORT_BYTE_COUNT); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   bits.r = bits.r < MINIMUM_BITS_PER_SAMPLE ? MINIMUM_BITS_PER_SAMPLE : bits.r; |   bits->r = bits->r < MIN_BITS_PER_SAMPLE ? MIN_BITS_PER_SAMPLE : bits->r; | ||||||
|   bits.g = bits.g < MINIMUM_BITS_PER_SAMPLE ? MINIMUM_BITS_PER_SAMPLE : bits.g; |   bits->g = bits->g < MIN_BITS_PER_SAMPLE ? MIN_BITS_PER_SAMPLE : bits->g; | ||||||
|   bits.b = bits.b < MINIMUM_BITS_PER_SAMPLE ? MINIMUM_BITS_PER_SAMPLE : bits.b; |   bits->b = bits->b < MIN_BITS_PER_SAMPLE ? MIN_BITS_PER_SAMPLE : bits->b; | ||||||
|   bits.a = bits.a < MINIMUM_BITS_PER_SAMPLE ? MINIMUM_BITS_PER_SAMPLE : bits.a; |   bits->a = bits->a < MIN_BITS_PER_SAMPLE ? MIN_BITS_PER_SAMPLE : bits->a; | ||||||
|  |  | ||||||
|   return bits; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| internal Pixel *load_image_pixels(TiffReader *reader, Arena *arena) { | internal void load_image_pixels(TiffReader *reader, Arena *arena) { | ||||||
|   Pixel *buf = NULL; |   reader->pixels = NULL; | ||||||
|   u64 img_byte_count = |   u64 img_byte_count = | ||||||
|       sizeof(Pixel) * reader->img.image_width * reader->img.image_length; |       sizeof(Pixel) * reader->img.image_width * reader->img.image_length; | ||||||
|  |  | ||||||
|   if (!read_strip_data(reader, arena)) { |   if (!read_strip_data(reader, arena)) { | ||||||
|     goto LOAD_IMAGE_PIXELS_RETURN; |     return; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| #ifdef DEBUG | #ifdef DEBUG | ||||||
| @@ -381,15 +405,12 @@ internal Pixel *load_image_pixels(TiffReader *reader, Arena *arena) { | |||||||
|   } |   } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|   buf = wapp_mem_arena_alloc(arena, img_byte_count); |   reader->pixels = wapp_mem_arena_alloc(arena, img_byte_count); | ||||||
|   if (!buf) { |   if (!reader->pixels) { | ||||||
|     goto LOAD_IMAGE_PIXELS_RETURN; |     return; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   read_strips(reader, buf); |   read_strips(reader); | ||||||
|  |  | ||||||
| LOAD_IMAGE_PIXELS_RETURN: |  | ||||||
|   return buf; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| internal bool read_strip_data(TiffReader *reader, Arena *arena) { | internal bool read_strip_data(TiffReader *reader, Arena *arena) { | ||||||
| @@ -438,7 +459,7 @@ internal bool read_strip_data(TiffReader *reader, Arena *arena) { | |||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| internal void read_strips(const TiffReader *reader, Pixel *buf) { | internal void read_strips(TiffReader *reader) { | ||||||
|   u64 position = 0; |   u64 position = 0; | ||||||
|   u64 main_samples = reader->img.sample_count - reader->img.extra_samples_count; |   u64 main_samples = reader->img.sample_count - reader->img.extra_samples_count; | ||||||
|   TiffAlpha alpha = reader->img.alpha; |   TiffAlpha alpha = reader->img.alpha; | ||||||
| @@ -451,7 +472,7 @@ internal void read_strips(const TiffReader *reader, Pixel *buf) { | |||||||
|     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) { | ||||||
|       p = &(buf[position]); |       p = &(reader->pixels[position]); | ||||||
|       start_offset = strip->offset + j * reader->img.sample_count; |       start_offset = strip->offset + j * reader->img.sample_count; | ||||||
|       alpha_offset = start_offset + main_samples + alpha.sample_offset; |       alpha_offset = start_offset + main_samples + alpha.sample_offset; | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user