mirror of
https://git.code.sf.net/p/libpng/code.git
synced 2025-07-10 18:04:09 +02:00
Compare commits
2 Commits
0cc6436ef5
...
3bca02e274
Author | SHA1 | Date | |
---|---|---|---|
![]() |
3bca02e274 | ||
![]() |
197bbfe0d5 |
143
contrib/examples/.clang-format
Normal file
143
contrib/examples/.clang-format
Normal file
@ -0,0 +1,143 @@
|
||||
---
|
||||
Language: Cpp
|
||||
AccessModifierOffset: -3
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignArrayOfStructures: None
|
||||
AlignConsecutiveAssignments:
|
||||
Enabled: false
|
||||
AlignConsecutiveBitFields:
|
||||
Enabled: false
|
||||
AlignConsecutiveDeclarations:
|
||||
Enabled: false
|
||||
AlignConsecutiveMacros:
|
||||
Enabled: false
|
||||
AlignConsecutiveShortCaseStatements:
|
||||
Enabled: false
|
||||
AlignEscapedNewlines: DontAlign
|
||||
AlignOperands: false
|
||||
AlignTrailingComments:
|
||||
Kind: Never
|
||||
OverEmptyLines: 0
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowBreakBeforeNoexceptSpecifier: Never
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseExpressionOnASingleLine: true
|
||||
AllowShortCaseLabelsOnASingleLine: true
|
||||
AllowShortCompoundRequirementOnASingleLine: true
|
||||
AllowShortEnumsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AllowShortNamespacesOnASingleLine: false
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
BinPackArguments: true
|
||||
BinPackParameters: BinPack
|
||||
BitFieldColonSpacing: Both
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: true
|
||||
AfterClass: true
|
||||
AfterControlStatement: Always
|
||||
AfterEnum: true
|
||||
AfterExternBlock: false
|
||||
AfterFunction: true
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: true
|
||||
AfterStruct: true
|
||||
AfterUnion: true
|
||||
BeforeCatch: true
|
||||
BeforeElse: true
|
||||
BeforeLambdaBody: false
|
||||
BeforeWhile: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakAdjacentStringLiterals: true
|
||||
BreakAfterAttributes: Leave
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakAfterReturnType: TopLevel
|
||||
BreakArrays: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeConceptDeclarations: Always
|
||||
BreakBeforeBraces: Custom
|
||||
BreakBeforeTernaryOperators: false
|
||||
BreakStringLiterals: false
|
||||
BreakTemplateDeclarations: MultiLine
|
||||
ColumnLimit: 79
|
||||
ContinuationIndentWidth: 3
|
||||
DerivePointerAlignment: true
|
||||
EmptyLineAfterAccessModifier: Never
|
||||
EmptyLineBeforeAccessModifier: LogicalBlock
|
||||
FixNamespaceComments: true
|
||||
IncludeBlocks: Preserve
|
||||
IndentAccessModifiers: false
|
||||
IndentCaseBlocks: true
|
||||
IndentCaseLabels: true
|
||||
IndentExportBlock: true
|
||||
IndentExternBlock: AfterExternBlock
|
||||
IndentGotoLabels: false
|
||||
IndentPPDirectives: None
|
||||
IndentRequiresClause: true
|
||||
IndentWidth: 3
|
||||
IndentWrappedFunctionNames: false
|
||||
KeepEmptyLines:
|
||||
AtEndOfFile: false
|
||||
AtStartOfBlock: false
|
||||
AtStartOfFile: false
|
||||
KeepFormFeed: false
|
||||
MaxEmptyLinesToKeep: 2
|
||||
NamespaceIndentation: None
|
||||
PackConstructorInitializers: Never
|
||||
PointerAlignment: Left
|
||||
QualifierAlignment: Custom
|
||||
QualifierOrder: [static, inline, constexpr, const, volatile, restrict, type]
|
||||
ReferenceAlignment: Pointer
|
||||
ReflowComments: Never
|
||||
RequiresClausePosition: OwnLine
|
||||
RequiresExpressionIndentation: OuterScope
|
||||
SortIncludes: false
|
||||
SortUsingDeclarations: LexicographicNumeric
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceAroundPointerQualifiers: Default
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCaseColon: false
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeJsonColon: false
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeParensOptions:
|
||||
AfterControlStatements: true
|
||||
AfterFunctionDefinitionName: false
|
||||
AfterFunctionDeclarationName: false
|
||||
AfterOverloadedOperator: false
|
||||
AfterPlacementOperator: true
|
||||
AfterRequiresInClause: false
|
||||
AfterRequiresInExpression: false
|
||||
BeforeNonEmptyParentheses: false
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceBeforeSquareBrackets: false
|
||||
SpaceInEmptyBlock: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: Never
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInLineCommentPrefix:
|
||||
Minimum: 1
|
||||
Maximum: -1
|
||||
SpacesInParens: Never
|
||||
SpacesInParensOptions:
|
||||
ExceptDoubleParentheses: false
|
||||
InCStyleCasts: false
|
||||
InConditionalStatements: false
|
||||
InEmptyParentheses: false
|
||||
Other: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Latest
|
||||
TabWidth: 8
|
||||
UseTab: Never
|
||||
WrapNamespaceBodyWithEmptyLines: Leave
|
||||
...
|
@ -26,8 +26,9 @@
|
||||
|
||||
#include <png.h>
|
||||
|
||||
#if defined(PNG_READ_SUPPORTED) && defined(PNG_STDIO_SUPPORTED) && \
|
||||
defined (PNG_iCCP_SUPPORTED)
|
||||
#if !defined(PNG_iCCP_SUPPORTED) || !defined(PNG_READ_SUPPORTED)
|
||||
#error This program requires libpng supporting the iCCP chunk and the read API
|
||||
#endif
|
||||
|
||||
|
||||
static int verbose = 1;
|
||||
@ -36,7 +37,8 @@ static png_byte no_profile[] = "no profile";
|
||||
static png_bytep
|
||||
extract(FILE *fp, png_uint_32 *proflen)
|
||||
{
|
||||
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,0,0,0);
|
||||
png_structp png_ptr =
|
||||
png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
png_infop info_ptr = NULL;
|
||||
png_bytep result = NULL;
|
||||
|
||||
@ -69,7 +71,7 @@ extract(FILE *fp, png_uint_32 *proflen)
|
||||
png_bytep profile;
|
||||
|
||||
if (png_get_iCCP(png_ptr, info_ptr, &name, &compression_type, &profile,
|
||||
proflen) & PNG_INFO_iCCP)
|
||||
proflen) & PNG_INFO_iCCP)
|
||||
{
|
||||
result = malloc(*proflen);
|
||||
if (result != NULL)
|
||||
@ -107,7 +109,7 @@ extract_one_file(const char *filename)
|
||||
const char *ep = strrchr(filename, '.');
|
||||
|
||||
if (ep != NULL)
|
||||
len = ep-filename;
|
||||
len = ep - filename;
|
||||
|
||||
else
|
||||
len = strlen(filename);
|
||||
@ -119,14 +121,14 @@ extract_one_file(const char *filename)
|
||||
FILE *of;
|
||||
|
||||
memcpy(output, filename, len);
|
||||
strcpy(output+len, ".icc");
|
||||
strcpy(output + len, ".icc");
|
||||
|
||||
of = fopen(output, "wb");
|
||||
if (of != NULL)
|
||||
{
|
||||
if (fwrite(profile, proflen, 1, of) == 1 &&
|
||||
fflush(of) == 0 &&
|
||||
fclose(of) == 0)
|
||||
fflush(of) == 0 &&
|
||||
fclose(of) == 0)
|
||||
{
|
||||
if (verbose)
|
||||
printf("%s -> %s\n", filename, output);
|
||||
@ -161,6 +163,9 @@ extract_one_file(const char *filename)
|
||||
else
|
||||
fprintf(stderr, "%s: could not open file\n", filename);
|
||||
|
||||
if (fp != NULL)
|
||||
fclose(fp);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -170,7 +175,7 @@ main(int argc, char **argv)
|
||||
int i;
|
||||
int extracted = 0;
|
||||
|
||||
for (i=1; i<argc; ++i)
|
||||
for (i = 1; i < argc; ++i)
|
||||
{
|
||||
if (strcmp(argv[i], "-q") == 0)
|
||||
verbose = 0;
|
||||
@ -182,4 +187,3 @@ main(int argc, char **argv)
|
||||
/* Exit code is true if any extract succeeds */
|
||||
return extracted == 0;
|
||||
}
|
||||
#endif /* READ && STDIO && iCCP */
|
||||
|
@ -15,8 +15,8 @@
|
||||
* images. Normally you would call png_set_interlace_handling() to have libpng
|
||||
* deal with the interlace for you, but that obliges you to buffer half of the
|
||||
* image to assemble the interlaced rows. In this code
|
||||
* png_set_interlace_handling() is not called and, instead, the code handles the
|
||||
* interlace passes directly looking for the required pixel.
|
||||
* png_set_interlace_handling() is not called and, instead, the code handles
|
||||
* the interlace passes directly looking for the required pixel.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
@ -27,34 +27,37 @@
|
||||
*/
|
||||
#include "../../png.h"
|
||||
|
||||
#if defined(PNG_READ_SUPPORTED) && defined(PNG_SEQUENTIAL_READ_SUPPORTED)
|
||||
#if !defined(PNG_READ_SUPPORTED) || !defined(PNG_SEQUENTIAL_READ_SUPPORTED)
|
||||
#error This program requires libpng supporting the read and sequential read API
|
||||
#endif
|
||||
|
||||
|
||||
/* Return component 'c' of pixel 'x' from the given row. */
|
||||
static unsigned int
|
||||
component(png_const_bytep row, png_uint_32 x, unsigned int c,
|
||||
unsigned int bit_depth, unsigned int channels)
|
||||
unsigned int bit_depth, unsigned int channels)
|
||||
{
|
||||
/* PNG images can be up to 2^31 pixels wide, but this means they can be up to
|
||||
* 2^37 bits wide (for a 64-bit pixel - the largest possible) and hence 2^34
|
||||
* bytes wide. Since the row fitted into memory, however, the following must
|
||||
/* PNG images can be up to 2^31 pixels wide, which means they can be up to
|
||||
* 2^37 bits wide (for a 64-bit pixel - the largest possible) and hence
|
||||
* 2^34 bytes wide. Since the row fitted into memory, the following must
|
||||
* work:
|
||||
*/
|
||||
png_uint_32 bit_offset_hi = bit_depth * ((x >> 6) * channels);
|
||||
png_uint_32 bit_offset_lo = bit_depth * ((x & 0x3f) * channels + c);
|
||||
|
||||
row = (png_const_bytep)(((const png_byte (*)[8])row) + bit_offset_hi);
|
||||
row = (png_const_bytep)(((const png_byte(*)[8])row) + bit_offset_hi);
|
||||
row += bit_offset_lo >> 3;
|
||||
bit_offset_lo &= 0x07;
|
||||
|
||||
/* PNG pixels are packed into bytes to put the first pixel in the highest
|
||||
* bits of the byte and into two bytes for 16-bit values with the high 8 bits
|
||||
* first, so:
|
||||
* bits of the byte, and into two bytes for 16-bit values with the high
|
||||
* 8 bits first, so:
|
||||
*/
|
||||
switch (bit_depth)
|
||||
{
|
||||
case 1: return (row[0] >> (7-bit_offset_lo)) & 0x01;
|
||||
case 2: return (row[0] >> (6-bit_offset_lo)) & 0x03;
|
||||
case 4: return (row[0] >> (4-bit_offset_lo)) & 0x0f;
|
||||
case 1: return (row[0] >> (7 - bit_offset_lo)) & 0x01;
|
||||
case 2: return (row[0] >> (6 - bit_offset_lo)) & 0x03;
|
||||
case 4: return (row[0] >> (4 - bit_offset_lo)) & 0x0f;
|
||||
case 8: return row[0];
|
||||
case 16: return (row[0] << 8) + row[1];
|
||||
default:
|
||||
@ -71,7 +74,7 @@ component(png_const_bytep row, png_uint_32 x, unsigned int c,
|
||||
*/
|
||||
static void
|
||||
print_pixel(png_structp png_ptr, png_infop info_ptr, png_const_bytep row,
|
||||
png_uint_32 x)
|
||||
png_uint_32 x)
|
||||
{
|
||||
unsigned int bit_depth = png_get_bit_depth(png_ptr, info_ptr);
|
||||
|
||||
@ -92,22 +95,24 @@ print_pixel(png_structp png_ptr, png_infop info_ptr, png_const_bytep row,
|
||||
int num_palette = 0;
|
||||
|
||||
if ((png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette) &
|
||||
PNG_INFO_PLTE) && num_palette > 0 && palette != NULL)
|
||||
PNG_INFO_PLTE) &&
|
||||
(num_palette > 0) &&
|
||||
(palette != NULL))
|
||||
{
|
||||
png_bytep trans_alpha = NULL;
|
||||
int num_trans = 0;
|
||||
if ((png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans,
|
||||
NULL) & PNG_INFO_tRNS) && num_trans > 0 &&
|
||||
trans_alpha != NULL)
|
||||
NULL) & PNG_INFO_tRNS) &&
|
||||
(num_trans > 0) &&
|
||||
(trans_alpha != NULL))
|
||||
printf("INDEXED %u = %d %d %d %d\n", index,
|
||||
palette[index].red, palette[index].green,
|
||||
palette[index].blue,
|
||||
index < num_trans ? trans_alpha[index] : 255);
|
||||
palette[index].red, palette[index].green,
|
||||
palette[index].blue,
|
||||
index < num_trans ? trans_alpha[index] : 255);
|
||||
|
||||
else /* no transparency */
|
||||
printf("INDEXED %u = %d %d %d\n", index,
|
||||
palette[index].red, palette[index].green,
|
||||
palette[index].blue);
|
||||
printf("INDEXED %u = %d %d %d\n", index, palette[index].red,
|
||||
palette[index].green, palette[index].blue);
|
||||
}
|
||||
|
||||
else
|
||||
@ -117,20 +122,20 @@ print_pixel(png_structp png_ptr, png_infop info_ptr, png_const_bytep row,
|
||||
|
||||
case PNG_COLOR_TYPE_RGB:
|
||||
printf("RGB %u %u %u\n", component(row, x, 0, bit_depth, 3),
|
||||
component(row, x, 1, bit_depth, 3),
|
||||
component(row, x, 2, bit_depth, 3));
|
||||
component(row, x, 1, bit_depth, 3),
|
||||
component(row, x, 2, bit_depth, 3));
|
||||
return;
|
||||
|
||||
case PNG_COLOR_TYPE_GRAY_ALPHA:
|
||||
printf("GRAY+ALPHA %u %u\n", component(row, x, 0, bit_depth, 2),
|
||||
component(row, x, 1, bit_depth, 2));
|
||||
component(row, x, 1, bit_depth, 2));
|
||||
return;
|
||||
|
||||
case PNG_COLOR_TYPE_RGB_ALPHA:
|
||||
printf("RGBA %u %u %u %u\n", component(row, x, 0, bit_depth, 4),
|
||||
component(row, x, 1, bit_depth, 4),
|
||||
component(row, x, 2, bit_depth, 4),
|
||||
component(row, x, 3, bit_depth, 4));
|
||||
component(row, x, 1, bit_depth, 4),
|
||||
component(row, x, 2, bit_depth, 4),
|
||||
component(row, x, 3, bit_depth, 4));
|
||||
return;
|
||||
|
||||
default:
|
||||
@ -138,7 +143,8 @@ print_pixel(png_structp png_ptr, png_infop info_ptr, png_const_bytep row,
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
int
|
||||
main(int argc, const char **argv)
|
||||
{
|
||||
/* This program uses the default, <setjmp.h> based, libpng error handling
|
||||
* mechanism, therefore any local variable that exists before the call to
|
||||
@ -146,7 +152,7 @@ int main(int argc, const char **argv)
|
||||
* be declared with 'volatile' to ensure that their values don't get
|
||||
* destroyed by longjmp:
|
||||
*/
|
||||
volatile int result = 1/*fail*/;
|
||||
volatile int result = 1 /*fail*/;
|
||||
|
||||
if (argc == 4)
|
||||
{
|
||||
@ -163,8 +169,8 @@ int main(int argc, const char **argv)
|
||||
* writes error messages to stderr. Creating the png_struct is a
|
||||
* little tricky; just copy the following code.
|
||||
*/
|
||||
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
|
||||
NULL, NULL, NULL);
|
||||
png_structp png_ptr =
|
||||
png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
|
||||
if (png_ptr != NULL)
|
||||
{
|
||||
@ -202,21 +208,21 @@ int main(int argc, const char **argv)
|
||||
* space. In this case png_malloc is used - it will not
|
||||
* return if memory isn't available.
|
||||
*/
|
||||
row = png_malloc(png_ptr, png_get_rowbytes(png_ptr,
|
||||
info_ptr));
|
||||
row =
|
||||
png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
|
||||
|
||||
/* To avoid the overhead of using a volatile auto copy row_tmp
|
||||
/* Avoid the overhead of using a volatile auto copy row_tmp
|
||||
* to a local here - just use row for the png_free below.
|
||||
*/
|
||||
row_tmp = row;
|
||||
|
||||
/* All the information we need is in the header is returned by
|
||||
* png_get_IHDR, if this fails we can now use 'png_error' to
|
||||
/* All the information we need is in the header returned by
|
||||
* png_get_IHDR. If this fails, we can use 'png_error' to
|
||||
* signal the error and return control to the setjmp above.
|
||||
*/
|
||||
if (png_get_IHDR(png_ptr, info_ptr, &width, &height,
|
||||
&bit_depth, &color_type, &interlace_method,
|
||||
&compression_method, &filter_method))
|
||||
&bit_depth, &color_type, &interlace_method,
|
||||
&compression_method, &filter_method))
|
||||
{
|
||||
int passes, pass;
|
||||
|
||||
@ -242,7 +248,7 @@ int main(int argc, const char **argv)
|
||||
/* Now read the pixels, pass-by-pass, row-by-row: */
|
||||
png_start_read_image(png_ptr);
|
||||
|
||||
for (pass=0; pass<passes; ++pass)
|
||||
for (pass = 0; pass < passes; ++pass)
|
||||
{
|
||||
png_uint_32 ystart, xstart, ystep, xstep;
|
||||
png_uint_32 py;
|
||||
@ -299,19 +305,27 @@ int main(int argc, const char **argv)
|
||||
* are, of course, much better ways of doing this
|
||||
* than using a for loop:
|
||||
*/
|
||||
if (y == py) for (px = xstart, ppx = 0;
|
||||
px < width; px += xstep, ++ppx) if (x == px)
|
||||
if (y == py)
|
||||
{
|
||||
/* 'ppx' is the index of the pixel in the row
|
||||
* buffer.
|
||||
*/
|
||||
print_pixel(png_ptr, info_ptr, row_tmp, ppx);
|
||||
for (px = xstart, ppx = 0;
|
||||
px < width;
|
||||
px += xstep, ++ppx)
|
||||
{
|
||||
if (x == px)
|
||||
{
|
||||
/* 'ppx' is the index of the pixel in the
|
||||
* row buffer.
|
||||
*/
|
||||
print_pixel(png_ptr, info_ptr, row_tmp,
|
||||
ppx);
|
||||
|
||||
/* Now terminate the loops early - we have
|
||||
* found and handled the required data.
|
||||
*/
|
||||
goto pass_loop_end;
|
||||
} /* x loop */
|
||||
/* Now terminate the loops early - we have
|
||||
* found and handled the required data.
|
||||
*/
|
||||
goto pass_loop_end;
|
||||
} /* x loop */
|
||||
}
|
||||
}
|
||||
} /* y loop */
|
||||
} /* pass loop */
|
||||
|
||||
@ -323,7 +337,6 @@ int main(int argc, const char **argv)
|
||||
|
||||
else
|
||||
png_error(png_ptr, "pngpixel: png_get_IHDR failed");
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
@ -349,7 +362,8 @@ int main(int argc, const char **argv)
|
||||
}
|
||||
|
||||
else
|
||||
fprintf(stderr, "pngpixel: out of memory allocating png_info\n");
|
||||
fprintf(stderr,
|
||||
"pngpixel: out of memory allocating png_info\n");
|
||||
|
||||
png_destroy_read_struct(&png_ptr, NULL, NULL);
|
||||
}
|
||||
@ -368,4 +382,3 @@ int main(int argc, const char **argv)
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif /* READ && SEQUENTIAL_READ */
|
||||
|
@ -8,8 +8,8 @@
|
||||
* Read a PNG and write it out in a fixed format, using the 'simplified API'
|
||||
* that was introduced in libpng-1.6.0.
|
||||
*
|
||||
* This sample code is just the code from the top of 'example.c' with some error
|
||||
* handling added. See example.c for more comments.
|
||||
* This sample code is just the code from 'example.c' with some error handling
|
||||
* added. See example.c in the top-level libpng directory for more comments.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
@ -20,10 +20,15 @@
|
||||
* ensure the code picks up the local libpng implementation:
|
||||
*/
|
||||
#include "../../png.h"
|
||||
#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) && \
|
||||
defined(PNG_SIMPLIFIED_WRITE_SUPPORTED)
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
#if !defined(PNG_SIMPLIFIED_READ_SUPPORTED) || \
|
||||
!defined(PNG_SIMPLIFIED_WRITE_SUPPORTED)
|
||||
#error This program requires libpng supporting the simplified read/write API
|
||||
#endif
|
||||
|
||||
|
||||
int
|
||||
main(int argc, const char **argv)
|
||||
{
|
||||
int result = 1;
|
||||
|
||||
@ -48,22 +53,22 @@ int main(int argc, const char **argv)
|
||||
|
||||
if (buffer != NULL)
|
||||
{
|
||||
if (png_image_finish_read(&image, NULL/*background*/, buffer,
|
||||
0/*row_stride*/, NULL/*colormap for PNG_FORMAT_FLAG_COLORMAP */))
|
||||
if (png_image_finish_read(&image, NULL /*background*/, buffer,
|
||||
0 /*row_stride*/, NULL /*colormap */))
|
||||
{
|
||||
if (png_image_write_to_file(&image, argv[2],
|
||||
0/*convert_to_8bit*/, buffer, 0/*row_stride*/,
|
||||
NULL/*colormap*/))
|
||||
if (png_image_write_to_file(
|
||||
&image, argv[2], 0 /*convert_to_8bit*/, buffer,
|
||||
0 /*row_stride*/, NULL /*colormap*/))
|
||||
result = 0;
|
||||
|
||||
else
|
||||
fprintf(stderr, "pngtopng: write %s: %s\n", argv[2],
|
||||
image.message);
|
||||
image.message);
|
||||
}
|
||||
|
||||
else
|
||||
fprintf(stderr, "pngtopng: read %s: %s\n", argv[1],
|
||||
image.message);
|
||||
image.message);
|
||||
|
||||
free(buffer);
|
||||
}
|
||||
@ -71,7 +76,7 @@ int main(int argc, const char **argv)
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "pngtopng: out of memory: %lu bytes\n",
|
||||
(unsigned long)PNG_IMAGE_SIZE(image));
|
||||
(unsigned long)PNG_IMAGE_SIZE(image));
|
||||
|
||||
/* This is the only place where a 'free' is required; libpng does
|
||||
* the cleanup on error and success, but in this case we couldn't
|
||||
@ -93,4 +98,3 @@ int main(int argc, const char **argv)
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif /* READ && WRITE */
|
||||
|
@ -6,9 +6,9 @@
|
||||
* United States.
|
||||
*
|
||||
* Read several PNG files, which should have an alpha channel or transparency
|
||||
* information, and composite them together to produce one or more 16-bit linear
|
||||
* RGBA intermediates. This involves doing the correct 'over' composition to
|
||||
* combine the alpha channels and corresponding data.
|
||||
* information, and composite them together to produce one or more 16-bit
|
||||
* linear RGBA intermediates. This involves doing the 'over' compositing
|
||||
* operation to combine the alpha channels and corresponding data.
|
||||
*
|
||||
* Finally read an output (background) PNG using the 24-bit RGB format (the
|
||||
* PNG will be composited on green (#00ff00) by default if it has an alpha
|
||||
@ -28,8 +28,8 @@
|
||||
* correctly. Apart from the libpng Simplified API the only work done in here
|
||||
* is to combine multiple input PNG images into a single sprite; this involves
|
||||
* a Porter-Duff 'over' operation and the input PNG images may, as a result,
|
||||
* be regarded as being layered one on top of the other with the first (leftmost
|
||||
* on the command line) being at the bottom and the last on the top.
|
||||
* be regarded as being layered one on top of the other with the first
|
||||
* (leftmost on the command line) being at the bottom and the last on the top.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
@ -44,54 +44,61 @@
|
||||
*/
|
||||
#include "../../png.h"
|
||||
|
||||
#ifdef PNG_SIMPLIFIED_READ_SUPPORTED
|
||||
#if !defined(PNG_SIMPLIFIED_READ_SUPPORTED)
|
||||
#error This program requires libpng supporting the simplified read API
|
||||
#endif
|
||||
|
||||
#define sprite_name_chars 15
|
||||
struct sprite {
|
||||
FILE *file;
|
||||
png_uint_16p buffer;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
char name[sprite_name_chars+1];
|
||||
struct sprite
|
||||
{
|
||||
FILE *file;
|
||||
png_uint_16p buffer;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
char name[sprite_name_chars + 1];
|
||||
};
|
||||
|
||||
#if 0 /* div by 65535 test program */
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void) {
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
double err = 0;
|
||||
unsigned int xerr = 0;
|
||||
unsigned int r = 32769;
|
||||
unsigned int x = 0;
|
||||
|
||||
do
|
||||
{
|
||||
unsigned int x = 0;
|
||||
unsigned int t = x + (x >> 16) /*+ (x >> 31)*/ + r;
|
||||
double v = x, errtest;
|
||||
|
||||
do {
|
||||
unsigned int t = x + (x >> 16) /*+ (x >> 31)*/ + r;
|
||||
double v = x, errtest;
|
||||
if (t < x)
|
||||
{
|
||||
fprintf(stderr, "overflow: %u+%u -> %u\n", x, r, t);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (t < x) {
|
||||
fprintf(stderr, "overflow: %u+%u -> %u\n", x, r, t);
|
||||
return 1;
|
||||
v /= 65535;
|
||||
errtest = v;
|
||||
t >>= 16;
|
||||
errtest -= t;
|
||||
|
||||
if (errtest > err)
|
||||
{
|
||||
err = errtest;
|
||||
xerr = x;
|
||||
|
||||
if (errtest >= .5)
|
||||
{
|
||||
fprintf(stderr, "error: %u/65535 = %f, not %u, error %f\n",
|
||||
x, v, t, errtest);
|
||||
return 0;
|
||||
}
|
||||
|
||||
v /= 65535;
|
||||
errtest = v;
|
||||
t >>= 16;
|
||||
errtest -= t;
|
||||
|
||||
if (errtest > err) {
|
||||
err = errtest;
|
||||
xerr = x;
|
||||
|
||||
if (errtest >= .5) {
|
||||
fprintf(stderr, "error: %u/65535 = %f, not %u, error %f\n",
|
||||
x, v, t, errtest);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} while (++x <= 65535U*65535U);
|
||||
}
|
||||
}
|
||||
} while (++x <= 65535U * 65535U);
|
||||
|
||||
printf("error %f @ %u\n", err, xerr);
|
||||
|
||||
@ -101,7 +108,7 @@ int main(void) {
|
||||
|
||||
static void
|
||||
sprite_op(const struct sprite *sprite, int x_offset, int y_offset,
|
||||
png_imagep image, const png_uint_16 *buffer)
|
||||
png_imagep image, const png_uint_16 *buffer)
|
||||
{
|
||||
/* This is where the Porter-Duff 'Over' operator is evaluated; change this
|
||||
* code to change the operator (this could be parameterized). Any other
|
||||
@ -112,8 +119,8 @@ sprite_op(const struct sprite *sprite, int x_offset, int y_offset,
|
||||
/* Check for an x or y offset that pushes any part of the image beyond the
|
||||
* right or bottom of the sprite:
|
||||
*/
|
||||
if ((y_offset < 0 || (unsigned)/*SAFE*/y_offset < sprite->height) &&
|
||||
(x_offset < 0 || (unsigned)/*SAFE*/x_offset < sprite->width))
|
||||
if ((y_offset < 0 || /*SAFE*/ (unsigned)y_offset < sprite->height) &&
|
||||
(x_offset < 0 || /*SAFE*/ (unsigned)x_offset < sprite->width))
|
||||
{
|
||||
unsigned int y = 0;
|
||||
|
||||
@ -130,7 +137,7 @@ sprite_op(const struct sprite *sprite, int x_offset, int y_offset,
|
||||
do
|
||||
{
|
||||
/* In and out are RGBA values, so: */
|
||||
const png_uint_16 *in_pixel = buffer + (y * image->width + x)*4;
|
||||
const png_uint_16 *in_pixel = buffer + (y * image->width + x) * 4;
|
||||
png_uint_32 in_alpha = in_pixel[3];
|
||||
|
||||
/* This is the optimized Porter-Duff 'Over' operation, when the
|
||||
@ -139,10 +146,10 @@ sprite_op(const struct sprite *sprite, int x_offset, int y_offset,
|
||||
if (in_alpha > 0)
|
||||
{
|
||||
png_uint_16 *out_pixel = sprite->buffer +
|
||||
((y+y_offset) * sprite->width + (x+x_offset))*4;
|
||||
((y + y_offset) * sprite->width + (x + x_offset)) * 4;
|
||||
|
||||
/* This is the weight to apply to the output: */
|
||||
in_alpha = 65535-in_alpha;
|
||||
in_alpha = 65535 - in_alpha;
|
||||
|
||||
if (in_alpha > 0)
|
||||
{
|
||||
@ -159,9 +166,9 @@ sprite_op(const struct sprite *sprite, int x_offset, int y_offset,
|
||||
*/
|
||||
png_uint_32 tmp;
|
||||
|
||||
# define compose(c)\
|
||||
tmp = out_pixel[c] * in_alpha;\
|
||||
tmp = (tmp + (tmp >> 16) + 32769) >> 16;\
|
||||
# define compose(c) \
|
||||
tmp = out_pixel[c] * in_alpha; \
|
||||
tmp = (tmp + (tmp >> 16) + 32769) >> 16; \
|
||||
out_pixel[c] = tmp + in_pixel[c]
|
||||
|
||||
/* The following is very vectorizable... */
|
||||
@ -172,15 +179,15 @@ sprite_op(const struct sprite *sprite, int x_offset, int y_offset,
|
||||
}
|
||||
|
||||
else
|
||||
out_pixel[0] = in_pixel[0],
|
||||
out_pixel[1] = in_pixel[1],
|
||||
out_pixel[2] = in_pixel[2],
|
||||
{
|
||||
out_pixel[0] = in_pixel[0];
|
||||
out_pixel[1] = in_pixel[1];
|
||||
out_pixel[2] = in_pixel[2];
|
||||
out_pixel[3] = in_pixel[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
while (++x < image->width);
|
||||
}
|
||||
while (++y < image->height);
|
||||
} while (++x < image->width);
|
||||
} while (++y < image->height);
|
||||
}
|
||||
}
|
||||
|
||||
@ -224,9 +231,8 @@ create_sprite(struct sprite *sprite, int *argc, const char ***argv)
|
||||
|
||||
if (buffer != NULL)
|
||||
{
|
||||
if (png_image_finish_read(&image, NULL/*background*/, buffer,
|
||||
0/*row_stride*/,
|
||||
NULL/*colormap for PNG_FORMAT_FLAG_COLORMAP*/))
|
||||
if (png_image_finish_read(&image, NULL /*background*/, buffer,
|
||||
0 /*row_stride*/, NULL /*colormap*/))
|
||||
{
|
||||
/* This is the place where the Porter-Duff 'Over' operator
|
||||
* needs to be done by this code. In fact, any image
|
||||
@ -245,14 +251,14 @@ create_sprite(struct sprite *sprite, int *argc, const char ***argv)
|
||||
{
|
||||
free(buffer);
|
||||
fprintf(stderr, "simpleover: read %s: %s\n", (*argv)[0],
|
||||
image.message);
|
||||
image.message);
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "simpleover: out of memory: %lu bytes\n",
|
||||
(unsigned long)PNG_IMAGE_SIZE(image));
|
||||
(unsigned long)PNG_IMAGE_SIZE(image));
|
||||
|
||||
/* png_image_free must be called if we abort the Simplified API
|
||||
* read because of a problem detected in this code. If problems
|
||||
@ -290,8 +296,9 @@ create_sprite(struct sprite *sprite, int *argc, const char ***argv)
|
||||
save.flags = PNG_IMAGE_FLAG_FAST;
|
||||
save.colormap_entries = 0;
|
||||
|
||||
if (png_image_write_to_stdio(&save, sprite->file, 1/*convert_to_8_bit*/,
|
||||
sprite->buffer, 0/*row_stride*/, NULL/*colormap*/))
|
||||
if (png_image_write_to_stdio(&save, sprite->file, 1 /*convert_to_8_bit*/,
|
||||
sprite->buffer, 0 /*row_stride*/,
|
||||
NULL /*colormap*/))
|
||||
{
|
||||
/* Success; the buffer is no longer needed: */
|
||||
free(sprite->buffer);
|
||||
@ -301,19 +308,20 @@ create_sprite(struct sprite *sprite, int *argc, const char ***argv)
|
||||
|
||||
else
|
||||
fprintf(stderr, "simpleover: write sprite %s: %s\n", sprite->name,
|
||||
save.message);
|
||||
save.message);
|
||||
}
|
||||
|
||||
else
|
||||
fprintf(stderr, "simpleover: sprite %s: could not allocate tmpfile: %s\n",
|
||||
sprite->name, strerror(errno));
|
||||
fprintf(stderr,
|
||||
"simpleover: sprite %s: could not allocate tmpfile: %s\n",
|
||||
sprite->name, strerror(errno));
|
||||
|
||||
return 0; /* fail */
|
||||
}
|
||||
|
||||
static int
|
||||
add_sprite(png_imagep output, png_bytep out_buf, struct sprite *sprite,
|
||||
int *argc, const char ***argv)
|
||||
int *argc, const char ***argv)
|
||||
{
|
||||
/* Given a --add argument naming this sprite, perform the operations listed
|
||||
* in the following arguments. The arguments are expected to have the form
|
||||
@ -334,13 +342,13 @@ add_sprite(png_imagep output, png_bytep out_buf, struct sprite *sprite,
|
||||
* will fit.
|
||||
*/
|
||||
if (x < 0 || y < 0 ||
|
||||
(unsigned)/*SAFE*/x >= output->width ||
|
||||
(unsigned)/*SAFE*/y >= output->height ||
|
||||
sprite->width > output->width-x ||
|
||||
sprite->height > output->height-y)
|
||||
/*SAFE*/ (unsigned)x >= output->width ||
|
||||
/*SAFE*/ (unsigned)y >= output->height ||
|
||||
sprite->width > output->width - x ||
|
||||
sprite->height > output->height - y)
|
||||
{
|
||||
fprintf(stderr, "simpleover: sprite %s @ (%d,%d) outside image\n",
|
||||
sprite->name, x, y);
|
||||
sprite->name, x, y);
|
||||
/* Could just skip this, but for the moment it is an error */
|
||||
return 0; /* error */
|
||||
}
|
||||
@ -359,10 +367,10 @@ add_sprite(png_imagep output, png_bytep out_buf, struct sprite *sprite,
|
||||
{
|
||||
in.format = PNG_FORMAT_RGB; /* force compose */
|
||||
|
||||
if (png_image_finish_read(&in, NULL/*background*/,
|
||||
out_buf + (y*output->width + x)*3/*RGB*/,
|
||||
output->width*3/*row_stride*/,
|
||||
NULL/*colormap for PNG_FORMAT_FLAG_COLORMAP*/))
|
||||
if (png_image_finish_read(
|
||||
&in, NULL /*background*/,
|
||||
out_buf + (y * output->width + x) * 3 /*RGB*/,
|
||||
output->width * 3 /*row_stride*/, NULL /*colormap*/))
|
||||
{
|
||||
++*argv, --*argc;
|
||||
continue;
|
||||
@ -371,7 +379,7 @@ add_sprite(png_imagep output, png_bytep out_buf, struct sprite *sprite,
|
||||
|
||||
/* The read failed: */
|
||||
fprintf(stderr, "simpleover: add sprite %s: %s\n", sprite->name,
|
||||
in.message);
|
||||
in.message);
|
||||
return 0; /* error */
|
||||
}
|
||||
}
|
||||
@ -379,7 +387,7 @@ add_sprite(png_imagep output, png_bytep out_buf, struct sprite *sprite,
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "simpleover: --add='%s': invalid position %s\n",
|
||||
sprite->name, (*argv)[0]);
|
||||
sprite->name, (*argv)[0]);
|
||||
return 0; /* error */
|
||||
}
|
||||
}
|
||||
@ -389,10 +397,10 @@ add_sprite(png_imagep output, png_bytep out_buf, struct sprite *sprite,
|
||||
|
||||
static int
|
||||
simpleover_process(png_imagep output, png_bytep out_buf, int argc,
|
||||
const char **argv)
|
||||
const char **argv)
|
||||
{
|
||||
int result = 1; /* success */
|
||||
# define csprites 10/*limit*/
|
||||
# define csprites 10 /*limit*/
|
||||
# define str(a) #a
|
||||
int nsprites = 0;
|
||||
struct sprite sprites[csprites];
|
||||
@ -412,23 +420,25 @@ simpleover_process(png_imagep output, png_bytep out_buf, int argc,
|
||||
sprites[nsprites].width = sprites[nsprites].height = 0;
|
||||
sprites[nsprites].name[0] = 0;
|
||||
|
||||
n = sscanf(argv[0], "--sprite=%u,%u,%" str(sprite_name_chars) "s%c",
|
||||
&sprites[nsprites].width, &sprites[nsprites].height,
|
||||
sprites[nsprites].name, &tombstone);
|
||||
n = sscanf(argv[0],
|
||||
"--sprite=%u,%u,%" str(sprite_name_chars) "s%c",
|
||||
&sprites[nsprites].width, &sprites[nsprites].height,
|
||||
sprites[nsprites].name, &tombstone);
|
||||
|
||||
if ((n == 2 || n == 3) &&
|
||||
sprites[nsprites].width > 0 && sprites[nsprites].height > 0)
|
||||
(sprites[nsprites].width > 0) &&
|
||||
(sprites[nsprites].height > 0))
|
||||
{
|
||||
size_t buf_size, tmp;
|
||||
|
||||
/* Default a name if not given. */
|
||||
if (sprites[nsprites].name[0] == 0)
|
||||
sprintf(sprites[nsprites].name, "sprite-%d", nsprites+1);
|
||||
sprintf(sprites[nsprites].name, "sprite-%d", nsprites + 1);
|
||||
|
||||
/* Allocate a buffer for the sprite and calculate the buffer
|
||||
* size:
|
||||
*/
|
||||
buf_size = sizeof (png_uint_16 [4]);
|
||||
buf_size = sizeof(png_uint_16[4]);
|
||||
buf_size *= sprites[nsprites].width;
|
||||
buf_size *= sprites[nsprites].height;
|
||||
|
||||
@ -437,7 +447,7 @@ simpleover_process(png_imagep output, png_bytep out_buf, int argc,
|
||||
tmp /= sprites[nsprites].width;
|
||||
tmp /= sprites[nsprites].height;
|
||||
|
||||
if (tmp == sizeof (png_uint_16 [4]))
|
||||
if (tmp == sizeof(png_uint_16[4]))
|
||||
{
|
||||
sprites[nsprites].buffer = malloc(buf_size);
|
||||
/* This buffer must be initialized to transparent: */
|
||||
@ -448,7 +458,7 @@ simpleover_process(png_imagep output, png_bytep out_buf, int argc,
|
||||
sprites[nsprites].file = NULL;
|
||||
++argv, --argc;
|
||||
|
||||
if (create_sprite(sprites+nsprites++, &argc, &argv))
|
||||
if (create_sprite(sprites + nsprites++, &argc, &argv))
|
||||
{
|
||||
result = 1; /* still ok */
|
||||
continue;
|
||||
@ -466,7 +476,8 @@ simpleover_process(png_imagep output, png_bytep out_buf, int argc,
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "simpleover: %s: invalid sprite (%u,%u)\n",
|
||||
argv[0], sprites[nsprites].width, sprites[nsprites].height);
|
||||
argv[0],
|
||||
sprites[nsprites].width, sprites[nsprites].height);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -480,7 +491,7 @@ simpleover_process(png_imagep output, png_bytep out_buf, int argc,
|
||||
|
||||
else if (strncmp(argv[0], "--add=", 6) == 0)
|
||||
{
|
||||
const char *name = argv[0]+6;
|
||||
const char *name = argv[0] + 6;
|
||||
int isprite = nsprites;
|
||||
|
||||
++argv, --argc;
|
||||
@ -489,7 +500,8 @@ simpleover_process(png_imagep output, png_bytep out_buf, int argc,
|
||||
{
|
||||
if (strcmp(sprites[isprite].name, name) == 0)
|
||||
{
|
||||
if (!add_sprite(output, out_buf, sprites+isprite, &argc, &argv))
|
||||
if (!add_sprite(output, out_buf, sprites + isprite,
|
||||
&argc, &argv))
|
||||
goto out; /* error in add_sprite */
|
||||
|
||||
break;
|
||||
@ -498,7 +510,8 @@ simpleover_process(png_imagep output, png_bytep out_buf, int argc,
|
||||
|
||||
if (isprite < 0) /* sprite not found */
|
||||
{
|
||||
fprintf(stderr, "simpleover: --add='%s': sprite not found\n", name);
|
||||
fprintf(stderr, "simpleover: --add='%s': sprite not found\n",
|
||||
name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -526,7 +539,8 @@ out:
|
||||
return result;
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
int
|
||||
main(int argc, const char **argv)
|
||||
{
|
||||
int result = 1; /* default to fail */
|
||||
|
||||
@ -536,7 +550,7 @@ int main(int argc, const char **argv)
|
||||
const char *output = NULL;
|
||||
png_image image;
|
||||
|
||||
if (argc > 2 && argv[2][0] != '-'/*an operation*/)
|
||||
if (argc > 2 && argv[2][0] != '-' /*an operation*/)
|
||||
{
|
||||
output = argv[2];
|
||||
argi = 3;
|
||||
@ -558,7 +572,7 @@ int main(int argc, const char **argv)
|
||||
png_color background = {0, 0xff, 0}; /* fully saturated green */
|
||||
|
||||
if (png_image_finish_read(&image, &background, buffer,
|
||||
0/*row_stride*/, NULL/*colormap for PNG_FORMAT_FLAG_COLORMAP */))
|
||||
0 /*row_stride*/, NULL /*colormap*/))
|
||||
{
|
||||
/* At this point png_image_finish_read has cleaned up the
|
||||
* allocated data in png_image, and only the buffer needs to be
|
||||
@ -566,22 +580,24 @@ int main(int argc, const char **argv)
|
||||
*
|
||||
* Perform the remaining operations:
|
||||
*/
|
||||
if (simpleover_process(&image, buffer, argc-argi, argv+argi))
|
||||
if (simpleover_process(&image, buffer,
|
||||
argc - argi, argv + argi))
|
||||
{
|
||||
/* Write the output: */
|
||||
if ((output != NULL &&
|
||||
png_image_write_to_file(&image, output,
|
||||
0/*convert_to_8bit*/, buffer, 0/*row_stride*/,
|
||||
NULL/*colormap*/)) ||
|
||||
png_image_write_to_file(
|
||||
&image, output, 0 /*convert_to_8bit*/, buffer,
|
||||
0 /*row_stride*/, NULL /*colormap*/)) ||
|
||||
(output == NULL &&
|
||||
png_image_write_to_stdio(&image, stdout,
|
||||
0/*convert_to_8bit*/, buffer, 0/*row_stride*/,
|
||||
NULL/*colormap*/)))
|
||||
png_image_write_to_stdio(
|
||||
&image, stdout, 0 /*convert_to_8bit*/, buffer,
|
||||
0 /*row_stride*/, NULL /*colormap*/)))
|
||||
result = 0;
|
||||
|
||||
else
|
||||
fprintf(stderr, "simpleover: write %s: %s\n",
|
||||
output == NULL ? "stdout" : output, image.message);
|
||||
output == NULL ? "stdout" : output,
|
||||
image.message);
|
||||
}
|
||||
|
||||
/* else simpleover_process writes an error message */
|
||||
@ -589,7 +605,7 @@ int main(int argc, const char **argv)
|
||||
|
||||
else
|
||||
fprintf(stderr, "simpleover: read %s: %s\n", argv[1],
|
||||
image.message);
|
||||
image.message);
|
||||
|
||||
free(buffer);
|
||||
}
|
||||
@ -597,7 +613,7 @@ int main(int argc, const char **argv)
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "simpleover: out of memory: %lu bytes\n",
|
||||
(unsigned long)PNG_IMAGE_SIZE(image));
|
||||
(unsigned long)PNG_IMAGE_SIZE(image));
|
||||
|
||||
/* This is the only place where a 'free' is required; libpng does
|
||||
* the cleanup on error and success, but in this case we couldn't
|
||||
@ -617,7 +633,8 @@ int main(int argc, const char **argv)
|
||||
else
|
||||
{
|
||||
/* Usage message */
|
||||
fprintf(stderr,
|
||||
fprintf(
|
||||
stderr,
|
||||
"simpleover: usage: simpleover background.png [output.png]\n"
|
||||
" Output 'background.png' as a 24-bit RGB PNG file in 'output.png'\n"
|
||||
" or, if not given, stdout. 'background.png' will be composited\n"
|
||||
@ -628,13 +645,13 @@ int main(int argc, const char **argv)
|
||||
" --sprite=width,height,name {[--at=x,y] {sprite.png}}\n"
|
||||
" Produce a transparent sprite of size (width,height) and with\n"
|
||||
" name 'name'.\n"
|
||||
" For each sprite.png composite it using a Porter-Duff 'Over'\n"
|
||||
" operation at offset (x,y) in the sprite (defaulting to (0,0)).\n"
|
||||
" For each sprite.png composite it is using a Porter-Duff 'Over'\n"
|
||||
" operation at offset (x,y) in the sprite, defaulting to (0,0).\n"
|
||||
" Input PNGs will be truncated to the area of the sprite.\n"
|
||||
"\n"
|
||||
" --add='name' {x,y}\n"
|
||||
" Optionally, before output, composite a sprite, 'name', which\n"
|
||||
" must have been previously produced using --sprite, at each\n"
|
||||
" must have been previously produced using --sprite at each\n"
|
||||
" offset (x,y) in the output image. Each sprite must fit\n"
|
||||
" completely within the output image.\n"
|
||||
"\n"
|
||||
@ -645,4 +662,3 @@ int main(int argc, const char **argv)
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif /* SIMPLIFIED_READ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user