CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/ext/libpng17/pngtrans.c
Views: 1401
1/* pngtrans.c - transforms the data in a row (used by both readers and writers)2*3* Last changed in libpng 1.7.0 [(PENDING RELEASE)]4* Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson5* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)6* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)7*8* This code is released under the libpng license.9* For conditions of distribution and use, see the disclaimer10* and license in png.h11*/12#include "pngpriv.h"13#define PNG_SRC_FILE PNG_SRC_FILE_pngtrans1415#ifdef _XOPEN_SOURCE16# include <unistd.h>17#endif /* for swab */1819/* Memory format enquiries */20#ifdef PNG_GAMMA_SUPPORTED21static png_fixed_point22memory_gamma(png_const_structrp png_ptr)23{24# ifdef PNG_READ_GAMMA_SUPPORTED25# ifdef PNG_TRANSFORM_MECH_SUPPORTED26if (png_ptr->read_struct)27return png_ptr->row_gamma;28# endif /* TRANSFORM_MECH */29# endif /* READ_GAMMA */3031/* Else either no READ_GAMMA support or this is a write struct; in both32* cases there are no gamma transforms. In the write case the set of the33* gamma in the info may not have been copied to the png_struct.34*/35# if defined(PNG_GAMMA_SUPPORTED) && defined(PNG_READ_SUPPORTED)36if ((png_ptr->colorspace.flags &37(PNG_COLORSPACE_INVALID|PNG_COLORSPACE_HAVE_GAMMA)) ==38PNG_COLORSPACE_HAVE_GAMMA)39return png_ptr->colorspace.gamma;40# else /* !(GAMMA && READ) */41PNG_UNUSED(png_ptr)42# endif /* !(GAMMA && READ) */4344/* '0' means the value is not know: */45return 0;46}47#endif /* GAMMA */4849unsigned int PNGAPI50png_memory_format(png_structrp png_ptr)51{52/* The in-memory format as a bitmask of PNG_FORMAT_FLAG_ values. All the53* flags listed below are used. If PNG_FORMAT_FLAG_INVALID is set the54* following caveats apply to the interpretation of PNG_FORMAT_FLAG_LINEAR:55*56* The gamma may differ from the sRGB (!LINEAR) or 1.0 (LINEAR). Call57* png_memory_gamma to find the correct value.58*59* The channel depth may differ from 8 (!LINEAR) or 16 (LINEAR). Call60* png_memory_channel_depth to find the correct value.61*62* It is only valid to call these APIS *after* either png_read_update_info63* or png_start_read_image on read or after the first row of an image has64* been written on write.65*/66if (png_ptr != NULL)67{68# ifdef PNG_TRANSFORM_MECH_SUPPORTED69unsigned int format = png_ptr->row_format;70# else /* !TRANSFORM_MECH */71unsigned int format = PNG_FORMAT_FROM_COLOR_TYPE(png_ptr->color_type);72# endif /* !TRANSFORM_MECH */7374if (png_ptr->read_struct) /* else no way to find the gamma! */75{76# ifdef PNG_GAMMA_SUPPORTED77# ifdef PNG_TRANSFORM_MECH_SUPPORTED78unsigned int bit_depth = png_ptr->row_bit_depth;79# else /* !TRANSFORM_MECH */80unsigned int bit_depth = png_ptr->bit_depth;81# endif /* !TRANSFORM_MECH */8283/* Now work out whether this is a valid simplified API format. */84switch (bit_depth)85{86case 8U:87{88png_fixed_point gamma = memory_gamma(png_ptr);8990if (!PNG_GAMMA_IS_sRGB(gamma))91format |= PNG_FORMAT_FLAG_INVALID;92}93break;9495case 16:96if (memory_gamma(png_ptr) == PNG_GAMMA_LINEAR)97{98static const union99{100png_uint_16 u16;101png_byte u8[2];102} sex = { 1U };103104format |= PNG_FORMAT_FLAG_LINEAR;105106/* But the memory layout of the 16-bit quantities must also107* match; we need swapped data on LSB platforms.108*/109if (sex.u8[0] == ((format & PNG_FORMAT_FLAG_SWAPPED) != 0))110break; /* ok */111}112113/* FALL THROUGH*/114default: /* bit depth not supported for simplified API */115format |= PNG_FORMAT_FLAG_INVALID;116break;117}118# else /* !GAMMA */119/* We have no way of knowing if the gamma value matches that120* expected by the simplified API so mark the format as invalid:121*/122format |= PNG_FORMAT_FLAG_INVALID;123# endif124} /* read_struct */125126return format;127}128129return 0;130}131132unsigned int PNGAPI png_memory_channel_depth(png_structrp png_ptr)133{134/* The actual depth of each channel in the image. */135if (png_ptr != NULL)136{137# ifdef PNG_TRANSFORM_MECH_SUPPORTED138return png_ptr->row_bit_depth;139# else140return png_ptr->bit_depth;141# endif142}143144return 0;145}146147#ifdef PNG_GAMMA_SUPPORTED148png_fixed_point PNGAPI149png_memory_gamma(png_structrp png_ptr)150{151/* The actual gamma of the image data, scaled by 100,000. This is the152* encoding gamma, e.g. 1/2.2 for sRGB. If the gamma is unknown this will153* return 0.154*155* On write this invariably returns 0; libpng does not change the gamma of156* the data on write.157*158* Note that this is not always the exact inverse of the 'screen gamma'159* passed to png_set_gamma; internal optimizations remove attempts to make160* small changes to the gamma value. This function returns the actual161* output value.162*/163return (png_ptr != NULL) ? memory_gamma(png_ptr) : 0;164}165#endif /* GAMMA */166167/* These are general purpose APIs that deal with the row buffer format in both168* the read and write case. The png_struct::row_* members describe the169* in-memory format of the image data based on the transformations requested by170* the application.171*/172#ifdef PNG_TRANSFORM_MECH_SUPPORTED173png_voidp /* PRIVATE */174png_transform_cast_check(png_const_structp png_ptr, unsigned int src_line,175png_transformp tr, size_t size)176{177/* Given a pointer to a transform, 'tr' validate that the underlying derived178* class has size 'size' using the tr->size field and return the same179* pointer. If there is a size mismatch the function does an affirm using180* the given line number.181*/182if (tr->size != size)183png_affirm(png_ptr, param_deb("transform upcast") src_line);184185return tr;186}187188void /* PRIAVE */189png_transform_free(png_const_structrp png_ptr, png_transformp *list)190{191if (*list != NULL)192{193png_transform_free(png_ptr, &(*list)-> next);194if ((*list)->free != NULL)195(*list)->free(png_ptr, *list);196png_free(png_ptr, *list);197*list = NULL;198}199}200201/* Utility to initialize a png_transform_control for read or write. */202void /* PRIVATE */203png_init_transform_control(png_transform_controlp tc, png_structp png_ptr)204{205png_byte bd; /* bit depth of the row */206png_byte cd; /* bit depth of color information */207208memset(tc, 0, sizeof *tc);209tc->png_ptr = png_ptr; /* ALIAS */210tc->sp = tc->dp = NULL;211tc->width = 0;212213# ifdef PNG_READ_GAMMA_SUPPORTED214/* The file gamma is set by png_set_gamma, as well as being read from the215* input PNG gAMA chunk, if present, we don't have a png_info so can't get216* the set_gAMA value but this doesn't matter because on read the gamma217* value is in png_struct::colorspace and on write it isn't used.218*/219if ((png_ptr->colorspace.flags &220(PNG_COLORSPACE_INVALID|PNG_COLORSPACE_HAVE_GAMMA)) ==221PNG_COLORSPACE_HAVE_GAMMA)222{223tc->gamma = png_ptr->colorspace.gamma;224debug(tc->gamma > 0);225}226227else228{229/* There is no input gamma, so there should be no overall gamma230* correction going on. This test works because the various things231* that set an output gamma also default the input gamma.232*/233debug(png_ptr->row_gamma == 0);234}235# endif236237/* Validate bit depth and color type here */238cd = bd = png_ptr->bit_depth;239240switch (png_ptr->color_type)241{242case PNG_COLOR_TYPE_GRAY:243affirm(bd == 1U || bd == 2U || bd == 4U || bd == 8U || bd == 16U);244tc->format = 0U;245break;246247case PNG_COLOR_TYPE_PALETTE:248affirm(bd == 1U || bd == 2U || bd == 4U || bd == 8U);249tc->format = PNG_FORMAT_FLAG_COLORMAP | PNG_FORMAT_FLAG_COLOR;250cd = 8U;251break;252253case PNG_COLOR_TYPE_GRAY_ALPHA:254affirm(bd == 8U || bd == 16U);255tc->format = PNG_FORMAT_FLAG_ALPHA;256break;257258case PNG_COLOR_TYPE_RGB:259affirm(bd == 8U || bd == 16U);260tc->format = PNG_FORMAT_FLAG_COLOR;261break;262263case PNG_COLOR_TYPE_RGB_ALPHA:264affirm(bd == 8U || bd == 16U);265tc->format = PNG_FORMAT_FLAG_COLOR | PNG_FORMAT_FLAG_ALPHA;266break;267268default:269impossible("PNG color type");270}271272tc->bit_depth = bd;273tc->range = 0;274275/* Preset the sBIT data to full precision/handled. */276tc->sBIT_R = tc->sBIT_G = tc->sBIT_B = tc->sBIT_A = cd;277# ifdef PNG_READ_sBIT_SUPPORTED278{279int handled = 1;280281if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)282{283png_byte c = png_ptr->sig_bit.red;284if (c > 0 && c < cd)285{286tc->sBIT_R = c;287handled = 0;288}289290c = png_ptr->sig_bit.green;291if (c > 0 && c < cd)292{293tc->sBIT_G = c;294handled = 0;295}296297c = png_ptr->sig_bit.blue;298if (c > 0 && c < cd)299{300tc->sBIT_B = c;301handled = 0;302}303}304305else /* grayscale */306{307png_byte c = png_ptr->sig_bit.gray;308if (c > 0 && c < cd)309{310tc->sBIT_R = tc->sBIT_G = tc->sBIT_B = c;311handled = 0;312}313}314315/* The palette-mapped format doesn't store alpha information, an316* omission in the spec that is difficult to fix. Notice that317* 'handled' is not cleared below, this is because the alpha channel is318* always linear, so the sBIT_A value can always be treated as a319* precision value.320*/321if ((png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)322{323png_byte c = png_ptr->sig_bit.alpha;324if (c > 0 && c < cd)325tc->sBIT_A = c;326}327328/* If 'handled' did not get cleared there is no sBIT information. */329if (handled)330tc->invalid_info = PNG_INFO_sBIT;331}332# else /* !READ_sBIT */333/* No sBIT information */334tc->invalid_info = PNG_INFO_sBIT;335# endif /* !READ_sBIT */336}337338png_transformp /*PRIVATE*/339png_add_transform(png_structrp png_ptr, size_t size, png_transform_fn fn,340unsigned int order)341{342/* Add a transform. This is a minimal implementation; the order is just343* controlled by 'order', the result is a point to the new transform, or344* to an existing one if one was already in the list.345*/346png_transformp *p = &png_ptr->transform_list;347348while (*p != NULL && (*p)->order < order)349p = &(*p)->next;350351if (size == 0)352size = sizeof (png_transform);353354else355affirm(size >= sizeof (png_transform));356357if (*p == NULL || (*p)->order > order)358{359png_transformp t;360361t = png_voidcast(png_transformp, png_malloc(png_ptr, size));362memset(t, 0, size); /* zeros out the extra data too */363/* *p comes after the new entry, t: */364t->next = *p;365t->fn = fn;366t->free = NULL;367t->order = order;368t->size = 0xFFFFU & size;369*p = t;370return t;371}372373else /* (*p)->order matches order, return *p */374{375affirm((*p)->fn == fn && (*p)->order == order && (*p)->size == size);376return *p;377}378}379380png_transformp /* PRIVATE */381png_push_transform(png_structrp png_ptr, size_t size, png_transform_fn fn,382png_transformp *transform, png_transform_controlp tc)383{384png_transformp tr = *transform;385unsigned int order = tr->order;386387/* Basic loop detection: */388affirm(fn != NULL && tr->fn != fn);389390/* Move the following transforms up: */391{392unsigned int old_order = order;393394do395{396tr->order = ++old_order;397tr = tr->next;398}399while (tr != NULL && tr->order == old_order);400401affirm(tr == NULL || tr->order > old_order);402}403404*transform = png_add_transform(png_ptr, size, fn, order);405406if (tc != NULL)407fn(transform, tc);408409return *transform;410}411412#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED413static png_transformp414png_find_transform(png_const_structrp png_ptr, unsigned int order)415/* Find a transform with the given order, or return NULL. Currently only416* used here.417*/418{419png_transformp p = png_ptr->transform_list;420421for (;;)422{423if (p == NULL || p->order > order)424return NULL;425426if (p->order == order)427return p;428429p = p->next;430}431}432#endif /* USER_TRANSFORM_PTR */433434static void435remove_transform(png_const_structp png_ptr, png_transformp *transform)436/* Remove a transform on a running list */437{438png_transformp tp = *transform;439png_transformp next = tp->next;440441*transform = next;442tp->next = NULL;443png_transform_free(png_ptr, &tp);444}445446#ifdef PNG_READ_TRANSFORMS_SUPPORTED447void /* PRIVATE */448png_remove_transform(png_const_structp png_ptr, png_transformp *transform)449{450remove_transform(png_ptr, transform);451}452#endif /* READ_TRANSFORMS */453454static unsigned int455run_transform_list_forwards(png_transform_controlp tc, png_transformp *start,456png_transformp end/*NULL for whole list*/)457/* Called from the init code and below, the caller must initialize 'tc' */458{459png_const_structp png_ptr = tc->png_ptr;460unsigned int max_depth = PNG_TC_PIXEL_DEPTH(*tc);461462/* Caller guarantees that *start is non-NULL */463debug(*start != NULL);464465do466{467if ((*start)->fn != NULL)468(*start)->fn(start, tc);469470if ((*start)->fn == NULL) /* delete this transform */471remove_transform(png_ptr, start);472473else474{475/* Handle the initialization of the maximum pixel depth. */476unsigned int tc_depth = PNG_TC_PIXEL_DEPTH(*tc);477478if (tc_depth > max_depth)479max_depth = tc_depth;480481/* Advance to the next transform. */482start = &(*start)->next;483}484}485while (*start != NULL && *start != end);486487/* This only goes wrong if 'end' was non-NULL and not in the list: */488debug(*start == end);489490return max_depth;491}492493#ifdef PNG_READ_TRANSFORMS_SUPPORTED494unsigned int /* PRIVATE */495png_run_this_transform_list_forwards(png_transform_controlp tc,496png_transformp *start, png_transformp end)497{498return run_transform_list_forwards(tc, start, end);499}500#endif /* READ_TRANSFORMS */501502#ifdef PNG_READ_SUPPORTED503unsigned int /* PRIVATE */504png_run_transform_list_forwards(png_structp png_ptr, png_transform_controlp tc)505{506if (png_ptr->transform_list != NULL)507return run_transform_list_forwards(tc, &png_ptr->transform_list, NULL);508509else510return PNG_PIXEL_DEPTH(*png_ptr);511}512#endif /* READ */513514#ifdef PNG_WRITE_SUPPORTED /* only used from pngwrite.c */515static unsigned int516run_transform_list_backwards(png_transform_controlp tc, png_transformp *list)517{518png_const_structp png_ptr = tc->png_ptr;519unsigned int max_depth = 0;520521if ((*list)->next != NULL)522max_depth = run_transform_list_backwards(tc, &(*list)->next);523524/* Note that the above might change (*list)->next, but it can't change525* *list itself.526*/527if ((*list)->fn != NULL)528(*list)->fn(list, tc);529530/* If that set 'fn' to NULL this transform must be removed; this is how531* (*list)->next gets changed in our caller:532*/533if ((*list)->fn == NULL)534remove_transform(png_ptr, list);535536else537{538unsigned int depth = PNG_TC_PIXEL_DEPTH(*tc);539540if (depth > max_depth)541max_depth = depth;542}543544return max_depth;545}546547void /* PRIVATE */548png_run_transform_list_backwards(png_structp png_ptr, png_transform_controlp tc)549{550if (png_ptr->transform_list != NULL)551{552/* This doesn't take account of the base PNG depth, but that shouldn't553* matter, it's just a check:554*/555unsigned int max_depth =556run_transform_list_backwards(tc, &png_ptr->transform_list);557558/* Better late than never (if this fires a memory overwrite has happened):559*/560affirm(max_depth <= png_ptr->row_max_pixel_depth);561}562}563#endif /* WRITE */564565static unsigned int566init_transform_mech(png_structrp png_ptr, png_transform_control *tc, int start)567/* Called each time to run the transform list once during initialization. */568{569png_init_transform_control(tc, png_ptr);570tc->init = start ? PNG_TC_INIT_FORMAT : PNG_TC_INIT_FINAL;571# ifdef PNG_READ_TRANSFORMS_SUPPORTED572if (png_ptr->read_struct)573return png_read_init_transform_mech(png_ptr, tc);574else575# endif576return run_transform_list_forwards(tc, &png_ptr->transform_list, NULL);577}578#endif /* TRANSFORM_MECH */579580#ifdef PNG_PALETTE_MAX_SUPPORTED581static int582set_palette_max(png_structrp png_ptr, png_transformp tr, unsigned int max,583unsigned int format_max)584/* Called whenever a new maximum pixel value is found */585{586/* One of these must be true: */587# ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED588if (max >= (tr->args & 0x1FFU) && !png_ptr->palette_index_check_issued)589{590/* In 1.7 only issue the error/warning by default; the 'check' API is591* used to enable/disable the check. Assume that if the app enabled it592* then the app will be checking the result with get_palette_max in593* read. In write an error results unless the check is disabled.594*/595if (png_ptr->palette_index_check == PNG_PALETTE_CHECK_DEFAULT596# ifdef PNG_WRITE_SUPPORTED597|| (!png_ptr->read_struct &&598png_ptr->palette_index_check != PNG_PALETTE_CHECK_OFF)599# endif /* WRITE */600)601{602# ifdef PNG_READ_SUPPORTED603# ifdef PNG_WRITE_SUPPORTED604if (png_ptr->read_struct)605# endif /* WRITE */606png_chunk_benign_error(png_ptr, "palette index too large");607# ifdef PNG_WRITE_SUPPORTED608else609# endif610# endif /* READ */611# ifdef PNG_WRITE_SUPPORTED612png_error(png_ptr, "palette index too large");613# endif /* WRITE */614}615616png_ptr->palette_index_check_issued = 1;617}618# endif /* CHECK_FOR_INVALID_INDEX */619# ifdef PNG_GET_PALETTE_MAX_SUPPORTED620png_ptr->palette_index_max = png_check_byte(png_ptr, max);621# endif622623if (max == format_max)624{625tr->fn = NULL; /* no point continuing once the max has been seen */626return 1; /* stop */627}628629return 0; /* keep going */630}631632static void633palette_max_1bpp(png_transformp *tr, png_transform_controlp tc)634{635png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp);636png_uint_32 width = tc->width;637638while (width >= 8)639{640if (*sp++) break;641width -= 8;642}643644if (width < 8)645{646if (width == 0 ||647(*sp & (((1U<<width)-1U) << (8-width))) == 0)648return; /* no '1' pixels */649}650651/* If the code reaches this point there is a set pixel */652(void)set_palette_max(tc->png_ptr, *tr, 1U, 1U);653}654655static void656palette_max_2bpp(png_transformp *tr, png_transform_controlp tc)657{658png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp);659png_uint_32 width = tc->width;660const png_uint_32 args = (*tr)->args;661unsigned int max = args >> 24; /* saved maximum */662663while (width > 0)664{665png_uint_32 input = 0U, test;666unsigned int new_max;667668/* This just skips 0 bytes: */669while (width > 0)670{671unsigned int next = *sp++;672673/* There may be partial pixels at the end, just remove the absent674* pixels with a right shift:675*/676if (width >= 4)677width -= 4;678else679next >>= (4U-width) * 2U, width = 0;680681if (next)682{683input = (input << 8) | next;684if ((input & 0xFF000000U) != 0)685break;686}687}688689test = input & 0xAAAAAAAAU;690691if (test != 0)692{693if ((input & (test >> 1)) != 0)694new_max = 3U; /* both bits set in at least one pixel */695696else if (max < 2U)697new_max = 2U;698699else700continue; /* no change to max */701}702703else /* test is 0 */ if (input != 0 && max == 0)704new_max = 1U;705706else /* input is 0, or max is at least 1 */707continue;708709/* new_max is greater than max: */710if (set_palette_max(tc->png_ptr, *tr, new_max, 3U))711return;712713/* Record new_max: */714max = new_max;715}716717/* End of input, check the next line. */718(*tr)->args = (max << 24) + (args & 0xFFFFFFU);719}720721static void722palette_max_4bpp(png_transformp *tr, png_transform_controlp tc)723{724png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp);725png_uint_32 width = tc->width;726const png_uint_32 args = (*tr)->args;727unsigned int max = args >> 24; /* saved maximum */728729while (width > 0)730{731unsigned int input = *sp++;732733if (width >= 2)734width -= 2;735else736input >>= 1, width = 0;737738if ((input & 0xFU) > max)739max = input & 0xFU;740741if (((input >> 4) & 0xFU) > max)742max = (input >> 4) & 0xFU;743}744745if (max > (args >> 24))746{747if (set_palette_max(tc->png_ptr, *tr, max, 15U))748return;749750(*tr)->args = (max << 24) + (args & 0xFFFFFFU);751}752}753754static void755palette_max_8bpp(png_transformp *tr, png_transform_controlp tc)756{757png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp);758png_uint_32 width = tc->width;759const png_uint_32 args = (*tr)->args;760unsigned int max = args >> 24; /* saved maximum */761762while (width > 0)763{764unsigned int input = *sp++;765766if (input > max)767max = input;768769--width;770}771772if (max > (args >> 24))773{774if (set_palette_max(tc->png_ptr, *tr, max, 255U))775return;776777(*tr)->args = (max << 24) + (args & 0xFFFFFFU);778}779}780781static void782palette_max_init(png_transformp *tr, png_transform_controlp tc)783{784# define png_ptr (tc->png_ptr)785affirm((tc->format & PNG_FORMAT_FLAG_COLORMAP) != 0);786debug(tc->init);787788if (tc->init == PNG_TC_INIT_FINAL)789{790/* Record the palette depth to check here along with the running total791* in the top 8 bits (initially 0, which is always valid).792*/793(*tr)->args = png_ptr->num_palette;794795switch (tc->bit_depth)796{797case 1: (*tr)->fn = palette_max_1bpp; break;798case 2: (*tr)->fn = palette_max_2bpp; break;799case 4: (*tr)->fn = palette_max_4bpp; break;800case 8: (*tr)->fn = palette_max_8bpp; break;801default:impossible("palette bit depth");802}803804png_ptr->palette_index_have_max = 1U;805}806# undef png_ptr807}808#endif /* PALETTE_MAX */809810#ifdef PNG_GET_PALETTE_MAX_SUPPORTED811int PNGAPI812png_get_palette_max(png_const_structrp png_ptr, png_const_inforp info_ptr)813{814if (png_ptr != NULL && png_ptr->palette_index_have_max)815return png_ptr->palette_index_max;816817/* This indicates to the caller that the information is not available: */818return -1;819PNG_UNUSED(info_ptr)820}821#endif /* GET_PALETTE_MAX */822823void /* PRIVATE */824png_init_row_info(png_structrp png_ptr)825{826/* PNG pixels never exceed 64 bits in depth: */827const png_byte png_depth =828png_check_bits(png_ptr, PNG_PIXEL_DEPTH(*png_ptr), 7U);829830# ifdef PNG_TRANSFORM_MECH_SUPPORTED831/* The palette index check stuff is *on* automatically. To handle this832* add it here, if it is supported.833*/834# ifdef PNG_PALETTE_MAX_SUPPORTED835/* The logic here is a little complex because of the plethora of836* #defines controlling this stuff.837*/838if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE/* fast escape */ && (839# if defined (PNG_READ_GET_PALETTE_MAX_SUPPORTED) ||\840defined (PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED)841(png_ptr->read_struct842# ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED843&& (png_ptr->palette_index_check == PNG_PALETTE_CHECK_ON ||844(png_ptr->palette_index_check == PNG_PALETTE_CHECK_DEFAULT845&& png_ptr->num_palette < (1U << png_ptr->bit_depth)))846# endif /* READ_CHECK_FOR_INVALID_INDEX */847)848# else /* no READ support */8490850# endif /* READ checks */851||852# if defined (PNG_WRITE_GET_PALETTE_MAX_SUPPORTED) ||\853defined (PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED)854(!png_ptr->read_struct855# ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED856&& (png_ptr->palette_index_check == PNG_PALETTE_CHECK_ON ||857(png_ptr->palette_index_check == PNG_PALETTE_CHECK_DEFAULT858&& png_ptr->num_palette < (1U << png_ptr->bit_depth)))859# endif /* WRITE_CHECK_FOR_INVALID_INDEX */860)861# else /* no WRITE support */8620863# endif /* WRITE checks */864))865png_add_transform(png_ptr, 0/*size*/, palette_max_init,866PNG_TR_CHECK_PALETTE);867# endif868869/* Application transforms may change the format of the data or, when870* producing interlaced images, the number of pixels in a line. This code871* determines the maximum pixel depth required and allows transformations872* a chance to initialize themselves.873*/874if (png_ptr->transform_list != NULL)875{876png_transform_control tc;877878(void)init_transform_mech(png_ptr, &tc, 1/*start*/);879880png_ptr->row_format = png_check_bits(png_ptr, tc.format, PNG_RF_BITS);881affirm(tc.bit_depth <= 32);882png_ptr->row_bit_depth = png_check_bits(png_ptr, tc.bit_depth, 6);883png_ptr->row_range = png_check_bits(png_ptr, tc.range, 3);884# ifdef PNG_READ_GAMMA_SUPPORTED885png_ptr->row_gamma = tc.gamma;886# endif /* READ_GAMMA */887888/* The above may have cancelled all the transforms in the list. */889if (png_ptr->transform_list != NULL)890{891/* Run the transform list again, also forward, and accumulate the892* maximum pixel depth. At this point the transforms can swap893* out their initialization code.894*/895unsigned int max_depth =896init_transform_mech(png_ptr, &tc, 0/*final*/);897898/* init_transform_mech is expected to take the input depth into899* account:900*/901debug(max_depth >= png_depth);902if (max_depth < png_depth)903max_depth = png_depth;904affirm(max_depth <= (png_ptr->read_struct ? 128U : 64U));905906# ifdef PNG_READ_TRANSFORMS_SUPPORTED907/* Set this now because it only gets resolved finally at this908* point.909*/910png_ptr->invalid_info = tc.invalid_info;911# endif /* READ_TRANSFORMS */912913/* And check the transform fields: */914affirm(png_ptr->row_format == tc.format &&915png_ptr->row_range == tc.range &&916png_ptr->row_bit_depth == tc.bit_depth);917# ifdef PNG_READ_GAMMA_SUPPORTED918affirm(png_ptr->row_gamma == tc.gamma);919# endif /* READ_GAMMA */920921png_ptr->row_max_pixel_depth =922png_check_bits(png_ptr, max_depth, 8U);923924/* On 'read' input_depth is the PNG pixel depth and output_depth is925* the depth of the pixels passed to the application, but on 'write'926* the transform list is reversed so output_depth is the PNG depth927* and input_depth the application depth.928*/929{930const png_byte app_depth =931png_check_bits(png_ptr, PNG_TC_PIXEL_DEPTH(tc), 8U);932933affirm(app_depth <= max_depth);934935if (png_ptr->read_struct)936{937png_ptr->row_input_pixel_depth = png_depth;938png_ptr->row_output_pixel_depth = app_depth;939}940941else942{943png_ptr->row_input_pixel_depth = app_depth;944png_ptr->row_output_pixel_depth = png_depth;945}946947return; /* to skip the default settings below */948}949}950}951952else /* png_ptr->transform_list == NULL */953{954png_ptr->row_format = png_check_bits(png_ptr,955PNG_FORMAT_FROM_COLOR_TYPE(png_ptr->color_type), PNG_RF_BITS);956png_ptr->row_bit_depth = png_check_bits(png_ptr, png_ptr->bit_depth,9576);958png_ptr->row_range = 0;959# ifdef PNG_READ_GAMMA_SUPPORTED960if ((png_ptr->colorspace.flags &961(PNG_COLORSPACE_INVALID|PNG_COLORSPACE_HAVE_GAMMA)) ==962PNG_COLORSPACE_HAVE_GAMMA)963png_ptr->row_gamma = png_ptr->colorspace.gamma;964# endif /* READ_GAMMA */965# ifdef PNG_READ_TRANSFORMS_SUPPORTED966png_ptr->invalid_info = 0U;967# endif /* READ_TRANSFORMS */968}969# endif /* TRANSFORM_MECH */970971/* We get here if there are no transforms therefore no change to the pixel972* bit depths.973*/974png_ptr->row_output_pixel_depth = png_ptr->row_max_pixel_depth =975png_ptr->row_input_pixel_depth = png_depth;976}977978#if defined(PNG_READ_INTERLACING_SUPPORTED) || \979defined(PNG_WRITE_INTERLACING_SUPPORTED)980int PNGAPI981png_set_interlace_handling(png_structrp png_ptr)982{983png_debug(1, "in png_set_interlace handling");984985if (png_ptr != 0)986{987if (png_ptr->read_struct)988{989# ifdef PNG_READ_INTERLACING_SUPPORTED990if (png_ptr->interlaced)991{992png_ptr->do_interlace = 1;993return PNG_INTERLACE_ADAM7_PASSES;994}995996return 1;997# else /* !READ_INTERLACING */998png_app_error(png_ptr, "no de-interlace support");999/* return 0 below */1000# endif /* !READ_INTERLACING */1001}10021003else /* write */1004{1005# ifdef PNG_WRITE_INTERLACING_SUPPORTED1006if (png_ptr->interlaced)1007{1008png_ptr->do_interlace = 1;1009return PNG_INTERLACE_ADAM7_PASSES;1010}10111012return 1;1013# else /* !WRITE_INTERLACING */1014png_app_error(png_ptr, "no interlace support");1015/* return 0 below */1016# endif /* !WRITE_INTERLACING */1017}1018}10191020/* API CHANGE: 1.7.0: returns 0 if called with a NULL png_ptr */1021return 0;1022}1023#endif /* READ_INTERLACING || WRITE_INTERLACING */10241025#ifdef PNG_MNG_READ_FEATURES_SUPPORTED1026/* Undoes intrapixel differencing, this is called immediately after the PNG1027* filter has been undone.1028*/1029static void1030png_do_read_intrapixel_RGB8(png_transformp *tr, png_transform_controlp tc)1031{1032png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp);1033png_bytep dp = png_voidcast(png_bytep, tc->dp);1034png_uint_32 width = tc->width;10351036tc->sp = dp;10371038/* TAKE CARE: dp and sp may be the same, in which case the assignments to *dp1039* are overwriting sp[]1040*/1041do1042{1043*dp++ = PNG_BYTE(sp[0] + sp[1]); /* red+green */1044*dp++ = *++sp; /* green */1045*dp++ = PNG_BYTE(sp[0] + sp[1]); /* green+blue */1046sp += 2;1047}1048while (--width > 0);10491050# define png_ptr (tc->png_ptr)1051UNTESTED1052# undef png_ptr1053PNG_UNUSED(tr)1054}10551056static void1057png_do_read_intrapixel_RGBA8(png_transformp *tr, png_transform_controlp tc)1058{1059png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp);1060png_bytep dp = png_voidcast(png_bytep, tc->dp);1061png_uint_32 width = tc->width;10621063tc->sp = dp;10641065do1066{1067*dp++ = PNG_BYTE(sp[0] + sp[1]); /* red+green */1068*dp++ = *++sp; /* green */1069*dp++ = PNG_BYTE(sp[0] + sp[1]); /* green+blue */1070sp += 2;1071*dp++ = *sp++; /* alpha */1072}1073while (--width > 0);10741075# define png_ptr (tc->png_ptr)1076UNTESTED1077# undef png_ptr1078PNG_UNUSED(tr)1079}10801081static void1082png_do_read_intrapixel_RGB16(png_transformp *tr, png_transform_controlp tc)1083{1084png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp);1085png_bytep dp = png_voidcast(png_bytep, tc->dp);1086png_uint_32 width = tc->width;10871088tc->sp = dp;10891090/* The input consists of 16-bit values and, by examination of the code1091* (please, someone, check; I didn't read the spec) the differencing is done1092* against the 16-bit green value.1093*/1094do1095{1096unsigned int red = png_get_uint_16(sp + 0);1097unsigned int green = png_get_uint_16(sp + 2);1098unsigned int blue = png_get_uint_16(sp + 4);1099sp += 6;11001101red += green;1102blue += green;11031104*dp++ = PNG_BYTE(red >> 8);1105*dp++ = PNG_BYTE(red);1106*dp++ = PNG_BYTE(green >> 8);1107*dp++ = PNG_BYTE(green);1108*dp++ = PNG_BYTE(blue >> 8);1109*dp++ = PNG_BYTE(blue);1110}1111while (--width > 0);11121113# define png_ptr (tc->png_ptr)1114UNTESTED1115# undef png_ptr1116PNG_UNUSED(tr)1117}11181119static void1120png_do_read_intrapixel_RGBA16(png_transformp *tr, png_transform_controlp tc)1121{1122png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp);1123png_bytep dp = png_voidcast(png_bytep, tc->dp);1124png_uint_32 width = tc->width;11251126tc->sp = dp;11271128/* As above but copy the alpha over too. */1129do1130{1131unsigned int red = png_get_uint_16(sp + 0);1132unsigned int green = png_get_uint_16(sp + 2);1133unsigned int blue = png_get_uint_16(sp + 4);1134sp += 6;11351136red += green;1137blue += green;11381139*dp++ = PNG_BYTE(red >> 8);1140*dp++ = PNG_BYTE(red);1141*dp++ = PNG_BYTE(green >> 8);1142*dp++ = PNG_BYTE(green);1143*dp++ = PNG_BYTE(blue >> 8);1144*dp++ = PNG_BYTE(blue);1145*dp++ = *sp++;1146*dp++ = *sp++; /* alpha */1147}1148while (--width > 0);11491150# define png_ptr (tc->png_ptr)1151UNTESTED1152# undef png_ptr1153PNG_UNUSED(tr)1154}11551156static void1157png_init_read_intrapixel(png_transformp *tr, png_transform_controlp tc)1158{1159/* Double check the permitted MNG features in case the app turned the feature1160* on then off again. Also make sure the color type is acceptable; it must1161* be RGB or RGBA.1162*/1163png_const_structp png_ptr = tc->png_ptr;11641165if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&1166(png_ptr->filter_method == PNG_INTRAPIXEL_DIFFERENCING) &&1167(tc->format & (PNG_FORMAT_FLAG_COLOR+PNG_FORMAT_FLAG_COLORMAP)) ==1168PNG_FORMAT_FLAG_COLOR)1169{1170if (tc->init == PNG_TC_INIT_FINAL) switch (PNG_TC_PIXEL_DEPTH(*tc))1171{1172case 24: (*tr)->fn = png_do_read_intrapixel_RGB8; break;1173case 32: (*tr)->fn = png_do_read_intrapixel_RGBA8; break;1174case 48: (*tr)->fn = png_do_read_intrapixel_RGB16; break;1175case 64: (*tr)->fn = png_do_read_intrapixel_RGBA16; break;1176default: impossible("bit depth");1177}1178}11791180else1181(*tr)->fn = NULL;1182}1183#endif /* MNG_READ_FEATURES_SUPPORTED */11841185#ifdef PNG_MNG_WRITE_FEATURES_SUPPORTED1186/* This is just the forward direction of the above:1187*1188* red := red - green1189* blue:= blue- green1190*1191* Alpha is not changed.1192*/1193static void1194png_do_write_intrapixel_RGB8(png_transformp *tr, png_transform_controlp tc)1195{1196png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp);1197png_bytep dp = png_voidcast(png_bytep, tc->dp);1198png_uint_32 width = tc->width;11991200tc->sp = dp;12011202/* TAKE CARE: dp and sp may be the same, in which case the assignments to *dp1203* are overwriting sp[]1204*/1205do1206{1207*dp++ = PNG_BYTE(sp[0] - sp[1]); /* red-green */1208*dp++ = *++sp; /* green */1209*dp++ = PNG_BYTE(sp[0] - sp[1]); /* green-blue */1210sp += 2;1211}1212while (--width > 0);12131214# define png_ptr (tc->png_ptr)1215UNTESTED1216# undef png_ptr1217PNG_UNUSED(tr)1218}12191220static void1221png_do_write_intrapixel_RGBA8(png_transformp *tr, png_transform_controlp tc)1222{1223png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp);1224png_bytep dp = png_voidcast(png_bytep, tc->dp);1225png_uint_32 width = tc->width;12261227tc->sp = dp;12281229do1230{1231*dp++ = PNG_BYTE(sp[0] - sp[1]); /* red-green */1232*dp++ = *++sp; /* green */1233*dp++ = PNG_BYTE(sp[0] - sp[1]); /* green-blue */1234sp += 2;1235*dp++ = *sp++; /* alpha */1236}1237while (--width > 0);12381239# define png_ptr (tc->png_ptr)1240UNTESTED1241# undef png_ptr1242PNG_UNUSED(tr)1243}12441245static void1246png_do_write_intrapixel_RGB16(png_transformp *tr, png_transform_controlp tc)1247{1248png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp);1249png_bytep dp = png_voidcast(png_bytep, tc->dp);1250png_uint_32 width = tc->width;12511252tc->sp = dp;12531254do1255{1256unsigned int red = png_get_uint_16(sp + 0);1257unsigned int green = png_get_uint_16(sp + 2);1258unsigned int blue = png_get_uint_16(sp + 4);1259sp += 6;12601261red -= green;1262blue -= green;12631264*dp++ = PNG_BYTE(red >> 8);1265*dp++ = PNG_BYTE(red);1266*dp++ = PNG_BYTE(green >> 8);1267*dp++ = PNG_BYTE(green);1268*dp++ = PNG_BYTE(blue >> 8);1269*dp++ = PNG_BYTE(blue);1270}1271while (--width > 0);12721273# define png_ptr (tc->png_ptr)1274UNTESTED1275# undef png_ptr1276PNG_UNUSED(tr)1277}12781279static void1280png_do_write_intrapixel_RGBA16(png_transformp *tr, png_transform_controlp tc)1281{1282png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp);1283png_bytep dp = png_voidcast(png_bytep, tc->dp);1284png_uint_32 width = tc->width;12851286tc->sp = dp;12871288/* As above but copy the alpha over too. */1289do1290{1291unsigned int red = png_get_uint_16(sp + 0);1292unsigned int green = png_get_uint_16(sp + 2);1293unsigned int blue = png_get_uint_16(sp + 4);1294sp += 6;12951296red -= green;1297blue -= green;12981299*dp++ = PNG_BYTE(red >> 8);1300*dp++ = PNG_BYTE(red);1301*dp++ = PNG_BYTE(green >> 8);1302*dp++ = PNG_BYTE(green);1303*dp++ = PNG_BYTE(blue >> 8);1304*dp++ = PNG_BYTE(blue);1305*dp++ = *sp++;1306*dp++ = *sp++; /* alpha */1307}1308while (--width > 0);13091310# define png_ptr (tc->png_ptr)1311UNTESTED1312# undef png_ptr1313PNG_UNUSED(tr)1314}13151316static void1317png_init_write_intrapixel(png_transformp *tr, png_transform_controlp tc)1318{1319/* Write filter_method 64 (intrapixel differencing) only if:1320*1321* 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED, and;1322* 2. Libpng did not write a PNG signature (this filter_method is only1323* used in PNG datastreams that are embedded in MNG datastreams),1324* and;1325* 3. The application called png_permit_mng_features with a mask that1326* included PNG_FLAG_MNG_FILTER_64, and;1327* 4. The filter_method is 64, and;1328* 5. The color_type is RGB or RGBA1329*/1330png_const_structp png_ptr = tc->png_ptr;13311332if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&1333(png_ptr->filter_method == PNG_INTRAPIXEL_DIFFERENCING) &&1334(tc->format & (PNG_FORMAT_FLAG_COLOR+PNG_FORMAT_FLAG_COLORMAP)) ==1335PNG_FORMAT_FLAG_COLOR)1336{1337if (tc->init == PNG_TC_INIT_FINAL) switch (PNG_TC_PIXEL_DEPTH(*tc))1338{1339case 24: (*tr)->fn = png_do_write_intrapixel_RGB8; break;1340case 32: (*tr)->fn = png_do_write_intrapixel_RGBA8; break;1341case 48: (*tr)->fn = png_do_write_intrapixel_RGB16; break;1342case 64: (*tr)->fn = png_do_write_intrapixel_RGBA16; break;1343default: impossible("bit depth");1344}1345}13461347else1348(*tr)->fn = NULL;1349}1350#endif /* MNG_WRITE_FEATURES */13511352#ifdef PNG_MNG_FEATURES_SUPPORTED1353png_uint_32 PNGAPI1354png_permit_mng_features(png_structrp png_ptr, png_uint_32 mng_features)1355{1356if (png_ptr != NULL)1357{1358# ifdef PNG_MNG_READ_FEATURES_SUPPORTED1359if ((mng_features & PNG_FLAG_MNG_FILTER_64) != 0)1360png_add_transform(png_ptr, 0/*size*/, png_init_read_intrapixel,1361PNG_TR_MNG_INTRAPIXEL);1362# else /* !MNG_READ_FEATURES */1363if (png_ptr->read_struct)1364{1365png_app_error(png_ptr, "MNG not supported on read");1366return;1367}1368# endif /* !MNG_READ_FEATURES */13691370# ifdef PNG_MNG_WRITE_FEATURES_SUPPORTED1371if ((mng_features & PNG_FLAG_MNG_FILTER_64) != 0)1372png_add_transform(png_ptr, 0/*size*/, png_init_write_intrapixel,1373PNG_TR_MNG_INTRAPIXEL);1374# else /* !MNG_WRITE_FEATURES */1375if (!png_ptr->read_struct)1376{1377png_app_error(png_ptr, "MNG not supported on write");1378return;1379}1380# endif /* !MNG_WRITE_FEATURES */13811382return png_ptr->mng_features_permitted =1383mng_features & PNG_ALL_MNG_FEATURES;1384}13851386return 0;1387}1388#endif /* MNG_FEATURES */13891390#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) ||\1391defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) ||\1392defined(PNG_READ_SWAP_ALPHA_SUPPORTED) ||\1393defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) ||\1394defined(PNG_READ_FILLER_SUPPORTED) ||\1395defined(PNG_WRITE_FILLER_SUPPORTED) ||\1396defined(PNG_READ_STRIP_ALPHA_SUPPORTED) ||\1397defined(PNG_READ_STRIP_16_TO_8_SUPPORTED) ||\1398defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) ||\1399defined(PNG_READ_EXPAND_16_SUPPORTED) ||\1400defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)1401/* This is a generic transform which manipulates the bytes in an input row. The1402* manipulations supported are:1403*1404* Channel addition (alpha or filler)1405* Channel removal (alpha or filler)1406* Channel swaps - RGB to BGR, alpha/filler from last to first and vice versa1407*1408* The output is described in blocks of output pixel size 4-bit codes encoded1409* as follows:1410*1411* 0 Advance the source pointer by the source pixel size, start the1412* code list again. This code doesn't actually exist; it is simply1413* the result of emptying the code list.1414* 1..3 An error (ignored; treated like 0)1415* 4..7 Put filler[code-4] into the output1416* 8..15 Put source byte[code-8] in the output1417*1418* The codes are held in a png_uint_32 parameter. transform->args is used by1419* the init routine to work out the required codes. The format change is a mask1420* which is XORed with the tc format. Note that the init routine works out1421* whether to work from the beginning or end of the row and the codes are always1422* stored LSB first in the order needed.1423*/1424typedef struct1425{1426png_transform tr;1427png_uint_32 codes; /* As above */1428unsigned int format; /* format after transform */1429unsigned int bit_depth; /* bit depth after transform */1430png_byte filler[4]; /* Filler or alpha bytes, LSB first (see below) */1431} png_transform_byte_op;14321433static void1434png_do_byte_ops_up(png_transformp *transform, png_transform_controlp tc)1435/* Row width is unchanged or decreasing */1436{1437# define png_ptr (tc->png_ptr)1438png_transform_byte_op *tr =1439png_transform_cast(png_transform_byte_op, *transform);1440png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp);1441const unsigned int sp_advance = PNG_TC_PIXEL_DEPTH(*tc) >> 3;1442const png_const_bytep ep = sp + PNG_TC_ROWBYTES(*tc);1443png_bytep dp = png_voidcast(png_bytep, tc->dp);14441445debug(tc->bit_depth == 8 || tc->bit_depth == 16);1446debug((tc->format & PNG_FORMAT_FLAG_COLORMAP) == 0);14471448tc->sp = tc->dp;1449tc->format = tr->format;1450tc->bit_depth = tr->bit_depth;14511452/* 'output' is a 32-byte buffer that is used to delay writes for 16 bytes,1453* avoiding overwrite when source and destination buffers are the same.1454* 'hwm' is either 32 or 16, initially '32', when the byte counter 'i'1455* reaches 'hwm' the last-but-one 16 bytes are written; the bytes1456* [hwm..hwm+15] modulo 32. hwm is then swapped to hwm+16 mod 32 and i1457* continues to advance. i is always below hwm.1458*1459* At the end the whole remaining buffer from hwm to i is written.1460*/1461{1462const png_uint_32 codes = tr->codes;1463png_uint_32 code = codes;1464unsigned int i, hwm; /* buffer index and high-water-mark */1465png_byte output[32];14661467hwm = 32;14681469for (i=0;;)1470{1471unsigned int next_code = code & 0xf;14721473if (next_code >= 8)1474output[i++] = sp[next_code-8];14751476else if (next_code >= 4)1477output[i++] = tr->filler[next_code - 4];14781479else /* end code */1480{1481sp += sp_advance;14821483if (sp >= ep)1484break; /* i may be == hwm at this point. */14851486code = codes;1487continue; /* no ouput produced, skip the check */1488}14891490code >>= 4; /* find the next code */14911492if (i == hwm)1493{1494hwm &= 0x10U; /* 0 or 16 */1495memcpy(dp, output + hwm, 16);1496dp += 16;1497i = hwm; /* reset i if hwm was 32 */1498/* hwm is only ever 16 or 32: */1499hwm += 16;1500}1501}15021503/* Write from hwm to (i-1), the delay means there is always something to1504* write.1505*/1506hwm &= 0x10U;1507if (hwm == 16)1508{1509debug(i <= 16);1510memcpy(dp, output + hwm, 16);1511dp += 16;1512}15131514if (i > 0)1515memcpy(dp, output, i);15161517# ifndef PNG_RELEASE_BUILD1518dp += i;1519/* The macro expansion exceeded the limit on ANSI strings, so split it:1520*/1521dp -= PNG_TC_ROWBYTES(*tc);1522debug(dp == tc->dp);1523# endif1524}15251526debug(sp == ep);1527# undef png_ptr1528}15291530#ifdef PNG_READ_TRANSFORMS_SUPPORTED1531static void1532png_do_byte_ops_down(png_transformp *transform, png_transform_controlp tc)1533/* Row width is increasing */1534{1535# define png_ptr (tc->png_ptr)1536png_transform_byte_op *tr =1537png_transform_cast(png_transform_byte_op, *transform);1538const png_const_bytep ep = png_voidcast(png_const_bytep, tc->sp);1539const unsigned int sp_advance = PNG_TC_PIXEL_DEPTH(*tc) >> 3;1540png_const_bytep sp = ep + PNG_TC_ROWBYTES(*tc);1541png_bytep dp = png_voidcast(png_bytep, tc->dp);1542png_alloc_size_t dest_rowbytes;15431544debug(tc->bit_depth == 8U || tc->bit_depth == 16U);1545debug((tc->format & PNG_FORMAT_FLAG_COLORMAP) == 0U);15461547tc->sp = tc->dp;1548tc->format = tr->format;1549tc->bit_depth = tr->bit_depth;1550dest_rowbytes = PNG_TC_ROWBYTES(*tc);1551dp += dest_rowbytes;15521553/* In this case the 32-byte buffer is written downwards with a writes delayed1554* by 16 bytes as before. 'hwm' is lower than i; 0 or 16.1555*/1556{1557const png_uint_32 codes = tr->codes;1558png_uint_32 code = codes;1559unsigned int size, hwm, i;1560png_byte output[32] = { 0 };15611562/* This catches an empty codes array, which would cause all the input to1563* be skipped and, potentially, a garbage output[] to be written (once) to1564* *dp.1565*/1566affirm((codes & 0xFU) >= 4U);15671568/* Align the writes to a 16-byte multiple from the start of the1569* destination buffer:1570*/1571size = dest_rowbytes & 0xFU;1572if (size == 0U) size = 16U;1573i = size+16U;1574sp -= sp_advance; /* Move 1 pixel back */1575hwm = 0U;15761577for (;;)1578{1579unsigned int next_code = code & 0xFU;15801581if (next_code >= 8U)1582output[--i] = sp[next_code-8U];15831584else if (next_code >= 4U)1585output[--i] = tr->filler[next_code - 4U];15861587else /* end code */1588{1589sp -= sp_advance;15901591if (sp < ep)1592break;15931594code = codes;1595continue; /* no ouput produced, skip the check */1596}15971598code >>= 4; /* find the next code */15991600if (i == hwm)1601{1602/* A partial copy comes at the beginning to align the copies to a1603* 16-byte boundary. The bytes to be written are the bytes1604* i+16..(hwm-1) except that the partial buffer may reduce this.1605*/1606dp -= size;1607hwm ^= 0x10U; /* == i+16 mod 32 */1608memcpy(dp, output + hwm, size);1609size = 16U;1610if (i == 0U) i = 32U;1611}1612}16131614/* The loop above only exits with an exit code, so 'i' has been checked1615* against 'hwm' before and, because of the alignment, i will always be1616* either 16 or 32:1617*/1618debug((i == 16U || i == 32U) & (((i & 0x10U)^0x10U) == hwm));1619debug(sp+sp_advance == ep);16201621/* At the end the bytes i..(hwm-1) need to be written, with the proviso1622* that 'size' will be less than 16 for short rows. If 'size' is still a1623* short value then the range to be written is output[i..16+(size-1)],1624* otherwise (size == 16) either this is the first write and a full 321625* bytes will be written (hwm == 0, i == 32) or 16 bytes need to be1626* written.1627*/1628if (size < 16U)1629{1630debug(i == 16U);1631dp -= size;1632memcpy(dp, output + i, size);1633}16341635else /* size == 16 */1636{1637debug(size == 16U);16381639/* Write i..(hwm-1); 16 or 32 bytes, however if 32 bytes are written1640* they are contiguous and i==0.1641*1642* hwm is 0 or 16, i is 16 or 32, swap 0 and 32:1643*/1644if (hwm == 0U) hwm = 32U;1645if (i == 32U) i = 0U;1646affirm(i < hwm);1647debug(hwm == i+16U || (i == 0U && hwm == 32U));16481649hwm -= i;1650dp -= hwm;1651memcpy(dp, output+i, hwm);1652}1653}16541655debug(dp == png_upcast(png_bytep, tc->dp));16561657# undef png_ptr1658}1659#endif /* READ_TRANSFORMS */16601661/* 16 bit byte swapping */1662static void1663png_do_bswap(png_transformp *transform, png_transform_controlp tc)1664{1665# define png_ptr (tc->png_ptr)1666png_transform_byte_op *tr =1667png_transform_cast(png_transform_byte_op, *transform);1668png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp);1669png_bytep dp = png_voidcast(png_bytep, tc->dp);1670const png_alloc_size_t rowbytes = PNG_TC_ROWBYTES(*tc);16711672tc->format = tr->format;1673tc->bit_depth = tr->bit_depth;1674tc->sp = dp;16751676# ifdef _XOPEN_SOURCE1677/* byte swapping often has incredibly fast implementations because of the1678* importance in handling ethernet traffic. X/Open defines swab() for1679* this purpose and it is widely supported and normally incredibly fast:1680*/1681debug((rowbytes & 1) == 0);1682swab(sp, dp, rowbytes);1683# else /* !_XOPEN_SOURCE */1684{1685const png_const_bytep ep = sp + rowbytes - 1;16861687while (sp < ep)1688{1689png_byte b0 = *sp++;1690*dp++ = *sp++;1691*dp++ = b0;1692}16931694debug(sp == ep+1); /* even number of bytes */1695}1696# endif16971698PNG_UNUSED(transform)1699# undef png_ptr1700}17011702/* The following flags, store in tr->args, are set by the relevant PNGAPI1703* png_set calls then resolved below.1704*/1705#define PNG_BO_STRIP_ALPHA 0x0001U /* Remove an alpha channel (read only) */1706#define PNG_BO_CHOP_16_TO_8 0x0002U /* Chop 16-bit to 8-bit channels */1707#define PNG_BO_GRAY_TO_RGB 0x0004U /* G <-> RGB; replicate channels */1708/* QUANTIZE happens here */1709#define PNG_BO_EXPAND_16 0x0008U /* Expand 8-bit channels to 16-bit */1710#define PNG_BO_BGR 0x0010U /* RGB <-> BGR */1711#define PNG_BO_FILLER 0x0020U /* Add a filler/alpha */1712#define PNG_BO_SWAP_ALPHA 0x0040U /* xA <-> Ax; alpha swap */1713#define PNG_BO_SWAP_16 0x0080U /* 16-bit channel byte swapping */17141715/* The following are additional flags to qualify the transforms: */1716#define PNG_BO_FILLER_ALPHA 0x4000U /* The filler is an alpha value */1717#define PNG_BO_FILLER_FIRST 0x8000U /* The filler comes first */17181719static void1720png_init_byte_ops(png_transformp *transform, png_transform_controlp tc)1721{1722/* In the absence of png_set_quantize none of the above operations apply to a1723* palette row except indirectly; they may apply if the palette was expanded,1724* but this happens earlier in the pipeline.1725*1726* In the presence of png_set_quantize the rules are considerably more1727* complex. In libpng 1.6.0 the following operations occur before1728* png_do_quantize:1729*1730* PNG_BO_GRAY_TO_RGB (png_do_gray_to_rgb, but only sometimes)1731* PNG_BO_STRIP_ALPHA (png_do_strip_channel; removes alpha)1732* encode_alpha1733* scale_16_to_81734* PNG_BO_CHOP_16_TO_8 (png_do_chop)1735*1736* The following occur afterward:1737*1738* PNG_BO_EXPAND_16 (png_do_expand_16)1739* PNG_BO_GRAY_TO_RGB (png_do_gray_to_rgb, normally)1740* PNG_BO_BGR (png_do_bgr)1741* PNG_BO_FILLER (png_do_read_filler)1742* PNG_BO_SWAP_ALPHA (png_do_read_swap_alpha)1743* PNG_BO_SWAP_16 (png_do_swap; 16-bit byte swap)1744*1745* The gray to RGB operation needs to occur early for GA or gray+tRNS images1746* where the pixels are being composed on a non-gray value. For the moment1747* we assume that if this is necessary the following 'init' code will see RGB1748* at this point.1749*1750* The quantize operation operates only if:1751*1752* 1) tc->bit_depth is 81753* 2) The color type exactly matches that required by the parameters to1754* png_set_quantize; it can be RGB, RGBA or palette, but1755* png_set_quantize (not the init routine) determines this.1756*1757* To avoid needing to know this here the two stage initialization is used1758* with two transforms, one pre-quantization the other post. In the first1759* stage the correct row format and depth is set up. In the second stage the1760* pre-quantization transform looks for a post-quantization transform1761* immediately following and, if it exists, transfers its flags to that.1762*/1763png_structp png_ptr = tc->png_ptr;1764png_transform_byte_op *tr =1765png_transform_cast(png_transform_byte_op, *transform);1766png_uint_32 args = tr->tr.args;1767const unsigned int png_format = tc->format;1768unsigned int format = png_format; /* memory format */1769const unsigned int png_bit_depth = tc->bit_depth;1770unsigned int bit_depth = png_bit_depth; /* memory bit depth */17711772debug(tc->init);17731774/* Channel swaps do not occur on COLORMAP format data at present because the1775* COLORMAP is limited to 1 byte per pixel (so there is nothing to1776* manipulate). Likewise for low bit depth gray, however the code below may1777* widen 8-bit gray to RGB.1778*/1779if ((png_format & PNG_FORMAT_FLAG_COLORMAP) != 0U || png_bit_depth < 8U)1780{1781tr->tr.fn = NULL;1782return;1783}17841785/* This will normally happen in TC_INIT_FORMAT, but if there is a1786* png_do_quantize operation which doesn't apply (this is unlikely) it will1787* happen in TC_INIT_FINAL.1788*/1789if (tr->tr.next != NULL && tr->tr.next->order == PNG_TR_CHANNEL_POSTQ)1790{1791debug(tr->tr.order == PNG_TR_CHANNEL_PREQ);17921793/* So we can merge this transform into the next one, note that because the1794* PNG_BO_FILLER operation is POSTQ we don't need to copy anything other1795* than the flags.1796*/1797debug((args & tr->tr.next->args) == 0U);1798tr->tr.next->args |= args;1799tr->tr.fn = NULL;1800return;1801}18021803/* Else compact the flags for this transform - this is done in both1804* TC_INIT_FORMAT and TC_INIT_FINAL because it is safer that way; the copy1805* above shouldn't actually affect the results but might result in TO8 and1806* TO16 cancelling each other because they are in separate transforms before1807* the merge above.1808*1809* QUIET API CHANGE:1810* For compatiblity with earlier versions of libpng these tests need to1811* occur in the same order as the earlier transforms; 'TO8' combined with1812* 'TO16' did actually do something to 16-bit data, however now it just1813* preserves the original bit depth.1814*/1815if ((args & PNG_BO_STRIP_ALPHA) != 0U)1816{1817if ((format & PNG_FORMAT_FLAG_ALPHA) != 0U)1818format &= PNG_BIC_MASK(PNG_FORMAT_FLAG_ALPHA);18191820else1821args &= PNG_BIC_MASK(PNG_BO_STRIP_ALPHA);1822}18231824if ((args & PNG_BO_CHOP_16_TO_8) != 0U)1825{1826/* This is the quiet API CHANGE; in fact it isn't necessary, but it1827* seems likely that requesting both operations is a mistake:1828*/1829if ((args & PNG_BO_EXPAND_16) != 0U)1830args &= PNG_BIC_MASK(PNG_BO_CHOP_16_TO_8|PNG_BO_EXPAND_16);18311832else if (bit_depth == 16U)1833{1834bit_depth = 8U;18351836/* This also makes the tRNS chunk unusable: */1837tc->invalid_info |= PNG_INFO_tRNS+PNG_INFO_hIST+PNG_INFO_pCAL;1838/* These need further processing: PNG_INFO_sBIT, PNG_INFO_bKGD */1839}18401841else1842args &= PNG_BIC_MASK(PNG_BO_CHOP_16_TO_8);1843}18441845/* QUANTIZE happens here */18461847if ((args & PNG_BO_EXPAND_16) != 0U)1848{1849/* This only does the 8 to 16-bit part of the expansion by multiply by1850* 65535/255 (257) using byte replication. The cases of low bit depth1851* gray being expanded to 16-bit have to be handled separately.1852*/1853if (bit_depth == 8U)1854bit_depth = 16U;18551856else1857args &= PNG_BIC_MASK(PNG_BO_EXPAND_16);1858}18591860if ((args & PNG_BO_GRAY_TO_RGB) != 0U)1861{1862if ((format & PNG_FORMAT_FLAG_COLOR) == 0U)1863format |= PNG_FORMAT_FLAG_COLOR;18641865else1866args &= PNG_BIC_MASK(PNG_BO_GRAY_TO_RGB);1867}18681869if ((args & PNG_BO_BGR) != 0U)1870{1871/* This does not happen on colormaps: */1872if ((format & PNG_FORMAT_FLAG_COLOR) != 0U && !tc->palette)1873format |= PNG_FORMAT_FLAG_BGR;18741875else1876args &= PNG_BIC_MASK(PNG_BO_BGR);1877}18781879if ((args & PNG_BO_FILLER) != 0U)1880{1881if ((format & PNG_FORMAT_FLAG_ALPHA) == 0U)1882{1883format |= PNG_FORMAT_FLAG_ALPHA;1884tc->channel_add = 1U;1885/* And SWAP_ALPHA did not occur, because prior to 1.7.0 the filler op1886* did not set ALPHA in the color type, so use SWAP_ALPHA to handle the1887* before/after filler location.1888*1889* NOTE: this occurs twice, once in TC_START and once in TC_FINAL, but1890* that is ok, the operations are idempotent.1891*1892* For colormaps (tc->palette set) the filler will just end up setting1893* all the tRNS entries and PNG_BO_SWAP_ALPHA will be cancelled below.1894*/1895if ((args & PNG_BO_FILLER_FIRST) != 0U)1896args |= PNG_BO_SWAP_ALPHA;18971898else1899args &= PNG_BIC_MASK(PNG_BO_SWAP_ALPHA);19001901if (!(args & PNG_BO_FILLER_ALPHA)) /* filler is not alpha */1902format |= PNG_FORMAT_FLAG_AFILLER;1903}19041905else1906args &= PNG_BIC_MASK(PNG_BO_FILLER);1907}19081909if ((args & PNG_BO_SWAP_ALPHA) != 0U)1910{1911/* This does not happen on color maps: */1912if ((format & PNG_FORMAT_FLAG_ALPHA) != 0U && !tc->palette)1913format |= PNG_FORMAT_FLAG_AFIRST;19141915else1916args &= PNG_BIC_MASK(PNG_BO_SWAP_ALPHA);1917}19181919if ((args & PNG_BO_SWAP_16) != 0U)1920{1921if (bit_depth == 16U)1922format |= PNG_FORMAT_FLAG_SWAPPED;19231924else1925args &= PNG_BIC_MASK(PNG_BO_SWAP_16);1926}19271928if (args != 0U)1929{1930/* At the end (TC_INIT_FINAL) work out the mapping array using the codes1931* defined above and store the format and bit depth changes (as changes,1932* so they will work either forward or backward). The filler array must1933* be set up by the png_set API.1934*/1935if (tc->init == PNG_TC_INIT_FINAL)1936{1937const unsigned int png_pixel_size = PNG_TC_PIXEL_DEPTH(*tc) >> 3;19381939tc->format = format;1940tc->bit_depth = bit_depth;19411942{1943const unsigned int memory_pixel_size = PNG_TC_PIXEL_DEPTH(*tc) >> 3;1944unsigned int code_size, src_size;1945int go_down;1946png_byte codes[8];19471948/* The codes array maps the PNG format into the memory format1949* assuming the mapping works upwards in the address space.1950* Initially ignore the bit depth and just work on the first four1951* bytes.1952*/1953codes[0] = 8U;1954codes[1] = 9U;1955codes[2] = 10U;1956codes[3] = 11U;1957codes[7] = codes[6] = codes[5] = codes[4] = 0U/*error*/;19581959/* PNG_BO_STRIP_ALPHA: handled by memory_pixel_size */1960/* PNG_BO_CHOP_16_TO_8: handled below */1961/* PNG_BO_EXPAND_16: handled below */19621963if ((args & PNG_BO_GRAY_TO_RGB) != 0U)1964{1965codes[3] = 9U; /* alpha, if present */1966codes[2] = codes[1] = 8U;19671968# ifdef PNG_READ_tRNS_SUPPORTED1969/* Gray to RGB, so copy the tRNS G value into r,g,b: */1970if (png_ptr->num_trans == 1U)1971png_ptr->trans_color.blue =1972png_ptr->trans_color.green =1973png_ptr->trans_color.red =1974png_ptr->trans_color.gray;1975# endif /* READ_tRNS */1976}19771978/* 'BGR' and gray-to-RGB are mutually exclusive; with gray-to-RGB1979* codes[0] == codes[2] == 81980*/1981else if ((args & PNG_BO_BGR) != 0U)1982{1983codes[0] = 10U;1984codes[2] = 8U;1985}19861987if ((args & PNG_BO_FILLER) != 0U)1988{1989/* The filler alway goes after; for a 'before' filler the code1990* above turns on SWAP_ALPHA too. The gray-to-RGB transform has1991* happened already, so the location of the filler channel is1992* given by 'format':1993*/1994if ((format & PNG_FORMAT_FLAG_COLOR) != 0U)1995codes[3] = 4U; /* low byte of filler */19961997else1998codes[1] = 4U;1999}20002001if ((args & PNG_BO_SWAP_ALPHA) != 0U)2002{2003if ((format & PNG_FORMAT_FLAG_COLOR) != 0U)2004{2005/* BGR may have swapped the early codes. gray-to-RGB may have2006* set them all to '8':2007*/2008png_byte acode = codes[3];2009codes[3] = codes[2];2010codes[2] = codes[1];2011codes[1] = codes[0];2012codes[0] = acode;2013}20142015else /* GA format */2016codes[0] = codes[1], codes[1] = 8U;2017}20182019/* PNG_BO_SWAP_16: 16-bit only, handled below */20202021/* Now the 16-bit dependent stuff. */2022if ((args & PNG_BO_CHOP_16_TO_8) != 0U)2023{2024/* 16-bit input, 8-bit output, happens before FILLER so the2025* filler must be an 8-bit value. Apart from a filler code (4 in2026* this case) the code must be adjusted from byte 'x' to byte2027* '2x' to select the MSB of each 16-bit channel.2028*2029* We must use PNG_FORMAT_CHANNELS here because the memory pixel2030* size might (in the future) include a TO16 operation.2031*/2032unsigned int i = PNG_FORMAT_CHANNELS(format);20332034while (i > 0U)2035{2036unsigned int code = codes[--i];20372038if (code > 8U) /* 8, 4 need not change */2039codes[i] = PNG_BYTE(8U+2U*(code-8U));2040}2041}20422043if ((args & PNG_BO_EXPAND_16) != 0U)2044{2045/* Don't expect this with CHOP, but it will work, setting the low2046* 8-bits of each 16-bit value to the high bits.2047*/2048unsigned int i = PNG_FORMAT_CHANNELS(format);20492050while (i > 0U)2051{2052png_byte code = codes[--i];20532054/* BSWAP is after FILLER, however the data passed in is a2055* machine native png_uint_16. We don't know until this init2056* routine whether the data is an 8 or 16-bit value because we2057* don't know the full set of transforms the app will apply2058* when the png_set_filler API is called.2059*2060* This means that the data in tr->filler[] needs to have the2061* low bits in a known place, so the code here puts the low 82062* bits in filler[0], code 4. Hence the following:2063*/2064if (code == 4U)2065codes[2U*i/*MSB*/] = 5U, codes[2U*i+1U/*LSB*/] = 4U;20662067else2068codes[2U*i] = codes[2U*i+1U] = code;2069}20702071# ifdef PNG_READ_tRNS_SUPPORTED2072/* We're just duplicating bytes, so the tRNS chunk can be2073* maintained if present. If the tRNS is for a colormap this2074* produces garbage in trans_color, but it isn't used.2075*/2076if (png_ptr->num_trans == 1U)2077{2078# define TO16(x) x = PNG_UINT_16((x & 0xFFU) * 0x101U)2079TO16(png_ptr->trans_color.gray);2080TO16(png_ptr->trans_color.red);2081TO16(png_ptr->trans_color.green);2082TO16(png_ptr->trans_color.blue);2083# undef TO162084}2085# endif /* READ_tRNS */2086}20872088else if (bit_depth == 16U)2089{2090/* 16-bit input and output. */2091unsigned int i = PNG_FORMAT_CHANNELS(format);20922093while (i > 0U)2094{2095unsigned int code = codes[--i];20962097if (code == 4U) /* as above */2098codes[2U*i/*MSB*/] = 5U, codes[2U*i+1U/*LSB*/] = 4U;20992100else2101{2102codes[2U*i] = PNG_BYTE(8U+2U*(code-8U));2103codes[2U*i+1U] = PNG_BYTE(8U+2U*(code-8U)+1U);2104}2105}2106}21072108if ((args & PNG_BO_SWAP_16) != 0U)2109{2110/* bswap the memory bytes. */2111unsigned int i;2112png_byte bswap_codes[sizeof codes];21132114debug((memory_pixel_size & 1U) == 0U);21152116for (i=0U; i<sizeof codes; ++i)2117bswap_codes[i] = codes[i ^ 1U];21182119memcpy(codes, bswap_codes, sizeof codes);2120}21212122# ifdef PNG_WRITE_TRANSFORMS_SUPPORTED2123/* Handle the 'write' case; the codes[] array must be inverted,2124* it lists the PNG pixel for each memory pixel, we need it to2125* list the memory pixel for each PNG pixel.2126*/2127if (!png_ptr->read_struct)2128{2129/* There are no write transforms that add data to the PNG2130* file; the 'filler' transform removes a channel, but that is2131* the limit of the changes.2132*/2133unsigned int i = 0U;2134png_byte write_codes[8U];21352136memset(write_codes, 0, sizeof write_codes);21372138while (i<memory_pixel_size)2139{2140unsigned int code = codes[i];21412142if (code >= 8U) /* 8+index of PNG byte */2143write_codes[code-8U] = PNG_BYTE(8U+i);2144/* else this is a filler byte to be removed */2145else2146debug(code == 4U || code == 5U);21472148++i;2149}21502151code_size = png_pixel_size;2152src_size = memory_pixel_size;2153tr->format = png_format;2154tr->bit_depth = png_bit_depth;21552156/* The PNG size should always be <= to the memory size, the2157* source pointer will be the memory, the destination the PNG2158* format, so it should always be possible to do the upwards2159* copy.2160*/2161go_down = png_pixel_size > memory_pixel_size;2162affirm(!go_down);2163memcpy(codes, write_codes, sizeof codes);2164}21652166else2167# endif /* WRITE_TRANSFORMS */2168{2169code_size = memory_pixel_size;2170src_size = png_pixel_size;2171tr->format = format;2172tr->bit_depth = bit_depth;2173go_down = png_pixel_size < memory_pixel_size;2174}21752176/* Record this for debugging: */2177tr->tr.args = args;21782179/* For the same-pixel-size case check for a bswap; this is available2180* in heavily optimized forms and is a common operation (50% of the2181* time) with 16-bit PNG data, particularly given the handling in2182* the simplified API.2183*/2184if (!go_down)2185{2186if (memory_pixel_size == png_pixel_size)2187{2188int the_same = 1;2189int swapped = (memory_pixel_size & 1) == 0; /* even count */2190unsigned int i;21912192for (i=0U; i<memory_pixel_size; ++i)2193{2194if (codes[i] != 8U+i)2195{2196the_same = 0;2197if (codes[i] != 8U+(i^1U))2198swapped = 0;2199if (!swapped)2200break;2201}22022203else /* byte is copied, so it can't be swapped! */2204{2205swapped = 0;2206if (!the_same)2207break;2208}2209}22102211/* Use the 'bswap' routine if possible. */2212if (swapped)2213{2214tr->tr.fn = png_do_bswap;2215return;2216}22172218else if (the_same)2219impossible("not reached");2220}22212222tr->tr.fn = png_do_byte_ops_up;22232224/* Construct the code, forwards: */2225{2226unsigned int i = code_size;2227png_uint_32 code = 0U;22282229while (i > 0U)2230{2231unsigned int next = codes[--i];22322233code <<= 4U;22342235if ((next >= 8U && next < 8U+src_size) ||2236next == 4U || next == 5U)2237code += next;22382239else2240impossible("invalid code (up)");2241}22422243tr->codes = code;2244}2245}22462247else /* go_down */2248# ifdef PNG_READ_TRANSFORMS_SUPPORTED2249{2250tr->tr.fn = png_do_byte_ops_down;22512252/* Construct the code, backwards: */2253{2254unsigned int i = 0U;2255png_uint_32 code = 0U;22562257while (i < code_size)2258{2259unsigned int next = codes[i++];22602261code <<= 4;22622263if ((next >= 8U && next < 8U+src_size) ||2264next == 4U || next == 5U)2265code += next;22662267else2268impossible("invalid code (down)");2269}22702271tr->codes = code;2272}2273}2274# else /* !READ_TRANSFORMS */2275impossible("not reached"); /* because of the affirm above */2276# endif /* !READ_TRANSFORMS */2277}2278}22792280else /* TC_INIT_FORMAT: just store modified 'args' */2281{2282tc->format = format;2283tc->bit_depth = bit_depth;2284tr->tr.args = args;2285}2286}22872288else /* the transform is not applicable */2289tr->tr.fn = NULL;2290}2291#endif /* SWAP poo */22922293#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED2294static void2295png_init_rgb_to_gray_byte_ops(png_transformp *transform,2296png_transform_controlp tc)2297{2298/* This just delay initializes the function; all the transform initialization2299* has been done below.2300*/2301(*transform)->fn = png_do_byte_ops_up;23022303/* If this happens on a row do the transform immediately: */2304if (!tc->init)2305png_do_byte_ops_up(transform, tc);23062307else2308{2309/* This doing the init - update the row information here */2310# define png_ptr (tc->png_ptr)2311png_transform_byte_op *tr =2312png_transform_cast(png_transform_byte_op, *transform);23132314debug(tc->bit_depth == 8U || tc->bit_depth == 16U);2315debug((tc->format & PNG_FORMAT_FLAG_COLORMAP) == 0U &&2316(tc->format & PNG_FORMAT_FLAG_COLOR) != 0U);23172318tc->format = tr->format;2319tc->bit_depth = tr->bit_depth;2320# undef png_ptr2321}2322}23232324void /* PRIVATE */2325png_add_rgb_to_gray_byte_ops(png_structrp png_ptr, png_transform_controlp tc,2326unsigned int index, unsigned int order)2327/* Add a byte_ops transform to convert RGB or RGBA data to 'gray' by2328* selecting just the given change [index] The transform added is added at2329* 'order'.2330*/2331{2332png_transform_byte_op *tr = png_transform_cast(png_transform_byte_op,2333png_add_transform(png_ptr, sizeof (png_transform_byte_op),2334png_init_rgb_to_gray_byte_ops, order));23352336affirm((tc->format & (PNG_FORMAT_FLAG_COLOR+PNG_FORMAT_FLAG_COLORMAP)) ==2337PNG_FORMAT_FLAG_COLOR &&2338index <= 2 && tc->init == PNG_TC_INIT_FINAL);23392340tr->format = tc->format & PNG_BIC_MASK(PNG_FORMAT_FLAG_COLOR);2341tr->bit_depth = tc->bit_depth;23422343/* For 1 byte channel [index] plus, maybe, alpha: */2344if (tc->bit_depth == 8)2345tr->codes = 8U + index +2346((tc->format & PNG_FORMAT_FLAG_ALPHA) != 0 ? (8U+3U) << 4 : 0U);23472348else2349{2350affirm(tc->bit_depth == 16);23512352/* As above, but two bytes; [2*index] and [2*index+1] */2353index *= 2U;2354tr->codes = (8U + index) + ((9U + index) << 4) +2355((tc->format & PNG_FORMAT_FLAG_ALPHA) != 0 ?2356((8U+6U) + ((9U+6U) << 4)) << 8 : 0U);2357}2358}2359#endif /* READ_RGB_TO_GRAY */23602361#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) &&\2362defined(PNG_READ_BACKGROUND_SUPPORTED)2363void /* PRIVATE */2364png_push_gray_to_rgb_byte_ops(png_transformp *transform,2365png_transform_controlp tc)2366/* This is an init-time utility to add appropriate byte ops to expand a2367* grayscale PNG data set to RGB.2368*/2369{2370# define png_ptr (tc->png_ptr)2371png_transformp tr = png_push_transform(png_ptr,2372sizeof (png_transform_byte_op), png_init_byte_ops, transform, NULL);23732374tr->args = PNG_BO_GRAY_TO_RGB;2375debug(tr == *transform);2376png_init_byte_ops(transform, tc);2377# undef png_ptr2378}2379#endif /* GRAY_TO_RGB && READ_BACKGROUND */23802381#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED2382void /* PRIVATE */2383png_add_strip_alpha_byte_ops(png_structrp png_ptr)2384{2385png_add_transform(png_ptr, sizeof (png_transform_byte_op), png_init_byte_ops,2386PNG_TR_CHANNEL_PREQ)->args |= PNG_BO_STRIP_ALPHA;2387}2388#endif /* READ_STRIP_ALPHA */23892390#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED2391/* Chop 16-bit depth files to 8-bit depth */2392void PNGAPI2393png_set_strip_16(png_structrp png_ptr)2394{2395if (png_ptr != NULL)2396png_add_transform(png_ptr, sizeof (png_transform_byte_op),2397png_init_byte_ops, PNG_TR_CHANNEL_PREQ)->args |=2398PNG_BO_CHOP_16_TO_8;2399}2400#endif /* READ_STRIP_16_TO_8 */24012402#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED2403void PNGAPI2404png_set_gray_to_rgb(png_structrp png_ptr)2405{2406if (png_ptr != NULL)2407{2408png_set_expand_gray_1_2_4_to_8(png_ptr);2409png_add_transform(png_ptr, sizeof (png_transform_byte_op),2410png_init_byte_ops, PNG_TR_CHANNEL_PREQ)->args |=2411PNG_BO_GRAY_TO_RGB;2412}2413}2414#endif /* READ_GRAY_TO_RGB */24152416/* QUANTIZE */24172418#ifdef PNG_READ_EXPAND_16_SUPPORTED2419/* Expand to 16-bit channels. PNG_BO_EXPAND_16 also expands the tRNS chunk if2420* it is present, but it requires low bit depth grayscale expanded first. This2421* must also force palette to RGB.2422*/2423void PNGAPI2424png_set_expand_16(png_structrp png_ptr)2425{2426if (png_ptr != NULL)2427{2428png_set_expand_gray_1_2_4_to_8(png_ptr);2429png_set_palette_to_rgb(png_ptr);2430png_add_transform(png_ptr, sizeof (png_transform_byte_op),2431png_init_byte_ops, PNG_TR_CHANNEL_POSTQ)->args |=2432PNG_BO_EXPAND_16;2433}2434}2435#endif /* READ_EXPAND_16 */24362437#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)2438void PNGAPI2439png_set_bgr(png_structrp png_ptr)2440{2441if (png_ptr != NULL)2442{2443# ifndef PNG_READ_BGR_SUPPORTED2444if (png_ptr->read_struct)2445{2446png_app_error(png_ptr, "png_set_bgr not supported on read");2447return;2448}2449# endif2450# ifndef PNG_WRITE_BGR_SUPPORTED2451if (!png_ptr->read_struct)2452{2453png_app_error(png_ptr, "png_set_bgr not supported on write");2454return;2455}2456# endif24572458png_add_transform(png_ptr, sizeof (png_transform_byte_op),2459png_init_byte_ops, PNG_TR_CHANNEL_POSTQ)->args |=2460PNG_BO_BGR;2461}2462}2463#endif /* BGR */24642465#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)2466/* This includes png_set_filler and png_set_add_alpha. The only difference2467* between the two is that the latter resulted in PNG_COLOR_MASK_ALPHA being2468* added to the info_ptr color type, if png_read_update_info was called whereas2469* the former did not.2470*2471* Regardless of whether the added channel resulted in the change to the2472* png_info color type, the SWAP_ALPHA transform was not performed, even though2473* it apparently occured after the add, because PNG_COLOR_MASK_ALPHA was never2474* set in the 1.6 'row_info'.2475*2476* Consequently 'SWAP_ALPHA' and 'FILLER' were independent; one or the other2477* would occur depending on the color type (not the number of channels) prior to2478* the two transforms.2479*2480* Prior to 1.7.0 the app could obtain information about the memory format by2481* calling png_read_update_info followed by png_get_color_type and2482* png_get_channels. The first would return PNG_COLOR_TYPE..._ALPHA if2483* png_set_add_alpha was performed and the base type if png_set_filler was2484* performed, however in both cases png_get_channels would return the extra2485* channel; 2 or 4.2486*2487* The app could also insert a user transform callback and view the color type2488* in the old "row_info" structure, however this resulted in an inconsistent2489* color type because png_set_alpha did not add COLOR_MASK_ALPHA to the color2490* type.2491*2492* Hence API CHANGE: 1.7.0, row transform callbacks now see the same color type2493* as reported by png_get_color_type after png_read_update_info.2494*/2495/* Add a filler byte on read, or remove a filler or alpha byte on write.2496* The filler type has changed in v0.95 to allow future 2-byte fillers2497* for 48-bit input data, as well as to avoid problems with some compilers2498* that don't like bytes as parameters.2499*/2500static void2501set_filler(png_structrp png_ptr, png_uint_32 filler, int filler_loc, int alpha)2502{2503if (png_ptr != NULL)2504{2505if (filler_loc != PNG_FILLER_BEFORE && filler_loc != PNG_FILLER_AFTER)2506{2507png_app_error(png_ptr, "png_set_filler: invalid filler location");2508return;2509}25102511# ifndef PNG_READ_SWAP_SUPPORTED2512if (png_ptr->read_struct)2513{2514png_app_error(png_ptr, "png_set_filler not supported on read");2515return;2516}2517# endif2518# ifndef PNG_WRITE_SWAP_SUPPORTED2519if (!png_ptr->read_struct)2520{2521png_app_error(png_ptr, "png_set_filler not supported on write");2522return;2523}2524# endif25252526{2527png_transform_byte_op *tr =2528png_transform_cast(png_transform_byte_op,2529png_add_transform(png_ptr, sizeof (png_transform_byte_op),2530png_init_byte_ops, PNG_TR_CHANNEL_POSTQ));2531png_uint_32 args = PNG_BO_FILLER;25322533if (filler_loc == PNG_FILLER_BEFORE)2534args |= PNG_BO_FILLER_FIRST;25352536if (alpha)2537args |= PNG_BO_FILLER_ALPHA;25382539tr->tr.args |= args;25402541/* The filler must be stored LSByte first: */2542tr->filler[0] = PNG_BYTE(filler >> 0);2543tr->filler[1] = PNG_BYTE(filler >> 8);2544tr->filler[2] = PNG_BYTE(filler >> 16);2545tr->filler[3] = PNG_BYTE(filler >> 24);2546}2547}2548}25492550void PNGAPI2551png_set_filler(png_structrp png_ptr, png_uint_32 filler, int filler_loc)2552{2553set_filler(png_ptr, filler, filler_loc, 0/*!alpha*/);2554}25552556/* Added to libpng-1.2.7 */2557void PNGAPI2558png_set_add_alpha(png_structrp png_ptr, png_uint_32 filler, int filler_loc)2559{2560set_filler(png_ptr, filler, filler_loc, 1/*alpha*/);2561}2562#endif /* FILLER */25632564#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \2565defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)2566void PNGAPI2567png_set_swap_alpha(png_structrp png_ptr)2568{2569if (png_ptr != NULL)2570{2571# ifndef PNG_READ_SWAP_SUPPORTED2572if (png_ptr->read_struct)2573{2574png_app_error(png_ptr, "png_set_swap_alpha not supported on read");2575return;2576}2577# endif2578# ifndef PNG_WRITE_SWAP_SUPPORTED2579if (!png_ptr->read_struct)2580{2581png_app_error(png_ptr, "png_set_swap_alpha not supported on write");2582return;2583}2584# endif25852586png_add_transform(png_ptr, sizeof (png_transform_byte_op),2587png_init_byte_ops, PNG_TR_CHANNEL_POSTQ)->args |=2588PNG_BO_SWAP_ALPHA;2589}2590}2591#endif /* SWAP_ALPHA */25922593#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)2594void PNGAPI2595png_set_swap(png_structrp png_ptr)2596{2597if (png_ptr != NULL)2598{2599# ifndef PNG_READ_SWAP_SUPPORTED2600if (png_ptr->read_struct)2601{2602png_app_error(png_ptr, "png_set_swap not supported on read");2603return;2604}2605# endif2606# ifndef PNG_WRITE_SWAP_SUPPORTED2607if (!png_ptr->read_struct)2608{2609png_app_error(png_ptr, "png_set_swap not supported on write");2610return;2611}2612# endif26132614png_add_transform(png_ptr, sizeof (png_transform_byte_op),2615png_init_byte_ops, PNG_TR_CHANNEL_POSTQ)->args |=2616PNG_BO_SWAP_16;2617}2618}2619#endif /* SWAP */26202621#if defined(PNG_READ_PACKSWAP_SUPPORTED) ||\2622defined(PNG_WRITE_PACKSWAP_SUPPORTED) ||\2623defined(PNG_READ_INVERT_ALPHA_SUPPORTED) ||\2624defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) ||\2625defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)2626static png_alloc_size_t2627row_align(png_transform_controlp tc)2628/* Utiltity to align the source row (sp) in a transform control; it does this2629* by simply copying it to dp if it is not already aligned. As a convenience2630* the utility returns the number of bytes in the row.2631*/2632{2633png_const_structp png_ptr = tc->png_ptr;2634png_const_voidp sp = tc->sp;2635png_voidp dp = tc->dp;2636png_alloc_size_t rowbytes = PNG_TC_ROWBYTES(*tc);26372638/* For alignment; if png_alignof is not supported by the compiler this will2639* always do an initial memcpy if the source and destination are not the2640* same. We can only get here for write; the read case always uses locally2641* allocated buffers, only write reads from the application data directly.2642*/2643# ifdef png_alignof2644debug(png_isaligned(dp, png_uint_32));2645# endif2646if (sp != dp && !png_ptr->read_struct && !png_isaligned(sp, png_uint_32))2647{2648UNTESTED2649memcpy(dp, sp, rowbytes);2650tc->sp = dp;2651}26522653return rowbytes;2654}2655#endif /* Stuff that needs row_align */26562657#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) ||\2658defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) ||\2659defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)2660/* Bit-ops; invert bytes. This works for mono inverts too because even the low2661* bit depths can be handled as bytes (since there can be no intervening2662* channels).2663*/2664#define PNG_B_INVERT_MONO 1U2665#define PNG_B_INVERT_RGB 2U /* not set, used below */2666#define PNG_B_INVERT_ALPHA 4U26672668typedef struct2669{2670png_transform tr;2671unsigned int step0; /* initial advance on sp and dp */2672unsigned int step; /* advance after start */2673png_uint_32 mask; /* XOR mask */2674} png_transform_bit_op;26752676static void2677png_do_invert_all(png_transformp *transform, png_transform_controlp tc)2678{2679const png_const_structp png_ptr = tc->png_ptr;2680/* Invert the whole row, quickly */2681const png_const_voidp dp_end = png_upcast(png_bytep, tc->dp) + row_align(tc);2682png_uint_32p dp = png_voidcast(png_uint_32p, tc->dp);2683png_const_uint_32p sp = png_voidcast(png_const_uint_32p, tc->sp);26842685tc->sp = dp;26862687if (png_ptr->read_struct)2688{2689tc->format |= PNG_FORMAT_FLAG_RANGE;2690tc->range++;2691}26922693else if (--(tc->range) == 0)2694tc->format &= PNG_BIC_MASK(PNG_FORMAT_FLAG_RANGE);26952696while (png_upcast(void*,dp) < dp_end)2697*dp++ = ~*sp++;26982699PNG_UNUSED(transform)2700}27012702static void2703png_do_invert_channel(png_transformp *transform, png_transform_controlp tc)2704{2705const png_const_structp png_ptr = tc->png_ptr;2706/* Invert just one channel in the row. */2707const png_transform_bit_op * const tr =2708png_transform_cast(png_transform_bit_op, *transform);2709const png_uint_32 mask = tr->mask;2710const unsigned int step = tr->step;2711const unsigned int step0 = tr->step0;2712const png_const_voidp dp_end = png_upcast(png_bytep, tc->dp) + row_align(tc);2713png_uint_32p dp = png_voidcast(png_uint_32p, tc->dp);2714png_const_uint_32p sp = png_voidcast(png_const_uint_32p, tc->sp);27152716tc->sp = dp;27172718if (png_ptr->read_struct)2719{2720tc->format |= PNG_FORMAT_FLAG_RANGE;2721tc->range++;2722}27232724else if (--(tc->range) == 0)2725tc->format &= PNG_BIC_MASK(PNG_FORMAT_FLAG_RANGE);27262727if (sp == dp || step == 1)2728{2729sp += step0;2730dp += step0;27312732while (png_upcast(void*,dp) < dp_end)2733*dp = *sp ^ mask, dp += step, sp += step;2734}27352736else /* step == 2, copy required */2737{2738if (step0) /* must be 1 */2739*dp++ = *sp++;27402741while (png_upcast(void*,dp) < dp_end)2742{2743*dp++ = *sp++ ^ mask;2744if (!(png_upcast(void*,dp) < dp_end))2745break;2746*dp++ = *sp++;2747}2748}27492750PNG_UNUSED(transform)2751}27522753static void2754png_init_invert(png_transformp *transform, png_transform_controlp tc)2755{2756# define png_ptr (tc->png_ptr)2757png_transform_bit_op *tr =2758png_transform_cast(png_transform_bit_op, *transform);2759png_uint_32 invert = tr->tr.args;2760png_uint_32 present; /* channels present */27612762if ((tc->format & PNG_FORMAT_FLAG_COLORMAP) != 0)2763present = 0;27642765else /* not color mapped */2766{2767if ((tc->format & PNG_FORMAT_FLAG_COLOR) != 0)2768present = PNG_B_INVERT_RGB;2769else2770present = PNG_B_INVERT_MONO;27712772if ((tc->format & PNG_FORMAT_FLAG_ALPHA) != 0)2773present |= PNG_B_INVERT_ALPHA;2774}27752776/* Cannot invert things that aren't there: */2777invert &= present;27782779/* If nothing can be inverted is present the transform is not applicable: */2780if (invert == 0)2781(*transform)->fn = NULL;27822783else2784{2785tc->format |= PNG_FORMAT_FLAG_RANGE;2786tc->range++;27872788if (tc->init == PNG_TC_INIT_FINAL)2789{2790/* If everything that is present is to be inverted just invert the2791* whole row:2792*/2793if (invert == present)2794(*transform)->fn = png_do_invert_all;27952796else2797{2798/* One thing is to be inverted, G or A: */2799unsigned int channels = PNG_TC_CHANNELS(*tc);2800unsigned int channel =2801(tc->format & PNG_FORMAT_FLAG_AFIRST) != 0 ? 0 : channels-1;28022803affirm(channels == 2 || channels == 4);28042805if (invert != PNG_B_INVERT_ALPHA)2806{2807debug(invert == PNG_B_INVERT_MONO && channels == 2 &&2808present == PNG_B_INVERT_MONO+PNG_B_INVERT_ALPHA);2809channel = (channels-1) - channel;2810}28112812affirm(tc->bit_depth == 8 || tc->bit_depth == 16);28132814/* So channels[channel] is to be inverted, make a mask: */2815{2816union2817{2818png_byte bytes[8];2819png_uint_32 words[2];2820} masks;28212822memset(&masks, 0, sizeof masks);28232824if (tc->bit_depth == 8)2825{2826/* channels is 2 or 4, channel < 4. */2827masks.bytes[channel+channels] = masks.bytes[channel] = 0xff;2828tr->step = 1;2829tr->mask = masks.words[0];2830tr->step0 = 0;2831}28322833else /* tc->bit_depth == 16 */2834{2835channel <<= 1; /* in bytes */2836masks.bytes[channel+1] = masks.bytes[channel] = 0xff;28372838if (channels == 2)2839{2840tr->step = 1;2841tr->mask = masks.words[0];2842tr->step0 = 0;2843}28442845else /* channels == 4 */2846{2847tr->step = 2;28482849if (masks.words[0] == 0)2850{2851tr->mask = masks.words[1];2852tr->step0 = 1;2853}28542855else2856{2857tr->mask = masks.words[0];2858tr->step0 = 0;2859}2860}2861}2862}28632864(*transform)->fn = png_do_invert_channel;2865}2866}2867}2868# undef png_ptr2869}28702871#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) ||\2872defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)2873void PNGAPI2874png_set_invert_alpha(png_structrp png_ptr)2875{2876if (png_ptr != NULL)2877{2878png_add_transform(png_ptr, sizeof (png_transform_bit_op),2879png_init_invert, PNG_TR_INVERT)->args |= PNG_B_INVERT_ALPHA;2880# ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED2881/* This is necessary to avoid palette processing on write; the only2882* transform that applies to colormapped images is the tRNS chunk2883* invert.2884*/2885png_ptr->write_invert_alpha = 1U;2886# endif2887}2888}2889#endif /* INVERT_ALPHA */28902891#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)2892void PNGAPI2893png_set_invert_mono(png_structrp png_ptr)2894{2895if (png_ptr != NULL)2896png_add_transform(png_ptr, sizeof (png_transform_bit_op),2897png_init_invert, PNG_TR_INVERT)->args |= PNG_B_INVERT_MONO;2898}2899#endif /* INVERT */2900#endif /* INVERT_ALPHA || INVERT */29012902/*2903* WARNING2904* WARNING2905* WARNING2906* WARNING2907* WARNING The transforms below are temporary; they can and will be2908* WARNING heavily optimized before release.2909* WARNING2910* WARNING2911* WARNING2912*/2913#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)2914typedef struct2915{2916png_transform tr;2917png_color_8 true_bits;2918} png_transform_shift;29192920/* Shift pixel values to take advantage of whole range. Pass the2921* true number of bits in bit_depth. The row should be packed2922* according to tc->bit_depth. Thus, if you had a row of2923* bit depth 4, but the pixels only had values from 0 to 7, you2924* would pass 3 as bit_depth, and this routine would translate the2925* data to 0 to 15.2926*2927* NOTE: this is horrible complexity for no value. Once people suggested they2928* were selling 16-bit displays with 5:6:5 bits spread R:G:B but so far as I2929* could determine these displays produced intermediate grey (uncolored) colors,2930* which is impossible with a true 5:6:5, so most likely 5:6:5 was marketing.2931*/2932static unsigned int2933set_shifts(unsigned int format, unsigned int bit_depth,2934png_const_color_8p true_bits, int *shift_start, int *shift_dec)2935{2936unsigned int channels = 0;29372938if ((format & (PNG_FORMAT_FLAG_ALPHA+PNG_FORMAT_FLAG_AFIRST)) ==2939(PNG_FORMAT_FLAG_ALPHA+PNG_FORMAT_FLAG_AFIRST))2940++channels; /* filled in below */29412942if ((format & PNG_FORMAT_FLAG_COLOR) != 0)2943{2944unsigned int offset = /* 0 or 2 as appropriate for red */2945((format & PNG_FORMAT_FLAG_BGR) != 0) << 1;29462947shift_start[channels+offset] = bit_depth - true_bits->red;2948if (shift_dec != NULL) shift_dec[channels+offset] = true_bits->red;29492950shift_start[channels+1] = bit_depth - true_bits->green;2951if (shift_dec != NULL) shift_dec[channels+1] = true_bits->green;29522953offset ^= 2; /* for blue */2954shift_start[channels+offset] = bit_depth - true_bits->blue;2955if (shift_dec != NULL) shift_dec[channels+offset] = true_bits->blue;29562957channels += 3;2958}29592960else /* no color: gray */2961{2962shift_start[channels] = bit_depth - true_bits->gray;2963if (shift_dec != NULL) shift_dec[channels] = true_bits->gray;2964++channels;2965}29662967if ((format & PNG_FORMAT_FLAG_ALPHA) != 0)2968{2969const unsigned int offset =2970(format & PNG_FORMAT_FLAG_AFIRST) != 0 ? 0 : channels++;29712972shift_start[offset] = bit_depth - true_bits->alpha;2973if (shift_dec != NULL) shift_dec[offset] = true_bits->alpha;2974}29752976return channels;2977}29782979#ifdef PNG_WRITE_SHIFT_SUPPORTED2980static void2981png_do_shift(png_transformp *transform, png_transform_controlp tc)2982{2983# define png_ptr (tc->png_ptr)2984png_transform_shift *tr =2985png_transform_cast(png_transform_shift, *transform);2986png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp);2987png_bytep dp = png_voidcast(png_bytep, tc->dp);2988png_const_bytep dp_end = dp + PNG_TC_ROWBYTES(*tc);29892990png_debug(1, "in png_do_shift");29912992if (--(tc->range) == 0)2993tc->format &= PNG_BIC_MASK(PNG_FORMAT_FLAG_RANGE);29942995tc->sp = dp;29962997{2998int shift_start[4], shift_dec[4];2999unsigned int channels = set_shifts(tc->format, tc->bit_depth,3000&tr->true_bits, shift_start, shift_dec);30013002debug(PNG_TC_CHANNELS(*tc) == channels);30033004/* With low res depths, could only be grayscale, so one channel */3005if (tc->bit_depth < 8)3006{3007unsigned int mask;30083009UNTESTED3010affirm(channels == 1);3011/* This doesn't matter but we expect to run before packswap: */3012debug(!(tc->format & PNG_FORMAT_FLAG_SWAPPED));30133014if (tr->true_bits.gray == 1 && tc->bit_depth == 2)3015mask = 0x55;30163017else if (tc->bit_depth == 4 && tr->true_bits.gray == 3)3018mask = 0x11;30193020else3021mask = 0xff;30223023while (dp < dp_end)3024{3025int j;3026unsigned int v, out;30273028v = *sp++;3029out = 0;30303031for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0])3032{3033if (j > 0)3034out |= v << j;30353036else3037out |= (v >> (-j)) & mask;3038}30393040*dp++ = png_check_byte(png_ptr, out);3041}3042}30433044else if (tc->bit_depth == 8)3045{3046unsigned int c = 0;30473048UNTESTED3049while (dp < dp_end)3050{30513052int j;3053unsigned int v, out;30543055v = *sp++;3056out = 0;30573058for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])3059{3060if (j > 0)3061out |= v << j;30623063else3064out |= v >> (-j);3065}30663067*dp++ = png_check_byte(png_ptr, out);3068if (++c == channels) c = 0;3069}3070}30713072else /* tc->bit_depth == 16 */3073{3074unsigned int c = 0, s0, s1;30753076UNTESTED3077if ((tc->format & PNG_FORMAT_FLAG_SWAPPED) != 0)3078s0 = 0, s1 = 8; /* LSB */30793080else3081s0 = 8, s1 = 0; /* MSB */30823083while (dp < dp_end)3084{3085int j;3086unsigned int value, v;30873088v = *sp++ << s0;3089v += *sp++ << s1;3090value = 0;30913092for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])3093{3094if (j > 0)3095value |= v << j;30963097else3098value |= v >> (-j);3099}31003101*dp++ = PNG_BYTE(value >> s0);3102*dp++ = PNG_BYTE(value >> s1);3103}3104}3105}3106# undef png_ptr3107}3108#endif /* WRITE_SHIFT */31093110#ifdef PNG_READ_SHIFT_SUPPORTED3111/* Reverse the effects of png_do_shift. This routine merely shifts the3112* pixels back to their significant bits values. Thus, if you have3113* a row of bit depth 8, but only 5 are significant, this will shift3114* the values back to 0 through 31.3115*/3116static void3117png_do_unshift(png_transformp *transform, png_transform_controlp tc)3118{3119# define png_ptr (tc->png_ptr)3120png_transform_shift *tr =3121png_transform_cast(png_transform_shift, *transform);3122png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp);3123png_bytep dp = png_voidcast(png_bytep, tc->dp);3124png_const_bytep dp_end = dp + PNG_TC_ROWBYTES(*tc);31253126png_debug(1, "in png_do_unshift");31273128tc->range++;3129tc->format |= PNG_FORMAT_FLAG_RANGE;31303131{3132int shift[4];3133unsigned int channels = set_shifts(tc->format, tc->bit_depth,3134&tr->true_bits, shift, NULL);31353136debug(PNG_TC_CHANNELS(*tc) == channels);31373138{3139unsigned int c, have_shift;31403141for (c = have_shift = 0; c < channels; ++c)3142{3143/* A shift of more than the bit depth is an error condition but it3144* gets ignored here.3145*/3146if (shift[c] <= 0 || (unsigned)/*SAFE*/shift[c] >= tc->bit_depth)3147shift[c] = 0;31483149else3150have_shift = 1;3151}31523153if (have_shift == 0)3154return;3155}31563157/* The code below will copy sp to dp, so: */3158tc->sp = dp;31593160switch (tc->bit_depth)3161{3162default:3163/* Must be 1bpp gray: should not be here! */3164impossible("unshift bit depth");3165/* NOTREACHED */3166break;31673168case 2:3169/* Must be 2bpp gray */3170debug(channels == 1 && shift[0] == 1);3171debug(!(tc->format & PNG_FORMAT_FLAG_SWAPPED));31723173while (dp < dp_end)3174*dp++ = (*sp++ >> 1) & 0x55;3175break;31763177case 4:3178/* Must be 4bpp gray */3179debug(channels == 1);3180debug(!(tc->format & PNG_FORMAT_FLAG_SWAPPED));3181{3182unsigned int gray_shift = shift[0];3183unsigned int mask = 0xf >> gray_shift; /* <= 4 bits */31843185mask |= mask << 4; /* <= 8 bits */31863187while (dp < dp_end)3188*dp++ = (png_byte)/*SAFE*/((*sp++ >> gray_shift) & mask);3189}3190break;31913192case 8:3193/* Single byte components, G, GA, RGB, RGBA */3194{3195unsigned int channel = 0;31963197while (dp < dp_end)3198{3199*dp++ = (png_byte)/*SAFE*/(*sp++ >> shift[channel]);3200if (++channel >= channels)3201channel = 0;3202}3203}3204break;32053206case 16:3207/* Double byte components, G, GA, RGB, RGBA */3208{3209unsigned int channel = 0;3210unsigned int s0, s1;32113212if ((tc->format & PNG_FORMAT_FLAG_SWAPPED) != 0)3213s0 = 0, s1 = 8; /* LSB */32143215else3216s0 = 8, s1 = 0; /* MSB */32173218while (dp < dp_end)3219{3220unsigned int value = *sp++ << s0;32213222value += *sp++ << s1; /* <= 16 bits */32233224value >>= shift[channel];3225if (++channel >= channels) channel = 0;3226*dp++ = PNG_BYTE(value >> s0);3227*dp++ = PNG_BYTE(value >> s1);3228}3229}3230break;3231}3232}32333234# undef png_ptr3235}3236#endif /* READ_SHIFT */32373238static void3239init_shift(png_transformp *transform, png_transform_controlp tc)3240{3241png_const_structp png_ptr = tc->png_ptr;32423243/* These shifts apply to the component value, not the pixel index, so skip3244* palette data. In addition there is no *write* shift for palette entries;3245* only a read one, so skip the write/palette case too.3246*/3247if ((tc->format & PNG_FORMAT_FLAG_COLORMAP) == 0 &&3248(png_ptr->read_struct || !tc->palette))3249{3250/* The only change to the format is to mark the data as having a non-PNG3251* range.3252*/3253tc->range++;3254tc->format |= PNG_FORMAT_FLAG_RANGE;32553256if (tc->init == PNG_TC_INIT_FINAL)3257{3258# ifdef PNG_READ_SHIFT_SUPPORTED3259if (png_ptr->read_struct)3260{3261(*transform)->fn = png_do_unshift;3262return;3263}3264# endif3265# ifdef PNG_WRITE_SHIFT_SUPPORTED3266if (png_ptr->read_struct)3267{3268(*transform)->fn = png_do_shift;3269return;3270}3271# endif3272}3273}32743275else /* transform not applicable */3276(*transform)->fn = NULL;3277}32783279void PNGAPI3280png_set_shift(png_structrp png_ptr, png_const_color_8p true_bits)3281{3282if (png_ptr != NULL && true_bits != NULL)3283{3284# ifndef PNG_READ_SHIFT_SUPPORTED3285if (png_ptr->read_struct)3286{3287png_app_error(png_ptr, "png_set_shift not supported on read");3288return;3289}3290# endif3291# ifndef PNG_WRITE_SHIFT_SUPPORTED3292if (!png_ptr->read_struct)3293{3294png_app_error(png_ptr, "png_set_shift not supported on write");3295return;3296}3297# endif32983299{3300png_transform_shift *trs = png_transform_cast(png_transform_shift,3301png_add_transform(png_ptr, sizeof (png_transform_shift),3302init_shift, PNG_TR_SHIFT));3303trs->true_bits = *true_bits;3304}3305}3306}3307#endif /* SHIFT */33083309#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)3310/* Turn on pixel packing */3311void PNGAPI3312png_set_packing(png_structrp png_ptr)3313{3314/* The transforms aren't symmetric, so even though there is one API there are3315* two internal init functions, one for read, the other write:3316*/3317if (png_ptr != NULL)3318{3319if (png_ptr->read_struct)3320{3321# ifdef PNG_READ_PACK_SUPPORTED3322png_add_transform(png_ptr, 0/*size*/, png_init_read_pack,3323PNG_TR_PACK);3324# else3325png_app_error(png_ptr, "png_set_packing not supported on read");3326# endif3327}33283329else3330{3331# ifdef PNG_WRITE_PACK_SUPPORTED3332png_add_transform(png_ptr, 0/*size*/, png_init_write_pack,3333PNG_TR_PACK);3334# else3335png_app_error(png_ptr, "png_set_packing not supported on write");3336# endif3337}3338}3339}3340#endif /* PACK */33413342#if defined(PNG_READ_PACKSWAP_SUPPORTED) ||\3343defined(PNG_WRITE_PACKSWAP_SUPPORTED)3344/* Turn on pixel-swapping within a byte, this is symmetric - doing the swap3345* twice produces the original value, so only one implementation is required for3346* either read or write.3347*3348* Used to be refered to as "packswap", but pixel-swap seems more3349* self-documenting.3350*/3351static void3352png_do_swap_1bit(png_transformp *transform, png_transform_controlp tc)3353{3354png_alloc_size_t rowbytes = row_align(tc); /* may change tc->sp */3355png_const_uint_32p sp = png_voidcast(png_const_uint_32p, tc->sp);3356png_uint_32p dp = png_voidcast(png_uint_32p, tc->dp);33573358tc->sp = dp;3359tc->format ^= PNG_FORMAT_FLAG_SWAPPED;33603361for (;;)3362{3363png_uint_32 s = *sp++;3364s = ((s >> 1) & 0x55555555) | ((s & 0x55555555) << 1);3365s = ((s >> 2) & 0x33333333) | ((s & 0x33333333) << 2);3366s = ((s >> 4) & 0x0f0f0f0f) | ((s & 0x0f0f0f0f) << 4);3367*dp++ = s;3368if (rowbytes <= 4) break;3369rowbytes -= 4;3370}33713372PNG_UNUSED(transform)3373}33743375static void3376png_do_swap_2bit(png_transformp *transform, png_transform_controlp tc)3377{3378png_alloc_size_t rowbytes = row_align(tc); /* may change tc->sp */3379png_const_uint_32p sp = png_voidcast(png_const_uint_32p, tc->sp);3380png_uint_32p dp = png_voidcast(png_uint_32p, tc->dp);33813382tc->sp = dp;3383tc->format ^= PNG_FORMAT_FLAG_SWAPPED;33843385for (;;)3386{3387png_uint_32 s = *sp++;3388s = ((s >> 2) & 0x33333333) | ((s & 0x33333333) << 2);3389s = ((s >> 4) & 0x0f0f0f0f) | ((s & 0x0f0f0f0f) << 4);3390*dp++ = s;3391if (rowbytes <= 4) break;3392rowbytes -= 4;3393}33943395PNG_UNUSED(transform)3396}33973398static void3399png_do_swap_4bit(png_transformp *transform, png_transform_controlp tc)3400{3401png_alloc_size_t rowbytes = row_align(tc); /* may change tc->sp */3402png_const_uint_32p sp = png_voidcast(png_const_uint_32p, tc->sp);3403png_uint_32p dp = png_voidcast(png_uint_32p, tc->dp);34043405tc->sp = dp;3406tc->format ^= PNG_FORMAT_FLAG_SWAPPED;34073408for (;;)3409{3410png_uint_32 s = *sp++;3411s = ((s >> 4) & 0x0f0f0f0f) | ((s & 0x0f0f0f0f) << 4);3412*dp++ = s;3413if (rowbytes <= 4) break;3414rowbytes -= 4;3415}34163417PNG_UNUSED(transform)3418}34193420static void3421init_packswap(png_transformp *transform, png_transform_controlp tc)3422{3423png_transform_fn fn;34243425# define png_ptr tc->png_ptr3426debug(tc->init);3427# undef png_ptr34283429switch (tc->bit_depth)3430{3431case 1: fn = png_do_swap_1bit; break;3432case 2: fn = png_do_swap_2bit; break;3433case 4: fn = png_do_swap_4bit; break;34343435default: /* transform not applicable */3436(*transform)->fn = NULL;3437return;3438}34393440tc->format ^= PNG_FORMAT_FLAG_SWAPPED;3441if (tc->init == PNG_TC_INIT_FINAL)3442(*transform)->fn = fn;3443}34443445void PNGAPI3446png_set_packswap(png_structrp png_ptr)3447{3448if (png_ptr != NULL)3449{3450# ifndef PNG_READ_PACKSWAP_SUPPORTED3451if (png_ptr->read_struct)3452{3453png_app_error(png_ptr, "png_set_packswap not supported on read");3454return;3455}3456# endif3457# ifndef PNG_WRITE_PACKSWAP_SUPPORTED3458if (!png_ptr->read_struct)3459{3460png_app_error(png_ptr, "png_set_packswap not supported on write");3461return;3462}3463# endif34643465png_add_transform(png_ptr, 0/*size*/, init_packswap, PNG_TR_PIXEL_SWAP);3466}3467}3468#endif /* PACKSWAP */34693470/* User transform handling */3471#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED3472png_uint_32 PNGAPI3473png_get_current_row_number(png_const_structrp png_ptr)3474{3475/* See the comments in png.h - this is the sub-image row when reading an3476* interlaced image.3477*/3478if (png_ptr != NULL)3479{3480/* In the read case png_struct::row_number is the row in the final image,3481* not the pass, this will return the previous row number if the row isn't3482* in the pass:3483*/3484if (png_ptr->read_struct)3485return PNG_PASS_ROWS(png_ptr->row_number+1, png_ptr->pass)-1U;34863487else3488return png_ptr->row_number;3489}34903491return PNG_UINT_32_MAX; /* help the app not to fail silently */3492}34933494png_byte PNGAPI3495png_get_current_pass_number(png_const_structrp png_ptr)3496{3497if (png_ptr != NULL)3498return png_ptr->pass;3499return 8; /* invalid */3500}3501#endif /* USER_TRANSFORM_INFO */35023503#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) ||\3504defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)3505typedef struct3506{3507png_transform tr;3508png_user_transform_ptr user_fn;3509#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED3510png_voidp user_ptr;3511#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED3512unsigned int user_depth;3513unsigned int user_channels;3514#endif3515#endif3516} png_user_transform, *png_user_transformp;35173518typedef const png_user_transform *png_const_user_transformp;35193520static png_user_transformp3521get_user_transform(png_structrp png_ptr)3522{3523/* Note that in an added transform the whole transform is memset to 0, so we3524* don't need to initialize anything.3525*/3526return png_transform_cast(png_user_transform, png_add_transform(png_ptr,3527sizeof (png_user_transform), NULL/*function*/, PNG_TR_USER));3528}3529#endif /* READ_USER_TRANSFORM || WRITE_USER_TRANSFORM */35303531#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED3532png_voidp PNGAPI3533png_get_user_transform_ptr(png_const_structrp png_ptr)3534{3535if (png_ptr != NULL)3536{3537png_transformp tr = png_find_transform(png_ptr, PNG_TR_USER);35383539if (tr != NULL)3540{3541png_user_transformp tru = png_transform_cast(png_user_transform, tr);3542return tru->user_ptr;3543}3544}35453546return NULL;3547}3548#endif /* USER_TRANSFORM_PTR */35493550#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED3551void PNGAPI3552png_set_user_transform_info(png_structrp png_ptr, png_voidp ptr, int depth,3553int channels)3554{3555if (png_ptr != NULL)3556{3557/* NOTE: this function only sets the user transform pointer on write, i.e.3558* the depth and channels arguments are ignored.3559*/3560png_user_transformp tr = get_user_transform(png_ptr);35613562tr->user_ptr = ptr;35633564# ifdef PNG_READ_USER_TRANSFORM_SUPPORTED3565if (png_ptr->read_struct)3566{3567if (png_ptr->row_bit_depth == 0)3568{3569if (depth > 0 && depth <= 32 && channels > 0 && channels <= 4 &&3570(-depth & depth) == depth /* power of 2 */)3571{3572tr->user_depth = png_check_bits(png_ptr, depth, 6);3573tr->user_channels = png_check_bits(png_ptr, channels, 3);3574}35753576else3577png_app_error(png_ptr, "unsupported bit-depth or channels");3578}3579else3580png_app_error(png_ptr,3581"cannot change user info after image start");3582}3583# else /* !READ_USER_TRANSFORM */3584PNG_UNUSED(depth)3585PNG_UNUSED(channels)3586# endif /* !READ_USER_TRANSFORM */3587}3588}3589#endif /* USER_TRANSFORM_PTR */35903591#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED3592static void3593png_do_read_user_transform(png_transformp *trIn, png_transform_controlp tc)3594{3595# define png_ptr (tc->png_ptr)3596png_user_transformp tr = png_transform_cast(png_user_transform, *trIn);35973598if (!tc->init && tr->user_fn != NULL)3599{3600png_row_info row_info;36013602row_info.width = tc->width;3603row_info.rowbytes = PNG_TC_ROWBYTES(*tc);3604row_info.color_type = png_check_byte(png_ptr,3605PNG_COLOR_TYPE_FROM_FORMAT(tc->format));3606row_info.bit_depth = png_check_byte(png_ptr, tc->bit_depth);3607row_info.channels = png_check_byte(png_ptr,3608PNG_FORMAT_CHANNELS(tc->format));3609row_info.bit_depth = png_check_byte(png_ptr,3610PNG_TC_PIXEL_DEPTH(*tc));36113612/* TODO: fix this API, but for the moment we have to copy the row data to3613* the working buffer. This is an unnecessary perf overhead when a user3614* transform is used to read information without a transform or when it is3615* used on write.3616*/3617if (tc->sp != tc->dp)3618{3619memcpy(tc->dp, tc->sp, PNG_TC_ROWBYTES(*tc));3620tc->sp = tc->dp;3621}36223623tr->user_fn(png_ptr, &row_info, png_voidcast(png_bytep, tc->dp));3624}36253626# ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED3627if (tr->user_depth > 0)3628{3629/* The read transform can modify the bit depth and number of3630* channels; the interface doesn't permit anything else to be3631* changed. If the information isn't set the user callback has to3632* produce pixels with the correct pixel depth (otherwise the3633* de-interlace won't work) but there really is no other constraint.3634*/3635tc->bit_depth = tr->user_depth;36363637/* The API is very restricted in functionality; the user_channels3638* can be changed, but the color_type can't, so the format is simply3639* fixed up to match the channels.3640*/3641if (tr->user_channels != PNG_FORMAT_CHANNELS(tc->format))3642switch (tr->user_channels)3643{3644case 1:3645tc->format &=3646PNG_BIC_MASK(PNG_FORMAT_FLAG_COLOR+PNG_FORMAT_FLAG_ALPHA);3647break;36483649case 2: /* has to be GA */3650tc->format &=3651PNG_BIC_MASK(PNG_FORMAT_FLAG_COLORMAP+PNG_FORMAT_FLAG_COLOR);3652tc->format |= PNG_FORMAT_FLAG_ALPHA;3653break;36543655case 3: /* has to be RGB */3656tc->format &=3657PNG_BIC_MASK(PNG_FORMAT_FLAG_COLORMAP|PNG_FORMAT_FLAG_ALPHA);3658tc->format |= PNG_FORMAT_FLAG_COLOR;3659break;36603661case 4: /* has to be RGBA */3662tc->format &= PNG_BIC_MASK(PNG_FORMAT_FLAG_COLORMAP);3663tc->format |= (PNG_FORMAT_FLAG_COLOR+PNG_FORMAT_FLAG_ALPHA);3664break;36653666default: /* checked before */3667impossible("user channels");3668}36693670debug(PNG_FORMAT_CHANNELS(tc->format) == tr->user_channels);3671}3672# endif /* USER_TRANSFORM_PTR */3673# undef png_ptr3674}36753676void PNGAPI3677png_set_read_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr3678read_user_transform_fn)3679{3680/* There is no 'init' function, just the callback above to handle the3681* transform.3682*/3683if (png_ptr != NULL)3684{3685if (png_ptr->read_struct)3686{3687png_user_transformp tr = get_user_transform(png_ptr);36883689tr->user_fn = read_user_transform_fn;3690tr->tr.fn = png_do_read_user_transform;3691}36923693else3694png_app_error(png_ptr, "cannot set a read transform on write");3695}3696}3697#endif /* READ_USER_TRANSFORM */36983699#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED3700static void3701png_do_write_user_transform(png_transformp *trIn, png_transform_controlp tc)3702{3703# define png_ptr (tc->png_ptr)3704/* The write side is pretty simple; call the call-back, it will make the row3705* data right.3706*3707* BUG: we need to copy the input row (it would be a non-quiet API change3708* otherwise) and we don't know how big it is because the information passed3709* to png_set_user_transform_info never was used on write, but that's fine3710* because the write code never did get this right, so presumably all the3711* apps have worked round it...3712*/3713if (!tc->init)3714{3715png_user_transformp tr = png_transform_cast(png_user_transform, *trIn);3716png_row_info row_info;37173718if (tc->sp != tc->dp) /* no interlace */3719{3720memcpy(tc->dp, tc->sp, PNG_TC_ROWBYTES(*tc));3721tc->sp = tc->dp;3722}37233724row_info.width = tc->width;3725row_info.rowbytes = PNG_TC_ROWBYTES(*tc);3726row_info.color_type = png_check_byte(png_ptr,3727PNG_COLOR_TYPE_FROM_FORMAT(tc->format));3728row_info.bit_depth = png_check_byte(png_ptr, tc->bit_depth);3729row_info.channels = png_check_byte(png_ptr,3730PNG_FORMAT_CHANNELS(tc->format));3731row_info.bit_depth = png_check_byte(png_ptr,3732PNG_TC_PIXEL_DEPTH(*tc));37333734/* The user function promises to give us this format: */3735tr->user_fn(png_ptr, &row_info, png_voidcast(png_bytep, tc->dp));3736}3737# undef png_ptr3738}37393740void PNGAPI3741png_set_write_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr3742write_user_transform_fn)3743{37443745if (png_ptr != NULL)3746{3747if (!png_ptr->read_struct)3748{3749png_user_transformp tr = get_user_transform(png_ptr);37503751tr->user_fn = write_user_transform_fn;3752tr->tr.fn = png_do_write_user_transform;3753}37543755else3756png_app_error(png_ptr, "cannot set a write transform on read");3757}3758}3759#endif /* WRITE_USER_TRANSFORM */376037613762