Changeset 107813 in vbox for trunk/src/libs/libpng-1.6.45/png.c
- Timestamp:
- Jan 16, 2025 1:09:46 PM (5 weeks ago)
- svn:sync-xref-src-repo-rev:
- 166977
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/libs/libpng-1.6.45/png.c
r105469 r107813 1 2 1 /* png.c - location for general purpose libpng functions 3 2 * 4 * Copyright (c) 2018-202 4Cosmin Truta3 * Copyright (c) 2018-2025 Cosmin Truta 5 4 * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson 6 5 * Copyright (c) 1996-1997 Andreas Dilger … … 15 14 16 15 /* Generate a compiler error if there is an old png.h in the search path. */ 17 typedef png_libpng_version_1_6_4 3 Your_png_h_is_not_version_1_6_43;16 typedef png_libpng_version_1_6_45 Your_png_h_is_not_version_1_6_45; 18 17 19 18 /* Tells libpng that we have already handled the first "num_bytes" bytes … … 795 794 #else 796 795 return PNG_STRING_NEWLINE \ 797 "libpng version 1.6.4 3" PNG_STRING_NEWLINE \798 "Copyright (c) 2018-202 4Cosmin Truta" PNG_STRING_NEWLINE \796 "libpng version 1.6.45" PNG_STRING_NEWLINE \ 797 "Copyright (c) 2018-2025 Cosmin Truta" PNG_STRING_NEWLINE \ 799 798 "Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson" \ 800 799 PNG_STRING_NEWLINE \ … … 1204 1203 1205 1204 #ifdef PNG_COLORSPACE_SUPPORTED 1205 static png_int_32 1206 png_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 1231 static png_int_32 1232 png_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 1252 static int 1253 png_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 1206 1267 /* Added at libpng-1.5.5 to support read and write of true CIEXYZ values for 1207 1268 * cHRM, as opposed to using chromaticities. These internal APIs return … … 1212 1273 png_xy_from_XYZ(png_xy *xy, const png_XYZ *XYZ) 1213 1274 { 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)) 1218 1282 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)) 1220 1313 return 1; 1221 1314 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)) 1227 1321 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)) 1229 1326 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 1246 1329 if (png_muldiv(&xy->whitex, whiteX, PNG_FP_1, dwhite) == 0) 1247 1330 return 1; … … 1262 1345 * points, but they are used to cover the possible colors). We check 1263 1346 * 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; 1273 1365 1274 1366 /* The reverse calculation is more difficult because the original tristimulus … … 1415 1507 * 1416 1508 * 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. 1422 1519 * 1423 1520 * The approach used here is to preserve the maximum precision within the 1424 1521 * signed representation. Because the red-scale calculation above uses the 1425 * difference between two products of values that must be in the range -1..+11426 * it is sufficient to divide the product by 7; ceil(100,000/32767*2). The1427 * factor is irrelevant in the calculation because it is applied to both1428 * 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. 1429 1526 * 1430 1527 * Note that the values of the differences of the products of the … … 1448 1545 * 0.258728243040113 0.724682314948566 0.016589442011321 1449 1546 */ 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; 1458 1561 1459 1562 /* 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; 1464 1567 1465 1568 /* Overflow is possible here and it indicates an extreme set of PNG cHRM … … 1468 1571 * into the denominator, which tends to produce a small number. 1469 1572 */ 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 || 1471 1575 red_inverse <= xy->whitey /* r+g+b scales = white scale */) 1472 1576 return 1; 1473 1577 1474 1578 /* 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 || 1480 1585 green_inverse <= xy->whitey) 1481 1586 return 1; … … 1484 1589 * can still produce 0 for extreme cHRM values. 1485 1590 */ 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) 1489 1595 return 1; 1490 1596 1491 1597 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 */ 1493 1602 if (png_muldiv(&XYZ->red_X, xy->redx, PNG_FP_1, red_inverse) == 0) 1494 1603 return 1; … … 1521 1630 png_XYZ_normalize(png_XYZ *XYZ) 1522 1631 { 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)) 1528 1637 return 1; 1529 1638 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; 1542 1640 1543 1641 if (Y != PNG_FP_1)
Note:
See TracChangeset
for help on using the changeset viewer.