📄 pngcrush.c
字号:
*/
#define NEAR_BUF_SIZE 1024
#define MIN(a,b) (a <= b ? a : b)
void PNGAPI
png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
{
png_uint_32 check;
png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */
png_FILE_p io_ptr;
/* Check if data really is near. If so, use usual code. */
near_data = (png_byte *)CVT_PTR_NOCHECK(data);
io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr);
if ((png_bytep)near_data == data)
{
#if defined(_WIN32_WCE)
if ( !WriteFile(io_ptr, near_data, length, &check, NULL) )
check = 0;
#else
check = fwrite(near_data, 1, length, io_ptr);
#endif
}
else
{
png_byte buf[NEAR_BUF_SIZE];
png_size_t written, remaining, err;
check = 0;
remaining = length;
do
{
written = MIN(NEAR_BUF_SIZE, remaining);
png_memcpy(buf, data, written); /* copy far buffer to near buffer */
#if defined(_WIN32_WCE)
if ( !WriteFile(io_ptr, buf, written, &err, NULL) )
err = 0;
#else
err = fwrite(buf, 1, written, io_ptr);
#endif
if (err != written)
break;
else
check += err;
data += written;
remaining -= written;
}
while (remaining != 0);
}
if (check != length)
png_error(png_ptr, "Write Error");
}
#endif
#endif
#endif /* !defined(PNGCRUSH_H) */
/* cexcept interface */
static void png_cexcept_error(png_structp png_ptr, png_const_charp err_msg)
{
if (png_ptr);
#if (defined(PNGCRUSH_H))
if (!strcmp(err_msg, "Too many IDAT's found")) {
#ifndef PNG_NO_CONSOLE_IO
fprintf(stderr, "\nIn %s, correcting ", inname);
#else
png_warning(png_ptr, err_msg);
#endif
} else
#endif /* defined(PNGCRUSH_H) */
{
Throw err_msg;
}
}
/* START of code to validate memory allocation and deallocation */
#ifdef PNG_USER_MEM_SUPPORTED
/*
* Allocate memory. For reasonable files, size should never exceed
* 64K. However, zlib may allocate more then 64K if you don't tell
* it not to. See zconf.h and png.h for more information. zlib does
* need to allocate exactly 64K, so whatever you call here must
* have the ability to do that.
*
* This piece of code can be compiled to validate max 64K allocations
* by setting MAXSEG_64K in zlib zconf.h *or* PNG_MAX_MALLOC_64K.
*/
typedef struct memory_information {
png_uint_32 size;
png_voidp pointer;
struct memory_information FAR *next;
} memory_information;
typedef memory_information FAR *memory_infop;
static memory_infop pinformation = NULL;
static int current_allocation = 0;
static int maximum_allocation = 0;
png_voidp png_debug_malloc(png_structp png_ptr, png_uint_32 size)
{
/*
* png_malloc has already tested for NULL; png_create_struct calls
* png_debug_malloc directly (with png_ptr == NULL prior to libpng-1.2.0
* which is OK since we are not using a user mem_ptr)
*/
if (size == 0)
return (png_voidp) (NULL);
/*
* This calls the library allocator twice, once to get the requested
* buffer and once to get a new free list entry.
*/
{
memory_infop pinfo = (memory_infop)png_malloc_default(png_ptr,
sizeof *pinfo);
pinfo->size = size;
current_allocation += size;
if (current_allocation > maximum_allocation)
maximum_allocation = current_allocation;
pinfo->pointer = png_malloc_default(png_ptr, size);
pinfo->next = pinformation;
pinformation = pinfo;
/* Make sure the caller isn't assuming zeroed memory. */
png_memset(pinfo->pointer, 0xdd, pinfo->size);
if (verbose > 2)
fprintf(STDERR, "Pointer %lux allocated %lu bytes\n",
(unsigned long) pinfo->pointer, (unsigned long)size);
return (png_voidp) (pinfo->pointer);
}
}
/* Free a pointer. It is removed from the list at the same time. */
void png_debug_free(png_structp png_ptr, png_voidp ptr)
{
if (png_ptr == NULL)
fprintf(STDERR, "NULL pointer to png_debug_free.\n");
if (ptr == 0) {
#if 0 /* This happens all the time. */
fprintf(STDERR, "WARNING: freeing NULL pointer\n");
#endif
return;
}
/* Unlink the element from the list. */
{
memory_infop FAR *ppinfo = &pinformation;
for (;;) {
memory_infop pinfo = *ppinfo;
if (pinfo->pointer == ptr) {
*ppinfo = pinfo->next;
current_allocation -= pinfo->size;
if (current_allocation < 0)
fprintf(STDERR, "Duplicate free of memory\n");
/* We must free the list element too, but first kill
the memory that is to be freed. */
memset(ptr, 0x55, pinfo->size);
if (verbose > 2)
fprintf(STDERR, "Pointer %lux freed %lu bytes\n",
(unsigned long) ptr, (unsigned long)pinfo->size);
png_free_default(png_ptr, pinfo);
break;
}
if (pinfo->next == NULL) {
fprintf(STDERR, "Pointer %lux not found\n",
(unsigned long) ptr);
break;
}
ppinfo = &pinfo->next;
}
}
/* Finally free the data. */
png_free_default(png_ptr, ptr);
}
#endif /* PNG_USER_MEM_SUPPORTED */
/* END of code to test memory allocation/deallocation */
void png_crush_pause(void)
{
if (pauses > 0) {
char keystroke;
fprintf(STDERR, "Press [ENTER] key to continue.\n");
keystroke = (char) getc(stdin);
keystroke = keystroke; /* stifle compiler warning */
}
}
void png_skip_chunk(png_structp png_ptr)
{
png_byte buff[4];
int i;
unsigned long length;
/* read the length field */
png_default_read_data(png_ptr, buff, 4);
length=buff[3]+(buff[2]<<8)+(buff[1]<<16)+(buff[0]<<24);
/* read the chunk name */
png_default_read_data(png_ptr, buff, 4);
printf("Skipping %c%c%c%c chunk.\n",buff[0],buff[1],
buff[2],buff[3]);
/* skip the data */
for (i=0; i<length; i++)
png_default_read_data(png_ptr, buff, 1);
/* skip the CRC */
png_default_read_data(png_ptr, buff, 4);
}
#ifndef __riscos
# define setfiletype(x)
#else /* defined(__riscos) */
# include <kernel.h>
/* The riscos/acorn support was contributed by Darren Salt. */
static int fileexists(const char *name)
{
# ifdef __acorn
int ret;
return _swix(8, 3 | 1 << 31, 17, name, &ret) ? 0 : ret;
# else
_kernel_swi_regs r;
r.r[0] = 17;
r.r[1] = (int) name;
return _kernel_swi(8, &r, &r) ? 0 : r.r[0];
# endif
}
static int filesize(const char *name)
{
# ifdef __acorn
int ret;
return _swix(8, 3 | 1 << 27, 17, name, &ret) ? 0 : ret;
# else
_kernel_swi_regs r;
r.r[0] = 17;
r.r[1] = (int) name;
return _kernel_swi(8, &r, &r) ? 0 : r.r[4];
# endif
}
static int mkdir(const char *name, int ignored)
{
# ifdef __acorn
_swi(8, 0x13, 8, name, 0);
return 0;
# else
_kernel_swi_regs r;
r.r[0] = 8;
r.r[1] = (int) name;
r.r[4] = r.r[3] = r.r[2] = 0;
return (int) _kernel_swi(8 | 1 << 31, &r, &r);
# endif
}
static void setfiletype(const char *name)
{
# ifdef __acorn
_swi(8, 7, 18, name, 0xB60);
# else
_kernel_swi_regs r;
r.r[0] = 18;
r.r[1] = (int) name;
r.r[2] = 0xB60;
_kernel_swi(8 | 1 << 31, &r, &r);
# endif
}
#endif /* ?defined(__riscos) */
/*
* GRR: basically boolean; first arg is chunk name-string (e.g., "tIME" or
* "alla"); second is always full argv[] command line
* - remove_chunks is argv index of *last* -rem arg on command line
* (would be more efficient to build table at time of cmdline processing!)
* (i.e., build removal_list with names or unique IDs or whatever--skip
* excessive string-processing on every single one)
* - reprocesses command line _every_ time called, looking for -rem opts...
* - just like keep_chunk() except that latter sets things_have_changed
* variable and debug stmts say "Removed chunk" (but caller actually does
* so, by choosing not to copy chunk to new file)
* - for any given chunk name, "name" must either match exact command-line
* arg (e.g., -rem fOOb), OR it must match one of the official PNG chunk
* names explicitly listed below AND command-line arg either used all-
* lowercase form or one of "all[ab]" options
*/
int keep_unknown_chunk(png_const_charp name, char *argv[])
{
int i;
if (remove_chunks == 0)
return 1; /* no -rem options, so always keeping */
for (i = 1; i <= remove_chunks; i++) {
if (!strncmp(argv[i], "-rem", 4)) {
int allb = 0;
i++;
if (!strncmp(argv[i], "all", 3)) {
allb++; /* all but gamma, but not doing gamma here */
}
if (!strncmp(argv[i], name, 4) /* exact chunk-name match in args */
/* ...or exact match for one of known set, plus args included
* either "alla", "allb", or all-lowercase form of "name" */
|| (!strncmp(name, "cHRM", 4)
&& (!strncmp(argv[i], "chrm", 4) || allb))
|| (!strncmp(name, "dSIG", 4)
&& (!strncmp(argv[i], "dsig", 4) || allb))
|| (!strncmp(name, "gIFg", 4)
&& (!strncmp(argv[i], "gifg", 4) || allb))
|| (!strncmp(name, "gIFt", 4)
&& (!strncmp(argv[i], "gift", 4) || allb))
|| (!strncmp(name, "gIFx", 4)
&& (!strncmp(argv[i], "gifx", 4) || allb))
|| (!strncmp(name, "hIST", 4)
&& (!strncmp(argv[i], "hist", 4) || allb))
|| (!strncmp(name, "iCCP", 4)
&& (!strncmp(argv[i], "iccp", 4) || allb))
|| (!strncmp(name, "pCAL", 4)
&& (!strncmp(argv[i], "pcal", 4) || allb))
|| (!strncmp(name, "sCAL", 4)
&& (!strncmp(argv[i], "scal", 4) || allb))
|| (!strncmp(name, "sPLT", 4)
&& (!strncmp(argv[i], "splt", 4) || allb))
|| (!strncmp(name, "tIME", 4)
&& (!strncmp(argv[i], "time", 4) || allb)))
{
return 0;
}
}
}
return 1;
}
int keep_chunk(png_const_charp name, char *argv[])
{
int i;
if (verbose > 2 && first_trial)
fprintf(STDERR, " Read the %s chunk.\n", name);
if (remove_chunks == 0)
return 1;
if (verbose > 1 && first_trial)
fprintf(STDERR, " Check for removal of the %s chunk.\n", name);
for (i = 1; i <= remove_chunks; i++) {
if (!strncmp(argv[i], "-rem", 4)) {
int alla = 0;
int allb = 0;
int allt = 0;
i++;
if (!strncmp(argv[i], "all", 3)) {
allt++; /* all forms of text chunk are ancillary */
allb++; /* all ancillaries but gamma... */
if (!strncmp(argv[i], "alla", 4))
alla++; /* ...no, all ancillaries, period */
} else if (!strncmp(argv[i], "text", 4))
allt++; /* all forms of text chunk */
if (!strncmp(argv[i], name, 4) /* exact chunk-name match in args
* ...or exact match for one of known set, plus args included
* either "alla", "allb", or all-lowercase form of "name": */
|| (!strncmp(name, "PLTE", 4)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -