nuttx-apps/graphics/tiff/tiff_finalize.c
Xiang Xiao 857158451b Unify the void cast usage
1.Remove void cast for function because many place ignore the returned value witout cast
2.Replace void cast for variable with UNUSED macro

Change-Id: Ie644129a563244a6397036789c4c3ea83c4e9b09
Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
2020-01-02 23:21:01 +08:00

440 lines
12 KiB
C

/****************************************************************************
* apps/graphics/tiff/tiff_finalize.c
*
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include "graphics/tiff.h"
#include "tiff_internal.h"
/****************************************************************************
* Pre-Processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: tiff_readifdentry
*
* Description:
* Read the IFD entry at the specified offset.
*
* Input Parameters:
* fd - File descriptor to rad from
* offset - Offset to read from
* ifdentry - Location to read the data
*
* Returned Value:
* Zero (OK) on success. A negated errno value on failure.
*
****************************************************************************/
static int tiff_readifdentry(int fd, off_t offset,
FAR struct tiff_ifdentry_s *ifdentry)
{
off_t newoffs;
ssize_t nbytes;
/* Seek to the read position */
newoffs = lseek(fd, offset, SEEK_SET);
if (newoffs == (off_t)-1)
{
return -errno;
}
/* Then read the IFD entry. Anything returned by tiff_read other than the
* size of the IFD entry would be an error.
*/
nbytes = tiff_read(fd, ifdentry, SIZEOF_IFD_ENTRY);
return nbytes == SIZEOF_IFD_ENTRY ? OK : -ENOSPC;
}
/****************************************************************************
* Name: tiff_writeifdentry
*
* Description:
* Write the IFD entry at the specified offset.
*
* Input Parameters:
* fd - File descriptor to rad from
* offset - Offset to read from
* ifdentry - Location to read the data
*
* Returned Value:
* Zero (OK) on success. A negated errno value on failure.
*
****************************************************************************/
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);
}
/****************************************************************************
* Name: tiff_cleanup
*
* Description:
* Normal clean-up after completion of the TIFF file creation
*
* Input Parameters:
* info - A pointer to the caller allocated parameter passing/TIFF
* state instance.
*
* Returned Value:
* None
*
****************************************************************************/
static void tiff_cleanup(FAR struct tiff_info_s *info)
{
/* Close all opened files */
if (info->outfd >= 0)
{
close(info->outfd);
}
info->outfd = -1;
if (info->tmp1fd >= 0)
{
close(info->tmp1fd);
}
info->tmp1fd = -1;
if (info->tmp2fd >= 0)
{
close(info->tmp2fd);
}
info->tmp2fd = -1;
/* And remove the temporary files */
unlink(info->tmpfile1);
unlink(info->tmpfile2);
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: tiff_finalize
*
* Description:
* Finalize the TIFF output file, completing the TIFF file creation steps.
*
* Input Parameters:
* info - A pointer to the caller allocated parameter passing/TIFF state
* instance.
*
* Returned Value:
* Zero (OK) on success. A negated errno value on failure.
*
****************************************************************************/
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
DEBUGASSERT(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
DEBUGASSERT(total == info->tmp2size);
#endif
/* Close all files and return success */
tiff_cleanup(info);
return OK;
errout:
tiff_abort(info);
return ret;
}
/************************************************************************************
* Name: tiff_abort
*
* Description:
* Abort the TIFF file creation and create-up resources.
*
* Input Parameters:
* info - A pointer to the caller allocated parameter passing/TIFF state instance.
*
* Returned Value:
* None
*
************************************************************************************/
void tiff_abort(FAR struct tiff_info_s *info)
{
/* Perform normal cleanup */
tiff_cleanup(info);
/* But then delete the output file as well */
unlink(info->outfile);
}