Exemple #1
0
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);
}
Exemple #2
0
static int tiff_writeifdentry(int fd, off_t offset,
                              FAR struct tiff_ifdentry_s *ifdentry)
{
  off_t newoffs;

  /* Seek to the write position */

  newoffs = lseek(fd, offset, SEEK_SET);
  if (newoffs == (off_t)-1)
    {
      return -errno;
    }

  /* Then write the IFD entry */

   return tiff_write(fd, ifdentry, SIZEOF_IFD_ENTRY);
}
Exemple #3
0
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;
}
Exemple #4
0
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;
}