mirror of
https://git.code.sf.net/p/libpng/code.git
synced 2025-07-10 18:04:09 +02:00
examples: Refactor and reformat using clang-format
Add contrib/examples/.clang-format, tailored to fit the existing code as closely as possible. The end goal is to set up automatic formatting for the entire libpng source tree. We're doing this experiment in this subdirectory, for now. Also make refactoring changes, as follows: * Rewrite the preprocessor checks `#if PNG_FOO_SUPPORTED` to stop compilation immediately, with a descriptive `#error` about what needs to be supported. * Rewrite and reflow comments, add braces and brackets, and make other minor modifications that are suited for the clang-format'ed code.
This commit is contained in:
parent
197bbfe0d5
commit
3bca02e274
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>
|
#include <png.h>
|
||||||
|
|
||||||
#if defined(PNG_READ_SUPPORTED) && defined(PNG_STDIO_SUPPORTED) && \
|
#if !defined(PNG_iCCP_SUPPORTED) || !defined(PNG_READ_SUPPORTED)
|
||||||
defined (PNG_iCCP_SUPPORTED)
|
#error This program requires libpng supporting the iCCP chunk and the read API
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static int verbose = 1;
|
static int verbose = 1;
|
||||||
@ -36,7 +37,8 @@ static png_byte no_profile[] = "no profile";
|
|||||||
static png_bytep
|
static png_bytep
|
||||||
extract(FILE *fp, png_uint_32 *proflen)
|
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_infop info_ptr = NULL;
|
||||||
png_bytep result = NULL;
|
png_bytep result = NULL;
|
||||||
|
|
||||||
@ -69,7 +71,7 @@ extract(FILE *fp, png_uint_32 *proflen)
|
|||||||
png_bytep profile;
|
png_bytep profile;
|
||||||
|
|
||||||
if (png_get_iCCP(png_ptr, info_ptr, &name, &compression_type, &profile,
|
if (png_get_iCCP(png_ptr, info_ptr, &name, &compression_type, &profile,
|
||||||
proflen) & PNG_INFO_iCCP)
|
proflen) & PNG_INFO_iCCP)
|
||||||
{
|
{
|
||||||
result = malloc(*proflen);
|
result = malloc(*proflen);
|
||||||
if (result != NULL)
|
if (result != NULL)
|
||||||
@ -107,7 +109,7 @@ extract_one_file(const char *filename)
|
|||||||
const char *ep = strrchr(filename, '.');
|
const char *ep = strrchr(filename, '.');
|
||||||
|
|
||||||
if (ep != NULL)
|
if (ep != NULL)
|
||||||
len = ep-filename;
|
len = ep - filename;
|
||||||
|
|
||||||
else
|
else
|
||||||
len = strlen(filename);
|
len = strlen(filename);
|
||||||
@ -119,14 +121,14 @@ extract_one_file(const char *filename)
|
|||||||
FILE *of;
|
FILE *of;
|
||||||
|
|
||||||
memcpy(output, filename, len);
|
memcpy(output, filename, len);
|
||||||
strcpy(output+len, ".icc");
|
strcpy(output + len, ".icc");
|
||||||
|
|
||||||
of = fopen(output, "wb");
|
of = fopen(output, "wb");
|
||||||
if (of != NULL)
|
if (of != NULL)
|
||||||
{
|
{
|
||||||
if (fwrite(profile, proflen, 1, of) == 1 &&
|
if (fwrite(profile, proflen, 1, of) == 1 &&
|
||||||
fflush(of) == 0 &&
|
fflush(of) == 0 &&
|
||||||
fclose(of) == 0)
|
fclose(of) == 0)
|
||||||
{
|
{
|
||||||
if (verbose)
|
if (verbose)
|
||||||
printf("%s -> %s\n", filename, output);
|
printf("%s -> %s\n", filename, output);
|
||||||
@ -161,8 +163,8 @@ extract_one_file(const char *filename)
|
|||||||
else
|
else
|
||||||
fprintf(stderr, "%s: could not open file\n", filename);
|
fprintf(stderr, "%s: could not open file\n", filename);
|
||||||
|
|
||||||
if (fp != NULL)
|
if (fp != NULL)
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -173,7 +175,7 @@ main(int argc, char **argv)
|
|||||||
int i;
|
int i;
|
||||||
int extracted = 0;
|
int extracted = 0;
|
||||||
|
|
||||||
for (i=1; i<argc; ++i)
|
for (i = 1; i < argc; ++i)
|
||||||
{
|
{
|
||||||
if (strcmp(argv[i], "-q") == 0)
|
if (strcmp(argv[i], "-q") == 0)
|
||||||
verbose = 0;
|
verbose = 0;
|
||||||
@ -185,4 +187,3 @@ main(int argc, char **argv)
|
|||||||
/* Exit code is true if any extract succeeds */
|
/* Exit code is true if any extract succeeds */
|
||||||
return extracted == 0;
|
return extracted == 0;
|
||||||
}
|
}
|
||||||
#endif /* READ && STDIO && iCCP */
|
|
||||||
|
@ -15,8 +15,8 @@
|
|||||||
* images. Normally you would call png_set_interlace_handling() to have libpng
|
* 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
|
* deal with the interlace for you, but that obliges you to buffer half of the
|
||||||
* image to assemble the interlaced rows. In this code
|
* image to assemble the interlaced rows. In this code
|
||||||
* png_set_interlace_handling() is not called and, instead, the code handles the
|
* png_set_interlace_handling() is not called and, instead, the code handles
|
||||||
* interlace passes directly looking for the required pixel.
|
* the interlace passes directly looking for the required pixel.
|
||||||
*/
|
*/
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -27,34 +27,37 @@
|
|||||||
*/
|
*/
|
||||||
#include "../../png.h"
|
#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. */
|
/* Return component 'c' of pixel 'x' from the given row. */
|
||||||
static unsigned int
|
static unsigned int
|
||||||
component(png_const_bytep row, png_uint_32 x, unsigned int c,
|
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
|
/* 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
|
* 2^37 bits wide (for a 64-bit pixel - the largest possible) and hence
|
||||||
* bytes wide. Since the row fitted into memory, however, the following must
|
* 2^34 bytes wide. Since the row fitted into memory, the following must
|
||||||
* work:
|
* work:
|
||||||
*/
|
*/
|
||||||
png_uint_32 bit_offset_hi = bit_depth * ((x >> 6) * channels);
|
png_uint_32 bit_offset_hi = bit_depth * ((x >> 6) * channels);
|
||||||
png_uint_32 bit_offset_lo = bit_depth * ((x & 0x3f) * channels + c);
|
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;
|
row += bit_offset_lo >> 3;
|
||||||
bit_offset_lo &= 0x07;
|
bit_offset_lo &= 0x07;
|
||||||
|
|
||||||
/* PNG pixels are packed into bytes to put the first pixel in the highest
|
/* 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
|
* bits of the byte, and into two bytes for 16-bit values with the high
|
||||||
* first, so:
|
* 8 bits first, so:
|
||||||
*/
|
*/
|
||||||
switch (bit_depth)
|
switch (bit_depth)
|
||||||
{
|
{
|
||||||
case 1: return (row[0] >> (7-bit_offset_lo)) & 0x01;
|
case 1: return (row[0] >> (7 - bit_offset_lo)) & 0x01;
|
||||||
case 2: return (row[0] >> (6-bit_offset_lo)) & 0x03;
|
case 2: return (row[0] >> (6 - bit_offset_lo)) & 0x03;
|
||||||
case 4: return (row[0] >> (4-bit_offset_lo)) & 0x0f;
|
case 4: return (row[0] >> (4 - bit_offset_lo)) & 0x0f;
|
||||||
case 8: return row[0];
|
case 8: return row[0];
|
||||||
case 16: return (row[0] << 8) + row[1];
|
case 16: return (row[0] << 8) + row[1];
|
||||||
default:
|
default:
|
||||||
@ -71,7 +74,7 @@ component(png_const_bytep row, png_uint_32 x, unsigned int c,
|
|||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
print_pixel(png_structp png_ptr, png_infop info_ptr, png_const_bytep row,
|
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);
|
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;
|
int num_palette = 0;
|
||||||
|
|
||||||
if ((png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette) &
|
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;
|
png_bytep trans_alpha = NULL;
|
||||||
int num_trans = 0;
|
int num_trans = 0;
|
||||||
if ((png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans,
|
if ((png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans,
|
||||||
NULL) & PNG_INFO_tRNS) && num_trans > 0 &&
|
NULL) & PNG_INFO_tRNS) &&
|
||||||
trans_alpha != NULL)
|
(num_trans > 0) &&
|
||||||
|
(trans_alpha != NULL))
|
||||||
printf("INDEXED %u = %d %d %d %d\n", index,
|
printf("INDEXED %u = %d %d %d %d\n", index,
|
||||||
palette[index].red, palette[index].green,
|
palette[index].red, palette[index].green,
|
||||||
palette[index].blue,
|
palette[index].blue,
|
||||||
index < num_trans ? trans_alpha[index] : 255);
|
index < num_trans ? trans_alpha[index] : 255);
|
||||||
|
|
||||||
else /* no transparency */
|
else /* no transparency */
|
||||||
printf("INDEXED %u = %d %d %d\n", index,
|
printf("INDEXED %u = %d %d %d\n", index, palette[index].red,
|
||||||
palette[index].red, palette[index].green,
|
palette[index].green, palette[index].blue);
|
||||||
palette[index].blue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
@ -117,20 +122,20 @@ print_pixel(png_structp png_ptr, png_infop info_ptr, png_const_bytep row,
|
|||||||
|
|
||||||
case PNG_COLOR_TYPE_RGB:
|
case PNG_COLOR_TYPE_RGB:
|
||||||
printf("RGB %u %u %u\n", component(row, x, 0, bit_depth, 3),
|
printf("RGB %u %u %u\n", component(row, x, 0, bit_depth, 3),
|
||||||
component(row, x, 1, bit_depth, 3),
|
component(row, x, 1, bit_depth, 3),
|
||||||
component(row, x, 2, bit_depth, 3));
|
component(row, x, 2, bit_depth, 3));
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case PNG_COLOR_TYPE_GRAY_ALPHA:
|
case PNG_COLOR_TYPE_GRAY_ALPHA:
|
||||||
printf("GRAY+ALPHA %u %u\n", component(row, x, 0, bit_depth, 2),
|
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;
|
return;
|
||||||
|
|
||||||
case PNG_COLOR_TYPE_RGB_ALPHA:
|
case PNG_COLOR_TYPE_RGB_ALPHA:
|
||||||
printf("RGBA %u %u %u %u\n", component(row, x, 0, bit_depth, 4),
|
printf("RGBA %u %u %u %u\n", component(row, x, 0, bit_depth, 4),
|
||||||
component(row, x, 1, bit_depth, 4),
|
component(row, x, 1, bit_depth, 4),
|
||||||
component(row, x, 2, bit_depth, 4),
|
component(row, x, 2, bit_depth, 4),
|
||||||
component(row, x, 3, bit_depth, 4));
|
component(row, x, 3, bit_depth, 4));
|
||||||
return;
|
return;
|
||||||
|
|
||||||
default:
|
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
|
/* This program uses the default, <setjmp.h> based, libpng error handling
|
||||||
* mechanism, therefore any local variable that exists before the call to
|
* 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
|
* be declared with 'volatile' to ensure that their values don't get
|
||||||
* destroyed by longjmp:
|
* destroyed by longjmp:
|
||||||
*/
|
*/
|
||||||
volatile int result = 1/*fail*/;
|
volatile int result = 1 /*fail*/;
|
||||||
|
|
||||||
if (argc == 4)
|
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
|
* writes error messages to stderr. Creating the png_struct is a
|
||||||
* little tricky; just copy the following code.
|
* little tricky; just copy the following code.
|
||||||
*/
|
*/
|
||||||
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
|
png_structp png_ptr =
|
||||||
NULL, NULL, NULL);
|
png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||||
|
|
||||||
if (png_ptr != 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
|
* space. In this case png_malloc is used - it will not
|
||||||
* return if memory isn't available.
|
* return if memory isn't available.
|
||||||
*/
|
*/
|
||||||
row = png_malloc(png_ptr, png_get_rowbytes(png_ptr,
|
row =
|
||||||
info_ptr));
|
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.
|
* to a local here - just use row for the png_free below.
|
||||||
*/
|
*/
|
||||||
row_tmp = row;
|
row_tmp = row;
|
||||||
|
|
||||||
/* All the information we need is in the header is returned by
|
/* All the information we need is in the header returned by
|
||||||
* png_get_IHDR, if this fails we can now use 'png_error' to
|
* png_get_IHDR. If this fails, we can use 'png_error' to
|
||||||
* signal the error and return control to the setjmp above.
|
* signal the error and return control to the setjmp above.
|
||||||
*/
|
*/
|
||||||
if (png_get_IHDR(png_ptr, info_ptr, &width, &height,
|
if (png_get_IHDR(png_ptr, info_ptr, &width, &height,
|
||||||
&bit_depth, &color_type, &interlace_method,
|
&bit_depth, &color_type, &interlace_method,
|
||||||
&compression_method, &filter_method))
|
&compression_method, &filter_method))
|
||||||
{
|
{
|
||||||
int passes, pass;
|
int passes, pass;
|
||||||
|
|
||||||
@ -242,7 +248,7 @@ int main(int argc, const char **argv)
|
|||||||
/* Now read the pixels, pass-by-pass, row-by-row: */
|
/* Now read the pixels, pass-by-pass, row-by-row: */
|
||||||
png_start_read_image(png_ptr);
|
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 ystart, xstart, ystep, xstep;
|
||||||
png_uint_32 py;
|
png_uint_32 py;
|
||||||
@ -299,19 +305,27 @@ int main(int argc, const char **argv)
|
|||||||
* are, of course, much better ways of doing this
|
* are, of course, much better ways of doing this
|
||||||
* than using a for loop:
|
* than using a for loop:
|
||||||
*/
|
*/
|
||||||
if (y == py) for (px = xstart, ppx = 0;
|
if (y == py)
|
||||||
px < width; px += xstep, ++ppx) if (x == px)
|
|
||||||
{
|
{
|
||||||
/* 'ppx' is the index of the pixel in the row
|
for (px = xstart, ppx = 0;
|
||||||
* buffer.
|
px < width;
|
||||||
*/
|
px += xstep, ++ppx)
|
||||||
print_pixel(png_ptr, info_ptr, row_tmp, 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
|
/* Now terminate the loops early - we have
|
||||||
* found and handled the required data.
|
* found and handled the required data.
|
||||||
*/
|
*/
|
||||||
goto pass_loop_end;
|
goto pass_loop_end;
|
||||||
} /* x loop */
|
} /* x loop */
|
||||||
|
}
|
||||||
|
}
|
||||||
} /* y loop */
|
} /* y loop */
|
||||||
} /* pass loop */
|
} /* pass loop */
|
||||||
|
|
||||||
@ -323,7 +337,6 @@ int main(int argc, const char **argv)
|
|||||||
|
|
||||||
else
|
else
|
||||||
png_error(png_ptr, "pngpixel: png_get_IHDR failed");
|
png_error(png_ptr, "pngpixel: png_get_IHDR failed");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
@ -349,7 +362,8 @@ int main(int argc, const char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
else
|
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);
|
png_destroy_read_struct(&png_ptr, NULL, NULL);
|
||||||
}
|
}
|
||||||
@ -368,4 +382,3 @@ int main(int argc, const char **argv)
|
|||||||
|
|
||||||
return result;
|
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'
|
* Read a PNG and write it out in a fixed format, using the 'simplified API'
|
||||||
* that was introduced in libpng-1.6.0.
|
* that was introduced in libpng-1.6.0.
|
||||||
*
|
*
|
||||||
* This sample code is just the code from the top of 'example.c' with some error
|
* This sample code is just the code from 'example.c' with some error handling
|
||||||
* handling added. See example.c for more comments.
|
* added. See example.c in the top-level libpng directory for more comments.
|
||||||
*/
|
*/
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -20,10 +20,15 @@
|
|||||||
* ensure the code picks up the local libpng implementation:
|
* ensure the code picks up the local libpng implementation:
|
||||||
*/
|
*/
|
||||||
#include "../../png.h"
|
#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;
|
int result = 1;
|
||||||
|
|
||||||
@ -48,22 +53,22 @@ int main(int argc, const char **argv)
|
|||||||
|
|
||||||
if (buffer != NULL)
|
if (buffer != NULL)
|
||||||
{
|
{
|
||||||
if (png_image_finish_read(&image, NULL/*background*/, buffer,
|
if (png_image_finish_read(&image, NULL /*background*/, buffer,
|
||||||
0/*row_stride*/, NULL/*colormap for PNG_FORMAT_FLAG_COLORMAP */))
|
0 /*row_stride*/, NULL /*colormap */))
|
||||||
{
|
{
|
||||||
if (png_image_write_to_file(&image, argv[2],
|
if (png_image_write_to_file(
|
||||||
0/*convert_to_8bit*/, buffer, 0/*row_stride*/,
|
&image, argv[2], 0 /*convert_to_8bit*/, buffer,
|
||||||
NULL/*colormap*/))
|
0 /*row_stride*/, NULL /*colormap*/))
|
||||||
result = 0;
|
result = 0;
|
||||||
|
|
||||||
else
|
else
|
||||||
fprintf(stderr, "pngtopng: write %s: %s\n", argv[2],
|
fprintf(stderr, "pngtopng: write %s: %s\n", argv[2],
|
||||||
image.message);
|
image.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
fprintf(stderr, "pngtopng: read %s: %s\n", argv[1],
|
fprintf(stderr, "pngtopng: read %s: %s\n", argv[1],
|
||||||
image.message);
|
image.message);
|
||||||
|
|
||||||
free(buffer);
|
free(buffer);
|
||||||
}
|
}
|
||||||
@ -71,7 +76,7 @@ int main(int argc, const char **argv)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
fprintf(stderr, "pngtopng: out of memory: %lu bytes\n",
|
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
|
/* 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
|
* 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;
|
return result;
|
||||||
}
|
}
|
||||||
#endif /* READ && WRITE */
|
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
* United States.
|
* United States.
|
||||||
*
|
*
|
||||||
* Read several PNG files, which should have an alpha channel or transparency
|
* 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
|
* information, and composite them together to produce one or more 16-bit
|
||||||
* RGBA intermediates. This involves doing the correct 'over' composition to
|
* linear RGBA intermediates. This involves doing the 'over' compositing
|
||||||
* combine the alpha channels and corresponding data.
|
* operation to combine the alpha channels and corresponding data.
|
||||||
*
|
*
|
||||||
* Finally read an output (background) PNG using the 24-bit RGB format (the
|
* 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
|
* 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
|
* 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
|
* 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,
|
* 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
|
* be regarded as being layered one on top of the other with the first
|
||||||
* on the command line) being at the bottom and the last on the top.
|
* (leftmost on the command line) being at the bottom and the last on the top.
|
||||||
*/
|
*/
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -44,54 +44,61 @@
|
|||||||
*/
|
*/
|
||||||
#include "../../png.h"
|
#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
|
#define sprite_name_chars 15
|
||||||
struct sprite {
|
struct sprite
|
||||||
FILE *file;
|
{
|
||||||
png_uint_16p buffer;
|
FILE *file;
|
||||||
unsigned int width;
|
png_uint_16p buffer;
|
||||||
unsigned int height;
|
unsigned int width;
|
||||||
char name[sprite_name_chars+1];
|
unsigned int height;
|
||||||
|
char name[sprite_name_chars + 1];
|
||||||
};
|
};
|
||||||
|
|
||||||
#if 0 /* div by 65535 test program */
|
#if 0 /* div by 65535 test program */
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
int main(void) {
|
int
|
||||||
|
main(void)
|
||||||
|
{
|
||||||
double err = 0;
|
double err = 0;
|
||||||
unsigned int xerr = 0;
|
unsigned int xerr = 0;
|
||||||
unsigned int r = 32769;
|
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 {
|
if (t < x)
|
||||||
unsigned int t = x + (x >> 16) /*+ (x >> 31)*/ + r;
|
{
|
||||||
double v = x, errtest;
|
fprintf(stderr, "overflow: %u+%u -> %u\n", x, r, t);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (t < x) {
|
v /= 65535;
|
||||||
fprintf(stderr, "overflow: %u+%u -> %u\n", x, r, t);
|
errtest = v;
|
||||||
return 1;
|
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;
|
} while (++x <= 65535U * 65535U);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("error %f @ %u\n", err, xerr);
|
printf("error %f @ %u\n", err, xerr);
|
||||||
|
|
||||||
@ -101,7 +108,7 @@ int main(void) {
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
sprite_op(const struct sprite *sprite, int x_offset, int y_offset,
|
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
|
/* This is where the Porter-Duff 'Over' operator is evaluated; change this
|
||||||
* code to change the operator (this could be parameterized). Any other
|
* 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
|
/* Check for an x or y offset that pushes any part of the image beyond the
|
||||||
* right or bottom of the sprite:
|
* right or bottom of the sprite:
|
||||||
*/
|
*/
|
||||||
if ((y_offset < 0 || (unsigned)/*SAFE*/y_offset < sprite->height) &&
|
if ((y_offset < 0 || /*SAFE*/ (unsigned)y_offset < sprite->height) &&
|
||||||
(x_offset < 0 || (unsigned)/*SAFE*/x_offset < sprite->width))
|
(x_offset < 0 || /*SAFE*/ (unsigned)x_offset < sprite->width))
|
||||||
{
|
{
|
||||||
unsigned int y = 0;
|
unsigned int y = 0;
|
||||||
|
|
||||||
@ -130,7 +137,7 @@ sprite_op(const struct sprite *sprite, int x_offset, int y_offset,
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
/* In and out are RGBA values, so: */
|
/* 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];
|
png_uint_32 in_alpha = in_pixel[3];
|
||||||
|
|
||||||
/* This is the optimized Porter-Duff 'Over' operation, when the
|
/* 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)
|
if (in_alpha > 0)
|
||||||
{
|
{
|
||||||
png_uint_16 *out_pixel = sprite->buffer +
|
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: */
|
/* This is the weight to apply to the output: */
|
||||||
in_alpha = 65535-in_alpha;
|
in_alpha = 65535 - in_alpha;
|
||||||
|
|
||||||
if (in_alpha > 0)
|
if (in_alpha > 0)
|
||||||
{
|
{
|
||||||
@ -159,9 +166,9 @@ sprite_op(const struct sprite *sprite, int x_offset, int y_offset,
|
|||||||
*/
|
*/
|
||||||
png_uint_32 tmp;
|
png_uint_32 tmp;
|
||||||
|
|
||||||
# define compose(c)\
|
# define compose(c) \
|
||||||
tmp = out_pixel[c] * in_alpha;\
|
tmp = out_pixel[c] * in_alpha; \
|
||||||
tmp = (tmp + (tmp >> 16) + 32769) >> 16;\
|
tmp = (tmp + (tmp >> 16) + 32769) >> 16; \
|
||||||
out_pixel[c] = tmp + in_pixel[c]
|
out_pixel[c] = tmp + in_pixel[c]
|
||||||
|
|
||||||
/* The following is very vectorizable... */
|
/* The following is very vectorizable... */
|
||||||
@ -172,15 +179,15 @@ sprite_op(const struct sprite *sprite, int x_offset, int y_offset,
|
|||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
out_pixel[0] = in_pixel[0],
|
{
|
||||||
out_pixel[1] = in_pixel[1],
|
out_pixel[0] = in_pixel[0];
|
||||||
out_pixel[2] = in_pixel[2],
|
out_pixel[1] = in_pixel[1];
|
||||||
|
out_pixel[2] = in_pixel[2];
|
||||||
out_pixel[3] = in_pixel[3];
|
out_pixel[3] = in_pixel[3];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
} while (++x < image->width);
|
||||||
while (++x < image->width);
|
} while (++y < image->height);
|
||||||
}
|
|
||||||
while (++y < image->height);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,9 +231,8 @@ create_sprite(struct sprite *sprite, int *argc, const char ***argv)
|
|||||||
|
|
||||||
if (buffer != NULL)
|
if (buffer != NULL)
|
||||||
{
|
{
|
||||||
if (png_image_finish_read(&image, NULL/*background*/, buffer,
|
if (png_image_finish_read(&image, NULL /*background*/, buffer,
|
||||||
0/*row_stride*/,
|
0 /*row_stride*/, NULL /*colormap*/))
|
||||||
NULL/*colormap for PNG_FORMAT_FLAG_COLORMAP*/))
|
|
||||||
{
|
{
|
||||||
/* This is the place where the Porter-Duff 'Over' operator
|
/* This is the place where the Porter-Duff 'Over' operator
|
||||||
* needs to be done by this code. In fact, any image
|
* 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);
|
free(buffer);
|
||||||
fprintf(stderr, "simpleover: read %s: %s\n", (*argv)[0],
|
fprintf(stderr, "simpleover: read %s: %s\n", (*argv)[0],
|
||||||
image.message);
|
image.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fprintf(stderr, "simpleover: out of memory: %lu bytes\n",
|
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
|
/* png_image_free must be called if we abort the Simplified API
|
||||||
* read because of a problem detected in this code. If problems
|
* 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.flags = PNG_IMAGE_FLAG_FAST;
|
||||||
save.colormap_entries = 0;
|
save.colormap_entries = 0;
|
||||||
|
|
||||||
if (png_image_write_to_stdio(&save, sprite->file, 1/*convert_to_8_bit*/,
|
if (png_image_write_to_stdio(&save, sprite->file, 1 /*convert_to_8_bit*/,
|
||||||
sprite->buffer, 0/*row_stride*/, NULL/*colormap*/))
|
sprite->buffer, 0 /*row_stride*/,
|
||||||
|
NULL /*colormap*/))
|
||||||
{
|
{
|
||||||
/* Success; the buffer is no longer needed: */
|
/* Success; the buffer is no longer needed: */
|
||||||
free(sprite->buffer);
|
free(sprite->buffer);
|
||||||
@ -301,19 +308,20 @@ create_sprite(struct sprite *sprite, int *argc, const char ***argv)
|
|||||||
|
|
||||||
else
|
else
|
||||||
fprintf(stderr, "simpleover: write sprite %s: %s\n", sprite->name,
|
fprintf(stderr, "simpleover: write sprite %s: %s\n", sprite->name,
|
||||||
save.message);
|
save.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
fprintf(stderr, "simpleover: sprite %s: could not allocate tmpfile: %s\n",
|
fprintf(stderr,
|
||||||
sprite->name, strerror(errno));
|
"simpleover: sprite %s: could not allocate tmpfile: %s\n",
|
||||||
|
sprite->name, strerror(errno));
|
||||||
|
|
||||||
return 0; /* fail */
|
return 0; /* fail */
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
add_sprite(png_imagep output, png_bytep out_buf, struct sprite *sprite,
|
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
|
/* Given a --add argument naming this sprite, perform the operations listed
|
||||||
* in the following arguments. The arguments are expected to have the form
|
* 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.
|
* will fit.
|
||||||
*/
|
*/
|
||||||
if (x < 0 || y < 0 ||
|
if (x < 0 || y < 0 ||
|
||||||
(unsigned)/*SAFE*/x >= output->width ||
|
/*SAFE*/ (unsigned)x >= output->width ||
|
||||||
(unsigned)/*SAFE*/y >= output->height ||
|
/*SAFE*/ (unsigned)y >= output->height ||
|
||||||
sprite->width > output->width-x ||
|
sprite->width > output->width - x ||
|
||||||
sprite->height > output->height-y)
|
sprite->height > output->height - y)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "simpleover: sprite %s @ (%d,%d) outside image\n",
|
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 */
|
/* Could just skip this, but for the moment it is an error */
|
||||||
return 0; /* 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 */
|
in.format = PNG_FORMAT_RGB; /* force compose */
|
||||||
|
|
||||||
if (png_image_finish_read(&in, NULL/*background*/,
|
if (png_image_finish_read(
|
||||||
out_buf + (y*output->width + x)*3/*RGB*/,
|
&in, NULL /*background*/,
|
||||||
output->width*3/*row_stride*/,
|
out_buf + (y * output->width + x) * 3 /*RGB*/,
|
||||||
NULL/*colormap for PNG_FORMAT_FLAG_COLORMAP*/))
|
output->width * 3 /*row_stride*/, NULL /*colormap*/))
|
||||||
{
|
{
|
||||||
++*argv, --*argc;
|
++*argv, --*argc;
|
||||||
continue;
|
continue;
|
||||||
@ -371,7 +379,7 @@ add_sprite(png_imagep output, png_bytep out_buf, struct sprite *sprite,
|
|||||||
|
|
||||||
/* The read failed: */
|
/* The read failed: */
|
||||||
fprintf(stderr, "simpleover: add sprite %s: %s\n", sprite->name,
|
fprintf(stderr, "simpleover: add sprite %s: %s\n", sprite->name,
|
||||||
in.message);
|
in.message);
|
||||||
return 0; /* error */
|
return 0; /* error */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -379,7 +387,7 @@ add_sprite(png_imagep output, png_bytep out_buf, struct sprite *sprite,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
fprintf(stderr, "simpleover: --add='%s': invalid position %s\n",
|
fprintf(stderr, "simpleover: --add='%s': invalid position %s\n",
|
||||||
sprite->name, (*argv)[0]);
|
sprite->name, (*argv)[0]);
|
||||||
return 0; /* error */
|
return 0; /* error */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -389,10 +397,10 @@ add_sprite(png_imagep output, png_bytep out_buf, struct sprite *sprite,
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
simpleover_process(png_imagep output, png_bytep out_buf, int argc,
|
simpleover_process(png_imagep output, png_bytep out_buf, int argc,
|
||||||
const char **argv)
|
const char **argv)
|
||||||
{
|
{
|
||||||
int result = 1; /* success */
|
int result = 1; /* success */
|
||||||
# define csprites 10/*limit*/
|
# define csprites 10 /*limit*/
|
||||||
# define str(a) #a
|
# define str(a) #a
|
||||||
int nsprites = 0;
|
int nsprites = 0;
|
||||||
struct sprite sprites[csprites];
|
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].width = sprites[nsprites].height = 0;
|
||||||
sprites[nsprites].name[0] = 0;
|
sprites[nsprites].name[0] = 0;
|
||||||
|
|
||||||
n = sscanf(argv[0], "--sprite=%u,%u,%" str(sprite_name_chars) "s%c",
|
n = sscanf(argv[0],
|
||||||
&sprites[nsprites].width, &sprites[nsprites].height,
|
"--sprite=%u,%u,%" str(sprite_name_chars) "s%c",
|
||||||
sprites[nsprites].name, &tombstone);
|
&sprites[nsprites].width, &sprites[nsprites].height,
|
||||||
|
sprites[nsprites].name, &tombstone);
|
||||||
|
|
||||||
if ((n == 2 || n == 3) &&
|
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;
|
size_t buf_size, tmp;
|
||||||
|
|
||||||
/* Default a name if not given. */
|
/* Default a name if not given. */
|
||||||
if (sprites[nsprites].name[0] == 0)
|
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
|
/* Allocate a buffer for the sprite and calculate the buffer
|
||||||
* size:
|
* size:
|
||||||
*/
|
*/
|
||||||
buf_size = sizeof (png_uint_16 [4]);
|
buf_size = sizeof(png_uint_16[4]);
|
||||||
buf_size *= sprites[nsprites].width;
|
buf_size *= sprites[nsprites].width;
|
||||||
buf_size *= sprites[nsprites].height;
|
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].width;
|
||||||
tmp /= sprites[nsprites].height;
|
tmp /= sprites[nsprites].height;
|
||||||
|
|
||||||
if (tmp == sizeof (png_uint_16 [4]))
|
if (tmp == sizeof(png_uint_16[4]))
|
||||||
{
|
{
|
||||||
sprites[nsprites].buffer = malloc(buf_size);
|
sprites[nsprites].buffer = malloc(buf_size);
|
||||||
/* This buffer must be initialized to transparent: */
|
/* 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;
|
sprites[nsprites].file = NULL;
|
||||||
++argv, --argc;
|
++argv, --argc;
|
||||||
|
|
||||||
if (create_sprite(sprites+nsprites++, &argc, &argv))
|
if (create_sprite(sprites + nsprites++, &argc, &argv))
|
||||||
{
|
{
|
||||||
result = 1; /* still ok */
|
result = 1; /* still ok */
|
||||||
continue;
|
continue;
|
||||||
@ -466,7 +476,8 @@ simpleover_process(png_imagep output, png_bytep out_buf, int argc,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
fprintf(stderr, "simpleover: %s: invalid sprite (%u,%u)\n",
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -480,7 +491,7 @@ simpleover_process(png_imagep output, png_bytep out_buf, int argc,
|
|||||||
|
|
||||||
else if (strncmp(argv[0], "--add=", 6) == 0)
|
else if (strncmp(argv[0], "--add=", 6) == 0)
|
||||||
{
|
{
|
||||||
const char *name = argv[0]+6;
|
const char *name = argv[0] + 6;
|
||||||
int isprite = nsprites;
|
int isprite = nsprites;
|
||||||
|
|
||||||
++argv, --argc;
|
++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 (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 */
|
goto out; /* error in add_sprite */
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -498,7 +510,8 @@ simpleover_process(png_imagep output, png_bytep out_buf, int argc,
|
|||||||
|
|
||||||
if (isprite < 0) /* sprite not found */
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -526,7 +539,8 @@ out:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, const char **argv)
|
int
|
||||||
|
main(int argc, const char **argv)
|
||||||
{
|
{
|
||||||
int result = 1; /* default to fail */
|
int result = 1; /* default to fail */
|
||||||
|
|
||||||
@ -536,7 +550,7 @@ int main(int argc, const char **argv)
|
|||||||
const char *output = NULL;
|
const char *output = NULL;
|
||||||
png_image image;
|
png_image image;
|
||||||
|
|
||||||
if (argc > 2 && argv[2][0] != '-'/*an operation*/)
|
if (argc > 2 && argv[2][0] != '-' /*an operation*/)
|
||||||
{
|
{
|
||||||
output = argv[2];
|
output = argv[2];
|
||||||
argi = 3;
|
argi = 3;
|
||||||
@ -558,7 +572,7 @@ int main(int argc, const char **argv)
|
|||||||
png_color background = {0, 0xff, 0}; /* fully saturated green */
|
png_color background = {0, 0xff, 0}; /* fully saturated green */
|
||||||
|
|
||||||
if (png_image_finish_read(&image, &background, buffer,
|
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
|
/* At this point png_image_finish_read has cleaned up the
|
||||||
* allocated data in png_image, and only the buffer needs to be
|
* 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:
|
* 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: */
|
/* Write the output: */
|
||||||
if ((output != NULL &&
|
if ((output != NULL &&
|
||||||
png_image_write_to_file(&image, output,
|
png_image_write_to_file(
|
||||||
0/*convert_to_8bit*/, buffer, 0/*row_stride*/,
|
&image, output, 0 /*convert_to_8bit*/, buffer,
|
||||||
NULL/*colormap*/)) ||
|
0 /*row_stride*/, NULL /*colormap*/)) ||
|
||||||
(output == NULL &&
|
(output == NULL &&
|
||||||
png_image_write_to_stdio(&image, stdout,
|
png_image_write_to_stdio(
|
||||||
0/*convert_to_8bit*/, buffer, 0/*row_stride*/,
|
&image, stdout, 0 /*convert_to_8bit*/, buffer,
|
||||||
NULL/*colormap*/)))
|
0 /*row_stride*/, NULL /*colormap*/)))
|
||||||
result = 0;
|
result = 0;
|
||||||
|
|
||||||
else
|
else
|
||||||
fprintf(stderr, "simpleover: write %s: %s\n",
|
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 */
|
/* else simpleover_process writes an error message */
|
||||||
@ -589,7 +605,7 @@ int main(int argc, const char **argv)
|
|||||||
|
|
||||||
else
|
else
|
||||||
fprintf(stderr, "simpleover: read %s: %s\n", argv[1],
|
fprintf(stderr, "simpleover: read %s: %s\n", argv[1],
|
||||||
image.message);
|
image.message);
|
||||||
|
|
||||||
free(buffer);
|
free(buffer);
|
||||||
}
|
}
|
||||||
@ -597,7 +613,7 @@ int main(int argc, const char **argv)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
fprintf(stderr, "simpleover: out of memory: %lu bytes\n",
|
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
|
/* 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
|
* 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
|
else
|
||||||
{
|
{
|
||||||
/* Usage message */
|
/* Usage message */
|
||||||
fprintf(stderr,
|
fprintf(
|
||||||
|
stderr,
|
||||||
"simpleover: usage: simpleover background.png [output.png]\n"
|
"simpleover: usage: simpleover background.png [output.png]\n"
|
||||||
" Output 'background.png' as a 24-bit RGB PNG file in '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"
|
" 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"
|
" --sprite=width,height,name {[--at=x,y] {sprite.png}}\n"
|
||||||
" Produce a transparent sprite of size (width,height) and with\n"
|
" Produce a transparent sprite of size (width,height) and with\n"
|
||||||
" name 'name'.\n"
|
" name 'name'.\n"
|
||||||
" For each sprite.png composite it using a Porter-Duff 'Over'\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"
|
" 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"
|
" Input PNGs will be truncated to the area of the sprite.\n"
|
||||||
"\n"
|
"\n"
|
||||||
" --add='name' {x,y}\n"
|
" --add='name' {x,y}\n"
|
||||||
" Optionally, before output, composite a sprite, 'name', which\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"
|
" offset (x,y) in the output image. Each sprite must fit\n"
|
||||||
" completely within the output image.\n"
|
" completely within the output image.\n"
|
||||||
"\n"
|
"\n"
|
||||||
@ -645,4 +662,3 @@ int main(int argc, const char **argv)
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
#endif /* SIMPLIFIED_READ */
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user