Implement reading RGB and RGBA images
This commit is contained in:
		| @@ -3,6 +3,7 @@ | ||||
| #include "endianness.h" | ||||
| #include "image.h" | ||||
| #include "mem_arena.h" | ||||
| #include <assert.h> | ||||
| #include <math.h> | ||||
| #include <netinet/in.h> | ||||
| #include <stdbool.h> | ||||
| @@ -35,7 +36,8 @@ | ||||
| TiffHdr read_tiff_header(FILE *fp); | ||||
| TiffIFD read_ifd(FILE *fp, const TiffHdr *header, u32 offset, Arena *arena); | ||||
| TiffImage read_fields(FILE *fp, const TiffHdr *header, const TiffIFD *ifd); | ||||
| bool read_strip_data(FILE *fp, const TiffImage *img, TiffStrip *strips); | ||||
| bool read_strip_data(FILE *fp, const TiffHdr *header, const TiffImage *img, | ||||
|                      TiffStrip *strips); | ||||
| void read_strips(FILE *fp, const TiffImage *img, const TiffStrip *strips, | ||||
|                  Pixel *buf); | ||||
| bool read_field(const TiffField *field, TiffImage *img, | ||||
| @@ -96,7 +98,7 @@ Image *read_baseline_tiff(const char *file, Arena *arena) { | ||||
|     goto READ_BASELINE_DESTROY_ARENA; | ||||
|   } | ||||
|  | ||||
|   if (!read_strip_data(fp, &img, strips)) { | ||||
|   if (!read_strip_data(fp, &header, &img, strips)) { | ||||
|     goto READ_BASELINE_DESTROY_ARENA; | ||||
|   } | ||||
|  | ||||
| @@ -260,7 +262,8 @@ READ_FIELDS_RETURN_IMAGE: | ||||
|   return img_out; | ||||
| } | ||||
|  | ||||
| bool read_strip_data(FILE *fp, const TiffImage *img, TiffStrip *strips) { | ||||
| bool read_strip_data(FILE *fp, const TiffHdr *header, const TiffImage *img, | ||||
|                      TiffStrip *strips) { | ||||
|   if (!fp || !img || !strips) { | ||||
|     return false; | ||||
|   } | ||||
| @@ -285,6 +288,21 @@ bool read_strip_data(FILE *fp, const TiffImage *img, TiffStrip *strips) { | ||||
|     if (offsets_total_bytes > sizeof(u32)) { | ||||
|       u32 offset = img->strip_offsets.long_val + offset_size * i; | ||||
|       read_from_file_with_offset(fp, &(strip->offset), offset_size, offset); | ||||
|  | ||||
|       switch (header->order) { | ||||
|       case TIFF_ORDER_BIG_ENDIAN: | ||||
|         if (IS_LITTLE_ENDIAN) { | ||||
|           strip->offset = offset_size > sizeof(u16) ? ntohl(strip->offset) | ||||
|                                                     : ntohs(strip->offset); | ||||
|         } | ||||
|         break; | ||||
|       case TIFF_ORDER_LITTLE_ENDIAN: | ||||
|         if (IS_BIG_ENDIAN) { | ||||
|           strip->offset = offset_size > sizeof(u16) ? htonl(strip->offset) | ||||
|                                                     : htons(strip->offset); | ||||
|         } | ||||
|         break; | ||||
|       } | ||||
|     } else { | ||||
|       memcpy(&(strip->offset), &(img->strip_offsets.long_val), offset_size); | ||||
|     } | ||||
| @@ -292,6 +310,23 @@ bool read_strip_data(FILE *fp, const TiffImage *img, TiffStrip *strips) { | ||||
|     if (byte_count_total_bytes > sizeof(u32)) { | ||||
|       u32 offset = img->strip_byte_counts.long_val + counts_size * i; | ||||
|       read_from_file_with_offset(fp, &(strip->byte_count), counts_size, offset); | ||||
|  | ||||
|       switch (header->order) { | ||||
|       case TIFF_ORDER_BIG_ENDIAN: | ||||
|         if (IS_LITTLE_ENDIAN) { | ||||
|           strip->byte_count = counts_size > sizeof(u16) | ||||
|                                   ? ntohl(strip->byte_count) | ||||
|                                   : ntohs(strip->byte_count); | ||||
|         } | ||||
|         break; | ||||
|       case TIFF_ORDER_LITTLE_ENDIAN: | ||||
|         if (IS_BIG_ENDIAN) { | ||||
|           strip->byte_count = counts_size > sizeof(u16) | ||||
|                                   ? htonl(strip->byte_count) | ||||
|                                   : htons(strip->byte_count); | ||||
|         } | ||||
|         break; | ||||
|       } | ||||
|     } else { | ||||
|       memcpy(&(strip->byte_count), &(img->strip_byte_counts.long_val), | ||||
|              counts_size); | ||||
| @@ -303,15 +338,24 @@ bool read_strip_data(FILE *fp, const TiffImage *img, TiffStrip *strips) { | ||||
|  | ||||
| void read_strips(FILE *fp, const TiffImage *img, const TiffStrip *strips, | ||||
|                  Pixel *buf) { | ||||
|   assert((img->sample_count == 3 || img->sample_count == 4) && | ||||
|          "Only RGB or RGBA images supported"); | ||||
|  | ||||
|   u64 position = 0; | ||||
|   for (u64 i = 0; i < img->strip_count; ++i) { | ||||
|     const TiffStrip *strip = &(strips[i]); | ||||
|  | ||||
|     for (u64 j = 0; j < img->image_width * img->image_length; ++j) { | ||||
|       Pixel *p = &(buf[j]); | ||||
|     for (u64 j = 0; j < strip->byte_count / img->sample_count; ++j) { | ||||
|       Pixel *p = &(buf[position]); | ||||
|  | ||||
|       read_from_file_with_offset(fp, p, 3, strip->offset + j * 3); | ||||
|       read_from_file_with_offset(fp, p, img->sample_count, | ||||
|                                  strip->offset + j * img->sample_count); | ||||
|  | ||||
|       p->a = 255; | ||||
|       if (img->sample_count == 3) { | ||||
|         p->a = 255; | ||||
|       } | ||||
|  | ||||
|       ++position; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user