Implement reading RGB and RGBA images
This commit is contained in:
parent
c46535c20b
commit
4b52630c1e
@ -3,6 +3,7 @@
|
|||||||
#include "endianness.h"
|
#include "endianness.h"
|
||||||
#include "image.h"
|
#include "image.h"
|
||||||
#include "mem_arena.h"
|
#include "mem_arena.h"
|
||||||
|
#include <assert.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
@ -35,7 +36,8 @@
|
|||||||
TiffHdr read_tiff_header(FILE *fp);
|
TiffHdr read_tiff_header(FILE *fp);
|
||||||
TiffIFD read_ifd(FILE *fp, const TiffHdr *header, u32 offset, Arena *arena);
|
TiffIFD read_ifd(FILE *fp, const TiffHdr *header, u32 offset, Arena *arena);
|
||||||
TiffImage read_fields(FILE *fp, const TiffHdr *header, const TiffIFD *ifd);
|
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,
|
void read_strips(FILE *fp, const TiffImage *img, const TiffStrip *strips,
|
||||||
Pixel *buf);
|
Pixel *buf);
|
||||||
bool read_field(const TiffField *field, TiffImage *img,
|
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;
|
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;
|
goto READ_BASELINE_DESTROY_ARENA;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,7 +262,8 @@ READ_FIELDS_RETURN_IMAGE:
|
|||||||
return img_out;
|
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) {
|
if (!fp || !img || !strips) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -285,6 +288,21 @@ bool read_strip_data(FILE *fp, const TiffImage *img, TiffStrip *strips) {
|
|||||||
if (offsets_total_bytes > sizeof(u32)) {
|
if (offsets_total_bytes > sizeof(u32)) {
|
||||||
u32 offset = img->strip_offsets.long_val + offset_size * i;
|
u32 offset = img->strip_offsets.long_val + offset_size * i;
|
||||||
read_from_file_with_offset(fp, &(strip->offset), offset_size, offset);
|
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 {
|
} else {
|
||||||
memcpy(&(strip->offset), &(img->strip_offsets.long_val), offset_size);
|
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)) {
|
if (byte_count_total_bytes > sizeof(u32)) {
|
||||||
u32 offset = img->strip_byte_counts.long_val + counts_size * i;
|
u32 offset = img->strip_byte_counts.long_val + counts_size * i;
|
||||||
read_from_file_with_offset(fp, &(strip->byte_count), counts_size, offset);
|
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 {
|
} else {
|
||||||
memcpy(&(strip->byte_count), &(img->strip_byte_counts.long_val),
|
memcpy(&(strip->byte_count), &(img->strip_byte_counts.long_val),
|
||||||
counts_size);
|
counts_size);
|
||||||
@ -303,16 +338,25 @@ bool read_strip_data(FILE *fp, const TiffImage *img, TiffStrip *strips) {
|
|||||||
|
|
||||||
void read_strips(FILE *fp, const TiffImage *img, const TiffStrip *strips,
|
void read_strips(FILE *fp, const TiffImage *img, const TiffStrip *strips,
|
||||||
Pixel *buf) {
|
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) {
|
for (u64 i = 0; i < img->strip_count; ++i) {
|
||||||
const TiffStrip *strip = &(strips[i]);
|
const TiffStrip *strip = &(strips[i]);
|
||||||
|
|
||||||
for (u64 j = 0; j < img->image_width * img->image_length; ++j) {
|
for (u64 j = 0; j < strip->byte_count / img->sample_count; ++j) {
|
||||||
Pixel *p = &(buf[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);
|
||||||
|
|
||||||
|
if (img->sample_count == 3) {
|
||||||
p->a = 255;
|
p->a = 255;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
++position;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user