static int tiff_putifdentry(FAR struct tiff_info_s *info, uint16_t tag, uint16_t type, uint32_t count, uint32_t offset) { struct tiff_ifdentry_s ifd; tiff_put16(ifd.tag, tag); tiff_put16(ifd.type, type); tiff_put32(ifd.count, count); tiff_put32(ifd.offset, offset); return tiff_write(info->outfd, &ifd, SIZEOF_IFD_ENTRY); }
static inline int tiff_putheader(FAR struct tiff_info_s *info) { struct tiff_header_s hdr; int ret; /* 0-1: Byte order */ #ifdef CONFIG_ENDIAN_BIG hdr.order[0] = 'M'; /* "MM"=big endian */ hdr.order[1] = 'M'; #else hdr.order[0] = 'I'; /* "II"=little endian */ hdr.order[1] = 'I'; #endif /* 2-3: 42 in appropriate byte order */ tiff_put16(hdr.magic, 42); /* 4-7: Offset to the first IFD */ tiff_put32(hdr.offset, TIFF_IFD_OFFSET); /* Write the header to the output file */ ret = tiff_write(info->outfd, &hdr, SIZEOF_TIFF_HEADER); if (ret != OK) { return ret; } /* Two pad bytes following the header */ ret = tiff_putint16(info->outfd, 0); return ret; }
int tiff_finalize(FAR struct tiff_info_s *info) { struct tiff_ifdentry_s ifdentry; FAR uint8_t *ptr; size_t maxoffsets; #ifdef CONFIG_DEBUG_GRAPHICS size_t total; #endif off_t offset; int ret; int i; int j; /* Put all of the pieces together to create the final output file. There * are three pieces: * * 1) outfile: The partial output file containing the header, IFD and strip * counts. This includes the StripOffsets and StripByteCounts that need * to be updated. Size=outsize; * 2) tmpfile1: This contains the offsets into tmpfile3 for each strip. The * size of this file is tmp1size. These offsets are relative to the * beginning of tmpfile3 and need to be offset by outsize+tmp1size. * 3) tmpfile3: The strip data. Size is tmp2size. This is raw image data; * no fixups are required. */ DEBUGASSERT(info && info->outfd >= 0 && info->tmp1fd >= 0 && info->tmp2fd >= 0); DEBUGASSERT((info->outsize & 3) == 0 && (info->tmp1size & 3) == 0); /* Fix-up the count value in the StripByteCounts IFD entry in the outfile. * The actual number of strips was unknown at the time that the IFD entry * was written. */ ret = tiff_readifdentry(info->outfd, info->filefmt->sbcifdoffset, &ifdentry); if (ret < 0) { goto errout; } tiff_put32(ifdentry.count, info->nstrips); ret = tiff_writeifdentry(info->outfd, info->filefmt->sbcifdoffset, &ifdentry); if (ret < 0) { goto errout; } /* Fix-up the count and offset values in the StripOffsets IFD entry in the * outfile. The StripOffsets data will be stored immediately after the * outfile, hence, the correct offset is outsize. */ ret = tiff_readifdentry(info->outfd, info->filefmt->soifdoffset, &ifdentry); if (ret < 0) { goto errout; } tiff_put32(ifdentry.count, info->nstrips); tiff_put32(ifdentry.offset, info->outsize); ret = tiff_writeifdentry(info->outfd, info->filefmt->soifdoffset, &ifdentry); if (ret < 0) { goto errout; } /* Rewind to the beginning of tmpfile1 */ offset = lseek(info->tmp1fd, 0, SEEK_SET); if (offset == (off_t)-1) { ret = -errno; goto errout; } /* Seek to the end of the outfile */ ret = lseek(info->outfd, 0, SEEK_END); if (offset == (off_t)-1) { ret = -errno; goto errout; } /* Now read strip offset data from tmpfile1, update the offsets, and write * the updated offsets to the outfile. The strip data will begin at offset * outsize + tmp1size; */ maxoffsets = info->iosize >> 2; #ifdef CONFIG_DEBUG_GRAPHICS total = 0; #endif for (i = 0; i < info->nstrips; ) { size_t noffsets; ssize_t nbytes; /* Read a group of up to 32-bit values */ noffsets = info->nstrips - i; if (noffsets > maxoffsets) { noffsets = maxoffsets; } nbytes = tiff_read(info->tmp1fd, info->iobuffer, noffsets << 2); /* If an error occurs or we fail to read exactly this number of * bytes, then something bad happened. */ if (nbytes != noffsets << 2) { goto errout; } /* Fix up the offsets */ for (j = 0, ptr = info->iobuffer; j < noffsets; j++, ptr += 4) { uint32_t stripoff = tiff_get32(ptr); stripoff += (info->outsize + info->tmp1size); tiff_put32(ptr, stripoff); } /* Then write the corrected offsets to the outfile */ ret = tiff_write(info->outfd, info->iobuffer, nbytes); if (ret < 0) { goto errout; } /* Update the count of offsets written */ i += noffsets; #ifdef CONFIG_DEBUG_GRAPHICS total += nbytes; #endif } #ifdef CONFIG_DEBUG_GRAPHICS ASSERT(total == info->tmp1size); #endif /* Rewind to the beginning of tmpfile2 */ offset = lseek(info->tmp2fd, 0, SEEK_SET); if (offset == (off_t)-1) { ret = -errno; goto errout; } /* Finally, copy the tmpfile2 to the end of the outfile */ #ifdef CONFIG_DEBUG_GRAPHICS total = 0; #endif for (;;) { ssize_t nbytes; /* Read a block of data from tmpfile2 */ nbytes = tiff_read(info->tmp2fd, info->iobuffer, info->iosize); /* Check for tead errors and for end-of-file */ if (nbytes < 0) { ret = (int)nbytes; goto errout; } else if (nbytes == 0) { break; } /* Then copy the data to the outfile */ ret = tiff_write(info->outfd, info->iobuffer, nbytes); if (ret < 0) { goto errout; } #ifdef CONFIG_DEBUG_GRAPHICS total += nbytes; #endif } #ifdef CONFIG_DEBUG_GRAPHICS ASSERT(total == info->tmp2size); #endif /* Close all files and return success */ tiff_cleanup(info); return OK; errout: tiff_abort(info); return ret; }