TIFF library now passes its unit test

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3970 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2011-09-22 18:28:42 +00:00
parent d37e2a8023
commit ca15acf7a8
9 changed files with 141 additions and 41 deletions

View File

@ -112,3 +112,4 @@
that will write to a register, read from register, and verify that
returned value.
* apps/graphics/tiff: Add a library that can be used to create TIFF files.
* apps/examples/tiff: Add a unit test for the TIFF file creation logic

View File

@ -735,10 +735,26 @@ examples/tiff
This is a simple unit test for the TIFF creation library at apps/graphic/tiff.
It is configured to work in the Linux user-mode simulation and has not been
tested in any other environment.
tested in any other environment. Since the example also depends on some
other logic to mount a file system, currently it will only work as an NSH
built-on, i.e., if the following is defined:
At a miniumum, you would probably have to change the hard-coded pathes to
the TIFF files defined in the example to run in an embedded platform.
CONFIG_NSH_BUILTIN_APPS=y
CONFIG_EXAMPLES_TIFF_BUILTIN=y
At a miniumum, to run in an embedded environment, you will probably have to
change the configured paths to the TIFF files defined in the example.
CONFIG_EXAMPLES_TIFF_OUTFILE - Name of the resulting TIFF file. Default is
"/tmp/result.tif"
CONFIG_EXAMPLES_TIFF_TMPFILE1/2 - Names of two temporaries files that
will be used in the file creation. Defaults are "/tmp/tmpfile1.dat" and
"/tmp/tmpfile2.dat"
The following must also be defined in your appconfig file:
CONFIGURED_APPS += examples/tiff
CONFIGURED_APPS += graphics/tiff
examples/udp
^^^^^^^^^^^^

View File

@ -82,7 +82,7 @@ $(COBJS): %$(OBJEXT): %.c
@touch .built
.context:
ifeq ($(CONFIG_EXAMPLES_USBSTRG_BUILTIN),y)
ifeq ($(CONFIG_EXAMPLES_TIFF_BUILTIN),y)
$(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main)
@touch $@
endif

View File

@ -48,6 +48,34 @@
/****************************************************************************
* Pre-Processor Definitions
****************************************************************************/
/* Configuration ************************************************************/
/* This is a simple unit test for the TIFF creation library at apps/graphic/tiff.
* It is configured to work in the Linux user-mode simulation and has not been
* tested in any other environment. Since the example also depends on some
* other logic to mount a file system, currently it will only work as an NSH
* built-on, i.e., if the following is defined:
*
* CONFIG_NSH_BUILTIN_APPS=y
* CONFIG_EXAMPLES_TIFF_BUILTIN=y
*
* Other configuration options:
*
* CONFIG_EXAMPLES_TIFF_OUTFILE - Name of the resulting TIFF file
* CONFIG_EXAMPLES_TIFF_TMPFILE1/2 - Names of two temporaries files that
* will be used in the file creation.
*/
#ifndef CONFIG_EXAMPLES_TIFF_OUTFILE
# define CONFIG_EXAMPLES_TIFF_OUTFILE "/tmp/result.tif"
#endif
#ifndef CONFIG_EXAMPLES_TIFF_TMPFILE1
# define CONFIG_EXAMPLES_TIFF_TMPFILE1 "/tmp/tmpfile1.dat"
#endif
#ifndef CONFIG_EXAMPLES_TIFF_TMPFILE2
# define CONFIG_EXAMPLES_TIFF_TMPFILE2 "/tmp/tmpfile2.dat"
#endif
/****************************************************************************
* Private Types
@ -95,9 +123,9 @@ int MAIN_NAME(int argc, char *argv[])
/* Configure the interface structure */
memset(&info, 0, sizeof(struct tiff_info_s));
info.outfile = "result.tif";
info.tmpfile1 = "tmpfile1.dat";
info.tmpfile2 = "tmpfile2.dat";
info.outfile = CONFIG_EXAMPLES_TIFF_OUTFILE;
info.tmpfile1 = CONFIG_EXAMPLES_TIFF_TMPFILE1;
info.tmpfile2 = CONFIG_EXAMPLES_TIFF_TMPFILE2;
info.colorfmt = FB_FMT_RGB24;
info.rps = 1;
info.imgwidth = 256;
@ -118,6 +146,7 @@ int MAIN_NAME(int argc, char *argv[])
for (green = 0, ptr = strip; green < 256; green++)
{
ptr = strip;
for (blue = 0; blue < 256; blue++)
{
*ptr++ = (green + blue) >> 1;
@ -138,7 +167,7 @@ int MAIN_NAME(int argc, char *argv[])
ret = tiff_finalize(&info);
if (ret < 0)
{
printf("tiff_initialize() failed: %d\n", ret);
printf("tiff_finalize() failed: %d\n", ret);
exit(1);
}
return 0;

View File

@ -144,7 +144,9 @@ int tiff_convstrip(FAR struct tiff_info_s *info, FAR const uint8_t *strip)
/* Flush any buffer data to tmpfile2 */
ret = tiff_write(info->tmp2fd, info->iobuffer, nbytes);
DEBUGASSERT(ntotal == info->bps);
#ifdef CONFIG_DEBUG_GRAPHICS
ASSERT(ntotal == info->bps);
#endif
return ret;
}

View File

@ -88,18 +88,22 @@ 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, SEEK_SET, offset);
newoffs = lseek(fd, offset, SEEK_SET);
if (newoffs == (off_t)-1)
{
return -errno;
}
/* Then read the IFD entry */
/* Then read the IFD entry. Anything returned by tiff_read other than the
* size of the IFD entry would be an error.
*/
return tiff_read(fd, ifdentry, SIZEOF_IFD_ENTRY);
nbytes = tiff_read(fd, ifdentry, SIZEOF_IFD_ENTRY);
return nbytes == SIZEOF_IFD_ENTRY ? OK : -ENOSPC;
}
/****************************************************************************
@ -125,7 +129,7 @@ static int tiff_writeifdentry(int fd, off_t offset,
/* Seek to the write position */
newoffs = lseek(fd, SEEK_SET, offset);
newoffs = lseek(fd, offset, SEEK_SET);
if (newoffs == (off_t)-1)
{
return -errno;
@ -247,9 +251,9 @@ int tiff_finalize(FAR struct tiff_info_s *info)
goto errout;
}
/* Seek to the beginning of tmpfile2 */
/* Revind to the beginning of tmpfile1 */
offset = lseek(info->tmp2fd, SEEK_SET, 0);
offset = lseek(info->tmp1fd, 0, SEEK_SET);
if (offset == (off_t)-1)
{
ret = -errno;
@ -258,14 +262,14 @@ int tiff_finalize(FAR struct tiff_info_s *info)
/* Seek to the end of the outfile */
ret = lseek(info->outfd, SEEK_END, 0);
ret = lseek(info->outfd, 0, SEEK_END);
if (offset == (off_t)-1)
{
ret = -errno;
goto errout;
}
/* Now read strip offset data from tmpfile2, update the offsets, and write
/* Now read strip offset data from tmpfile1, update the offsets, and write
* the updated offsets to the outfile.
*/
@ -277,6 +281,7 @@ int tiff_finalize(FAR struct tiff_info_s *info)
for (i = 0; i < info->nstrips; )
{
size_t noffsets;
ssize_t nbytes;
/* Read a group of up to 32-bit values */
@ -286,8 +291,13 @@ int tiff_finalize(FAR struct tiff_info_s *info)
noffsets = maxoffsets;
}
ret = tiff_read(info->tmp1fd, info->iobuffer, noffsets << 2);
if (ret <= 0)
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;
}
@ -305,7 +315,7 @@ int tiff_finalize(FAR struct tiff_info_s *info)
/* Then write the corrected offsets to the outfile */
ret = tiff_write(info->outfd, info->iobuffer, noffsets << 2);
ret = tiff_write(info->outfd, info->iobuffer, nbytes);
if (ret < 0)
{
goto errout;
@ -315,14 +325,22 @@ int tiff_finalize(FAR struct tiff_info_s *info)
i += noffsets;
#ifdef CONFIG_DEBUG_GRAPHICS
total += noffsets << 2;
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
@ -335,12 +353,15 @@ int tiff_finalize(FAR struct tiff_info_s *info)
/* 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 (ret == 0)
else if (nbytes == 0)
{
break;
}

View File

@ -635,11 +635,11 @@ int tiff_initialize(FAR struct tiff_info_s *info)
if (IMGFLAGS_ISRGB(info->imgflags))
{
val16 = TAG_PMI_BLACK;
val16 = TAG_PMI_RGB;
}
else
{
val16 = TAG_PMI_RGB;
val16 = TAG_PMI_BLACK;
}
ret = tiff_putifdentry16(info, IFD_TAG_PMI, IFD_FIELD_SHORT, 1, val16);
@ -750,7 +750,6 @@ int tiff_initialize(FAR struct tiff_info_s *info)
* RGB: Offset 168 Count, Hard-coded "NuttX"
*/
tiff_checkoffs(offset, info->filefmt->sbcifdoffset);
ret = tiff_putifdentry(info, IFD_TAG_SOFTWARE, IFD_FIELD_ASCII, TIFF_SOFTWARE_STRLEN, info->filefmt->swoffset);
if (ret < 0)
{
@ -765,7 +764,6 @@ int tiff_initialize(FAR struct tiff_info_s *info)
* RGB: Offset 180 Count, Format "YYYY:MM:DD HH:MM:SS"
*/
tiff_checkoffs(offset, info->filefmt->sbcifdoffset);
ret = tiff_putifdentry(info, IFD_TAG_DATETIME, IFD_FIELD_ASCII, TIFF_DATETIME_STRLEN, info->filefmt->dateoffset);
if (ret < 0)
{
@ -830,6 +828,24 @@ int tiff_initialize(FAR struct tiff_info_s *info)
}
tiff_offset(offset, 8);
/* Write RGB BitsPerSample Data:
*
* Bi-level Images: N/A
* Greyscale: N/A
* RGB: Offset 212 BitsPerSample (8,8,8)
* Offset 218 [2 bytes padding]
*/
if (IMGFLAGS_ISRGB(info->imgflags))
{
tiff_checkoffs(offset, TIFF_RGB_BPSOFFSET);
tiff_putint16(info->outfd, 8);
tiff_putint16(info->outfd, 8);
tiff_putint16(info->outfd, 8);
tiff_putint16(info->outfd, 0);
tiff_offset(offset, 8);
}
/* Write the Software string:
*
*
@ -838,7 +854,7 @@ int tiff_initialize(FAR struct tiff_info_s *info)
* RGB: Offset 220, Hard-coded "NuttX"
*/
tiff_checkoffs(offset, info->filefmt->xresoffset);
tiff_checkoffs(offset, info->filefmt->swoffset);
ret = tiff_putstring(info->outfd, TIFF_SOFTWARE_STRING, TIFF_SOFTWARE_STRLEN);
if (ret < 0)
{

View File

@ -108,11 +108,12 @@ extern "C" {
* count - The number of bytes to write
*
* Returned Value:
* Zero (OK) on success. A negated errno value on failure.
* On success, then number of bytes read; Zero is returned on EOF.
* Otherwise, a negated errno value on failure.
*
****************************************************************************/
EXTERN int tiff_read(int fd, FAR void *buffer, size_t count);
EXTERN ssize_t tiff_read(int fd, FAR void *buffer, size_t count);
/****************************************************************************
* Name: tiff_write

View File

@ -144,12 +144,14 @@ uint32_t tiff_get32(FAR uint8_t *src)
* count - The number of bytes to write
*
* Returned Value:
* Zero (OK) on success. A negated errno value on failure.
* On success, then number of bytes read; Zero is returned on EOF.
* Otherwise, a negated errno value on failure.
*
****************************************************************************/
int tiff_read(int fd, FAR void *buffer, size_t count)
ssize_t tiff_read(int fd, FAR void *buffer, size_t count)
{
size_t ntotal;
ssize_t nbytes;
int errval;
@ -157,11 +159,14 @@ int tiff_read(int fd, FAR void *buffer, size_t count)
* or (2) until an irrecoverble error occurs.
*/
while (count > 0)
for (ntotal = 0; ntotal < count; )
{
/* Do the read */
/* Do the read. The number of bytes left to read is the total
* requested size (count) minus the amount that we have alread read
* (ntotal).
*/
nbytes = read(fd, buffer, count);
nbytes = read(fd, buffer, count-ntotal);
/* Check for an error */
@ -180,17 +185,26 @@ int tiff_read(int fd, FAR void *buffer, size_t count)
}
}
/* What if read returns some number of bytes other than the requested number? */
/* Zero is a special case and means that the end of file was encountered. */
else if (nbytes == 0)
{
break;
}
/* What if read returns some number of bytes other than the requested number?
* This probably means that the end-of-file will be encountered the next time
* that we call read().
*/
else
{
DEBUGASSERT(nbytes < count && nbytes != 0);
buffer += nbytes;
count -= nbytes;
ntotal += nbytes;
}
}
return OK;
return ntotal;
}
/****************************************************************************
@ -245,7 +259,7 @@ int tiff_write(int fd, FAR const void *buffer, size_t count)
else
{
DEBUGASSERT(nbytes < count && nbytes != 0);
DEBUGASSERT(nbytes == count);
buffer += nbytes;
count -= nbytes;
}