VirtualBox

Ignore:
Timestamp:
Jan 16, 2025 1:09:46 PM (5 weeks ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
166977
Message:

libpng-1.6.45: Applied and adjusted our libpng changes to 1.6.45. bugref:8515

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/libs/libpng-1.6.45/png.c

    r105469 r107813  
    1 
    21/* png.c - location for general purpose libpng functions
    32 *
    4  * Copyright (c) 2018-2024 Cosmin Truta
     3 * Copyright (c) 2018-2025 Cosmin Truta
    54 * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
    65 * Copyright (c) 1996-1997 Andreas Dilger
     
    1514
    1615/* Generate a compiler error if there is an old png.h in the search path. */
    17 typedef png_libpng_version_1_6_43 Your_png_h_is_not_version_1_6_43;
     16typedef png_libpng_version_1_6_45 Your_png_h_is_not_version_1_6_45;
    1817
    1918/* Tells libpng that we have already handled the first "num_bytes" bytes
     
    795794#else
    796795   return PNG_STRING_NEWLINE \
    797       "libpng version 1.6.43" PNG_STRING_NEWLINE \
    798       "Copyright (c) 2018-2024 Cosmin Truta" PNG_STRING_NEWLINE \
     796      "libpng version 1.6.45" PNG_STRING_NEWLINE \
     797      "Copyright (c) 2018-2025 Cosmin Truta" PNG_STRING_NEWLINE \
    799798      "Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson" \
    800799      PNG_STRING_NEWLINE \
     
    12041203
    12051204#ifdef PNG_COLORSPACE_SUPPORTED
     1205static png_int_32
     1206png_fp_add(png_int_32 addend0, png_int_32 addend1, int *error)
     1207{
     1208   /* Safely add two fixed point values setting an error flag and returning 0.5
     1209    * on overflow.
     1210    * IMPLEMENTATION NOTE: ANSI requires signed overflow not to occur, therefore
     1211    * relying on addition of two positive values producing a negative one is not
     1212    * safe.
     1213    */
     1214   if (addend0 > 0)
     1215   {
     1216      if (0x7fffffff - addend0 >= addend1)
     1217         return addend0+addend1;
     1218   }
     1219   else if (addend0 < 0)
     1220   {
     1221      if (-0x7fffffff - addend0 <= addend1)
     1222         return addend0+addend1;
     1223   }
     1224   else
     1225      return addend1;
     1226
     1227   *error = 1;
     1228   return PNG_FP_1/2;
     1229}
     1230
     1231static png_int_32
     1232png_fp_sub(png_int_32 addend0, png_int_32 addend1, int *error)
     1233{
     1234   /* As above but calculate addend0-addend1. */
     1235   if (addend1 > 0)
     1236   {
     1237      if (-0x7fffffff + addend1 <= addend0)
     1238         return addend0-addend1;
     1239   }
     1240   else if (addend1 < 0)
     1241   {
     1242      if (0x7fffffff + addend1 >= addend0)
     1243         return addend0-addend1;
     1244   }
     1245   else
     1246      return addend0;
     1247
     1248   *error = 1;
     1249   return PNG_FP_1/2;
     1250}
     1251
     1252static int
     1253png_safe_add(png_int_32 *addend0_and_result, png_int_32 addend1,
     1254      png_int_32 addend2)
     1255{
     1256   /* Safely add three integers.  Returns 0 on success, 1 on overflow.  Does not
     1257    * set the result on overflow.
     1258    */
     1259   int error = 0;
     1260   int result = png_fp_add(*addend0_and_result,
     1261                           png_fp_add(addend1, addend2, &error),
     1262                           &error);
     1263   if (!error) *addend0_and_result = result;
     1264   return error;
     1265}
     1266
    12061267/* Added at libpng-1.5.5 to support read and write of true CIEXYZ values for
    12071268 * cHRM, as opposed to using chromaticities.  These internal APIs return
     
    12121273png_xy_from_XYZ(png_xy *xy, const png_XYZ *XYZ)
    12131274{
    1214    png_int_32 d, dwhite, whiteX, whiteY;
    1215 
    1216    d = XYZ->red_X + XYZ->red_Y + XYZ->red_Z;
    1217    if (png_muldiv(&xy->redx, XYZ->red_X, PNG_FP_1, d) == 0)
     1275   png_int_32 d, dred, dgreen, dblue, dwhite, whiteX, whiteY;
     1276
     1277   /* 'd' in each of the blocks below is just X+Y+Z for each component,
     1278    * x, y and z are X,Y,Z/(X+Y+Z).
     1279    */
     1280   d = XYZ->red_X;
     1281   if (png_safe_add(&d, XYZ->red_Y, XYZ->red_Z))
    12181282      return 1;
    1219    if (png_muldiv(&xy->redy, XYZ->red_Y, PNG_FP_1, d) == 0)
     1283   dred = d;
     1284   if (png_muldiv(&xy->redx, XYZ->red_X, PNG_FP_1, dred) == 0)
     1285      return 1;
     1286   if (png_muldiv(&xy->redy, XYZ->red_Y, PNG_FP_1, dred) == 0)
     1287      return 1;
     1288
     1289   d = XYZ->green_X;
     1290   if (png_safe_add(&d, XYZ->green_Y, XYZ->green_Z))
     1291      return 1;
     1292   dgreen = d;
     1293   if (png_muldiv(&xy->greenx, XYZ->green_X, PNG_FP_1, dgreen) == 0)
     1294      return 1;
     1295   if (png_muldiv(&xy->greeny, XYZ->green_Y, PNG_FP_1, dgreen) == 0)
     1296      return 1;
     1297
     1298   d = XYZ->blue_X;
     1299   if (png_safe_add(&d, XYZ->blue_Y, XYZ->blue_Z))
     1300      return 1;
     1301   dblue = d;
     1302   if (png_muldiv(&xy->bluex, XYZ->blue_X, PNG_FP_1, dblue) == 0)
     1303      return 1;
     1304   if (png_muldiv(&xy->bluey, XYZ->blue_Y, PNG_FP_1, dblue) == 0)
     1305      return 1;
     1306
     1307   /* The reference white is simply the sum of the end-point (X,Y,Z) vectors so
     1308    * the fillowing calculates (X+Y+Z) of the reference white (media white,
     1309    * encoding white) itself:
     1310    */
     1311   d = dblue;
     1312   if (png_safe_add(&d, dred, dgreen))
    12201313      return 1;
    12211314   dwhite = d;
    1222    whiteX = XYZ->red_X;
    1223    whiteY = XYZ->red_Y;
    1224 
    1225    d = XYZ->green_X + XYZ->green_Y + XYZ->green_Z;
    1226    if (png_muldiv(&xy->greenx, XYZ->green_X, PNG_FP_1, d) == 0)
     1315
     1316   /* Find the white X,Y values from the sum of the red, green and blue X,Y
     1317    * values.
     1318    */
     1319   d = XYZ->red_X;
     1320   if (png_safe_add(&d, XYZ->green_X, XYZ->blue_X))
    12271321      return 1;
    1228    if (png_muldiv(&xy->greeny, XYZ->green_Y, PNG_FP_1, d) == 0)
     1322   whiteX = d;
     1323
     1324   d = XYZ->red_Y;
     1325   if (png_safe_add(&d, XYZ->green_Y, XYZ->blue_Y))
    12291326      return 1;
    1230    dwhite += d;
    1231    whiteX += XYZ->green_X;
    1232    whiteY += XYZ->green_Y;
    1233 
    1234    d = XYZ->blue_X + XYZ->blue_Y + XYZ->blue_Z;
    1235    if (png_muldiv(&xy->bluex, XYZ->blue_X, PNG_FP_1, d) == 0)
    1236       return 1;
    1237    if (png_muldiv(&xy->bluey, XYZ->blue_Y, PNG_FP_1, d) == 0)
    1238       return 1;
    1239    dwhite += d;
    1240    whiteX += XYZ->blue_X;
    1241    whiteY += XYZ->blue_Y;
    1242 
    1243    /* The reference white is simply the sum of the end-point (X,Y,Z) vectors,
    1244     * thus:
    1245     */
     1327   whiteY = d;
     1328
    12461329   if (png_muldiv(&xy->whitex, whiteX, PNG_FP_1, dwhite) == 0)
    12471330      return 1;
     
    12621345    * points, but they are used to cover the possible colors).  We check
    12631346    * xy->whitey against 5, not 0, to avoid a possible integer overflow.
    1264     */
    1265    if (xy->redx   < 0 || xy->redx > PNG_FP_1) return 1;
    1266    if (xy->redy   < 0 || xy->redy > PNG_FP_1-xy->redx) return 1;
    1267    if (xy->greenx < 0 || xy->greenx > PNG_FP_1) return 1;
    1268    if (xy->greeny < 0 || xy->greeny > PNG_FP_1-xy->greenx) return 1;
    1269    if (xy->bluex  < 0 || xy->bluex > PNG_FP_1) return 1;
    1270    if (xy->bluey  < 0 || xy->bluey > PNG_FP_1-xy->bluex) return 1;
    1271    if (xy->whitex < 0 || xy->whitex > PNG_FP_1) return 1;
    1272    if (xy->whitey < 5 || xy->whitey > PNG_FP_1-xy->whitex) return 1;
     1347    *
     1348    * The limits here will *not* accept ACES AP0, where bluey is -7700
     1349    * (-0.0770) because the PNG spec itself requires the xy values to be
     1350    * unsigned.  whitey is also required to be 5 or more to avoid overflow.
     1351    *
     1352    * Instead the upper limits have been relaxed to accomodate ACES AP1 where
     1353    * redz ends up as -600 (-0.006).  ProPhotoRGB was already "in range."
     1354    * The new limit accomodates the AP0 and AP1 ranges for z but not AP0 redy.
     1355    */
     1356   const png_fixed_point fpLimit = PNG_FP_1+(PNG_FP_1/10);
     1357   if (xy->redx   < 0 || xy->redx > fpLimit) return 1;
     1358   if (xy->redy   < 0 || xy->redy > fpLimit-xy->redx) return 1;
     1359   if (xy->greenx < 0 || xy->greenx > fpLimit) return 1;
     1360   if (xy->greeny < 0 || xy->greeny > fpLimit-xy->greenx) return 1;
     1361   if (xy->bluex  < 0 || xy->bluex > fpLimit) return 1;
     1362   if (xy->bluey  < 0 || xy->bluey > fpLimit-xy->bluex) return 1;
     1363   if (xy->whitex < 0 || xy->whitex > fpLimit) return 1;
     1364   if (xy->whitey < 5 || xy->whitey > fpLimit-xy->whitex) return 1;
    12731365
    12741366   /* The reverse calculation is more difficult because the original tristimulus
     
    14151507    *
    14161508    * Accuracy:
    1417     * The input values have 5 decimal digits of accuracy.  The values are all in
    1418     * the range 0 < value < 1, so simple products are in the same range but may
    1419     * need up to 10 decimal digits to preserve the original precision and avoid
    1420     * underflow.  Because we are using a 32-bit signed representation we cannot
    1421     * match this; the best is a little over 9 decimal digits, less than 10.
     1509    * The input values have 5 decimal digits of accuracy.
     1510    *
     1511    * In the previous implementation the values were all in the range 0 < value
     1512    * < 1, so simple products are in the same range but may need up to 10
     1513    * decimal digits to preserve the original precision and avoid underflow.
     1514    * Because we are using a 32-bit signed representation we cannot match this;
     1515    * the best is a little over 9 decimal digits, less than 10.
     1516    *
     1517    * This range has now been extended to allow values up to 1.1, or 110,000 in
     1518    * fixed point.
    14221519    *
    14231520    * The approach used here is to preserve the maximum precision within the
    14241521    * signed representation.  Because the red-scale calculation above uses the
    1425     * difference between two products of values that must be in the range -1..+1
    1426     * it is sufficient to divide the product by 7; ceil(100,000/32767*2).  The
    1427     * factor is irrelevant in the calculation because it is applied to both
    1428     * numerator and denominator.
     1522    * difference between two products of values that must be in the range
     1523    * -1.1..+1.1 it is sufficient to divide the product by 8;
     1524    * ceil(121,000/32767*2).  The factor is irrelevant in the calculation
     1525    * because it is applied to both numerator and denominator.
    14291526    *
    14301527    * Note that the values of the differences of the products of the
     
    14481545    *    0.258728243040113 0.724682314948566 0.016589442011321
    14491546    */
    1450    /* By the argument, above overflow should be impossible here. The return
    1451     * value of 2 indicates an internal error to the caller.
    1452     */
    1453    if (png_muldiv(&left, xy->greenx-xy->bluex, xy->redy - xy->bluey, 7) == 0)
    1454       return 2;
    1455    if (png_muldiv(&right, xy->greeny-xy->bluey, xy->redx - xy->bluex, 7) == 0)
    1456       return 2;
    1457    denominator = left - right;
     1547   int error = 0;
     1548
     1549   /* By the argument above overflow should be impossible here, however the
     1550    * code now simply returns a failure code.  The xy subtracts in the arguments
     1551    * to png_muldiv are *not* checked for overflow because the checks at the
     1552    * start guarantee they are in the range 0..110000 and png_fixed_point is a
     1553    * 32-bit signed number.
     1554    */
     1555   if (png_muldiv(&left, xy->greenx-xy->bluex, xy->redy - xy->bluey, 8) == 0)
     1556      return 1;
     1557   if (png_muldiv(&right, xy->greeny-xy->bluey, xy->redx - xy->bluex, 8) == 0)
     1558      return 1;
     1559   denominator = png_fp_sub(left, right, &error);
     1560   if (error) return 1;
    14581561
    14591562   /* Now find the red numerator. */
    1460    if (png_muldiv(&left, xy->greenx-xy->bluex, xy->whitey-xy->bluey, 7) == 0)
    1461       return 2;
    1462    if (png_muldiv(&right, xy->greeny-xy->bluey, xy->whitex-xy->bluex, 7) == 0)
    1463       return 2;
     1563   if (png_muldiv(&left, xy->greenx-xy->bluex, xy->whitey-xy->bluey, 8) == 0)
     1564      return 1;
     1565   if (png_muldiv(&right, xy->greeny-xy->bluey, xy->whitex-xy->bluex, 8) == 0)
     1566      return 1;
    14641567
    14651568   /* Overflow is possible here and it indicates an extreme set of PNG cHRM
     
    14681571    * into the denominator, which tends to produce a small number.
    14691572    */
    1470    if (png_muldiv(&red_inverse, xy->whitey, denominator, left-right) == 0 ||
     1573   if (png_muldiv(&red_inverse, xy->whitey, denominator,
     1574                  png_fp_sub(left, right, &error)) == 0 || error ||
    14711575       red_inverse <= xy->whitey /* r+g+b scales = white scale */)
    14721576      return 1;
    14731577
    14741578   /* Similarly for green_inverse: */
    1475    if (png_muldiv(&left, xy->redy-xy->bluey, xy->whitex-xy->bluex, 7) == 0)
    1476       return 2;
    1477    if (png_muldiv(&right, xy->redx-xy->bluex, xy->whitey-xy->bluey, 7) == 0)
    1478       return 2;
    1479    if (png_muldiv(&green_inverse, xy->whitey, denominator, left-right) == 0 ||
     1579   if (png_muldiv(&left, xy->redy-xy->bluey, xy->whitex-xy->bluex, 8) == 0)
     1580      return 1;
     1581   if (png_muldiv(&right, xy->redx-xy->bluex, xy->whitey-xy->bluey, 8) == 0)
     1582      return 1;
     1583   if (png_muldiv(&green_inverse, xy->whitey, denominator,
     1584                  png_fp_sub(left, right, &error)) == 0 || error ||
    14801585       green_inverse <= xy->whitey)
    14811586      return 1;
     
    14841589    * can still produce 0 for extreme cHRM values.
    14851590    */
    1486    blue_scale = png_reciprocal(xy->whitey) - png_reciprocal(red_inverse) -
    1487        png_reciprocal(green_inverse);
    1488    if (blue_scale <= 0)
     1591   blue_scale = png_fp_sub(png_fp_sub(png_reciprocal(xy->whitey),
     1592                                      png_reciprocal(red_inverse), &error),
     1593                           png_reciprocal(green_inverse), &error);
     1594   if (error || blue_scale <= 0)
    14891595      return 1;
    14901596
    14911597
    1492    /* And fill in the png_XYZ: */
     1598   /* And fill in the png_XYZ.  Again the subtracts are safe because of the
     1599    * checks on the xy values at the start (the subtracts just calculate the
     1600    * corresponding z values.)
     1601    */
    14931602   if (png_muldiv(&XYZ->red_X, xy->redx, PNG_FP_1, red_inverse) == 0)
    14941603      return 1;
     
    15211630png_XYZ_normalize(png_XYZ *XYZ)
    15221631{
    1523    png_int_32 Y;
    1524 
    1525    if (XYZ->red_Y < 0 || XYZ->green_Y < 0 || XYZ->blue_Y < 0 ||
    1526       XYZ->red_X < 0 || XYZ->green_X < 0 || XYZ->blue_X < 0 ||
    1527       XYZ->red_Z < 0 || XYZ->green_Z < 0 || XYZ->blue_Z < 0)
     1632   png_int_32 Y, Ytemp;
     1633
     1634   /* Normalize by scaling so the sum of the end-point Y values is PNG_FP_1. */
     1635   Ytemp = XYZ->red_Y;
     1636   if (png_safe_add(&Ytemp, XYZ->green_Y, XYZ->blue_Y))
    15281637      return 1;
    15291638
    1530    /* Normalize by scaling so the sum of the end-point Y values is PNG_FP_1.
    1531     * IMPLEMENTATION NOTE: ANSI requires signed overflow not to occur, therefore
    1532     * relying on addition of two positive values producing a negative one is not
    1533     * safe.
    1534     */
    1535    Y = XYZ->red_Y;
    1536    if (0x7fffffff - Y < XYZ->green_X)
    1537       return 1;
    1538    Y += XYZ->green_Y;
    1539    if (0x7fffffff - Y < XYZ->blue_X)
    1540       return 1;
    1541    Y += XYZ->blue_Y;
     1639   Y = Ytemp;
    15421640
    15431641   if (Y != PNG_FP_1)
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette