| OLD | NEW |
| 1 | 1 |
| 2 /* pngwrite.c - general routines to write a PNG file | 2 /* pngwrite.c - general routines to write a PNG file |
| 3 * | 3 * |
| 4 * Last changed in libpng 1.2.52 [November 20, 2014] | 4 * Last changed in libpng 1.2.54 [November 12, 2015] |
| 5 * Copyright (c) 1998-2014 Glenn Randers-Pehrson | 5 * Copyright (c) 1998-2015 Glenn Randers-Pehrson |
| 6 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) | 6 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) |
| 7 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) | 7 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) |
| 8 * | 8 * |
| 9 * This code is released under the libpng license. | 9 * This code is released under the libpng license. |
| 10 * For conditions of distribution and use, see the disclaimer | 10 * For conditions of distribution and use, see the disclaimer |
| 11 * and license in png.h | 11 * and license in png.h |
| 12 */ | 12 */ |
| 13 | 13 |
| 14 /* Get internal access to png.h */ | 14 /* Get internal access to png.h */ |
| 15 #define PNG_INTERNAL | 15 #define PNG_INTERNAL |
| (...skipping 561 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 577 } | 577 } |
| 578 | 578 |
| 579 /* Initialize zbuf - compression buffer */ | 579 /* Initialize zbuf - compression buffer */ |
| 580 png_ptr->zbuf_size = PNG_ZBUF_SIZE; | 580 png_ptr->zbuf_size = PNG_ZBUF_SIZE; |
| 581 png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, | 581 png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, |
| 582 (png_uint_32)png_ptr->zbuf_size); | 582 (png_uint_32)png_ptr->zbuf_size); |
| 583 | 583 |
| 584 png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL, | 584 png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL, |
| 585 png_flush_ptr_NULL); | 585 png_flush_ptr_NULL); |
| 586 | 586 |
| 587 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED | |
| 588 png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT, | |
| 589 1, png_doublep_NULL, png_doublep_NULL); | |
| 590 #endif | |
| 591 | |
| 592 #ifdef PNG_SETJMP_SUPPORTED | 587 #ifdef PNG_SETJMP_SUPPORTED |
| 593 /* Applications that neglect to set up their own setjmp() and then | 588 /* Applications that neglect to set up their own setjmp() and then |
| 594 * encounter a png_error() will longjmp here. Since the jmpbuf is | 589 * encounter a png_error() will longjmp here. Since the jmpbuf is |
| 595 * then meaningless we abort instead of returning. | 590 * then meaningless we abort instead of returning. |
| 596 */ | 591 */ |
| 597 #ifdef USE_FAR_KEYWORD | 592 #ifdef USE_FAR_KEYWORD |
| 598 if (setjmp(jmpbuf)) | 593 if (setjmp(jmpbuf)) |
| 599 PNG_ABORT(); | 594 PNG_ABORT(); |
| 600 png_memcpy(png_ptr->jmpbuf, jmpbuf, png_sizeof(jmp_buf)); | 595 png_memcpy(png_ptr->jmpbuf, jmpbuf, png_sizeof(jmp_buf)); |
| 601 #else | 596 #else |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 724 png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof(jmp_buf)); | 719 png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof(jmp_buf)); |
| 725 #endif | 720 #endif |
| 726 | 721 |
| 727 png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL, | 722 png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL, |
| 728 png_flush_ptr_NULL); | 723 png_flush_ptr_NULL); |
| 729 | 724 |
| 730 /* Initialize zbuf - compression buffer */ | 725 /* Initialize zbuf - compression buffer */ |
| 731 png_ptr->zbuf_size = PNG_ZBUF_SIZE; | 726 png_ptr->zbuf_size = PNG_ZBUF_SIZE; |
| 732 png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, | 727 png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, |
| 733 (png_uint_32)png_ptr->zbuf_size); | 728 (png_uint_32)png_ptr->zbuf_size); |
| 734 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED | |
| 735 png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT, | |
| 736 1, png_doublep_NULL, png_doublep_NULL); | |
| 737 #endif | |
| 738 } | 729 } |
| 739 | 730 |
| 740 /* Write a few rows of image data. If the image is interlaced, | 731 /* Write a few rows of image data. If the image is interlaced, |
| 741 * either you will have to write the 7 sub images, or, if you | 732 * either you will have to write the 7 sub images, or, if you |
| 742 * have called png_set_interlace_handling(), you will have to | 733 * have called png_set_interlace_handling(), you will have to |
| 743 * "write" the image seven times. | 734 * "write" the image seven times. |
| 744 */ | 735 */ |
| 745 void PNGAPI | 736 void PNGAPI |
| 746 png_write_rows(png_structp png_ptr, png_bytepp row, | 737 png_write_rows(png_structp png_ptr, png_bytepp row, |
| 747 png_uint_32 num_rows) | 738 png_uint_32 num_rows) |
| (...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1143 png_free(png_ptr, png_ptr->sub_row); | 1134 png_free(png_ptr, png_ptr->sub_row); |
| 1144 png_free(png_ptr, png_ptr->up_row); | 1135 png_free(png_ptr, png_ptr->up_row); |
| 1145 png_free(png_ptr, png_ptr->avg_row); | 1136 png_free(png_ptr, png_ptr->avg_row); |
| 1146 png_free(png_ptr, png_ptr->paeth_row); | 1137 png_free(png_ptr, png_ptr->paeth_row); |
| 1147 #endif | 1138 #endif |
| 1148 | 1139 |
| 1149 #ifdef PNG_TIME_RFC1123_SUPPORTED | 1140 #ifdef PNG_TIME_RFC1123_SUPPORTED |
| 1150 png_free(png_ptr, png_ptr->time_buffer); | 1141 png_free(png_ptr, png_ptr->time_buffer); |
| 1151 #endif | 1142 #endif |
| 1152 | 1143 |
| 1153 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED | |
| 1154 png_free(png_ptr, png_ptr->prev_filters); | |
| 1155 png_free(png_ptr, png_ptr->filter_weights); | |
| 1156 png_free(png_ptr, png_ptr->inv_filter_weights); | |
| 1157 png_free(png_ptr, png_ptr->filter_costs); | |
| 1158 png_free(png_ptr, png_ptr->inv_filter_costs); | |
| 1159 #endif | |
| 1160 | |
| 1161 #ifdef PNG_SETJMP_SUPPORTED | 1144 #ifdef PNG_SETJMP_SUPPORTED |
| 1162 /* Reset structure */ | 1145 /* Reset structure */ |
| 1163 png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof(jmp_buf)); | 1146 png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof(jmp_buf)); |
| 1164 #endif | 1147 #endif |
| 1165 | 1148 |
| 1166 error_fn = png_ptr->error_fn; | 1149 error_fn = png_ptr->error_fn; |
| 1167 warning_fn = png_ptr->warning_fn; | 1150 warning_fn = png_ptr->warning_fn; |
| 1168 error_ptr = png_ptr->error_ptr; | 1151 error_ptr = png_ptr->error_ptr; |
| 1169 #ifdef PNG_USER_MEM_SUPPORTED | 1152 #ifdef PNG_USER_MEM_SUPPORTED |
| 1170 free_fn = png_ptr->free_fn; | 1153 free_fn = png_ptr->free_fn; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1194 return; | 1177 return; |
| 1195 #ifdef PNG_MNG_FEATURES_SUPPORTED | 1178 #ifdef PNG_MNG_FEATURES_SUPPORTED |
| 1196 if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && | 1179 if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && |
| 1197 (method == PNG_INTRAPIXEL_DIFFERENCING)) | 1180 (method == PNG_INTRAPIXEL_DIFFERENCING)) |
| 1198 method = PNG_FILTER_TYPE_BASE; | 1181 method = PNG_FILTER_TYPE_BASE; |
| 1199 #endif | 1182 #endif |
| 1200 if (method == PNG_FILTER_TYPE_BASE) | 1183 if (method == PNG_FILTER_TYPE_BASE) |
| 1201 { | 1184 { |
| 1202 switch (filters & (PNG_ALL_FILTERS | 0x07)) | 1185 switch (filters & (PNG_ALL_FILTERS | 0x07)) |
| 1203 { | 1186 { |
| 1187 case PNG_FILTER_VALUE_NONE: |
| 1188 png_ptr->do_filter = PNG_FILTER_NONE; break; |
| 1204 #ifdef PNG_WRITE_FILTER_SUPPORTED | 1189 #ifdef PNG_WRITE_FILTER_SUPPORTED |
| 1205 case 5: | 1190 case 5: |
| 1206 case 6: | 1191 case 6: |
| 1207 case 7: png_warning(png_ptr, "Unknown row filter for method 0"); | 1192 case 7: png_warning(png_ptr, "Unknown row filter for method 0"); |
| 1208 #endif /* PNG_WRITE_FILTER_SUPPORTED */ | 1193 break; |
| 1209 case PNG_FILTER_VALUE_NONE: | |
| 1210 png_ptr->do_filter = PNG_FILTER_NONE; break; | |
| 1211 #ifdef PNG_WRITE_FILTER_SUPPORTED | |
| 1212 case PNG_FILTER_VALUE_SUB: | 1194 case PNG_FILTER_VALUE_SUB: |
| 1213 png_ptr->do_filter = PNG_FILTER_SUB; break; | 1195 png_ptr->do_filter = PNG_FILTER_SUB; break; |
| 1214 case PNG_FILTER_VALUE_UP: | 1196 case PNG_FILTER_VALUE_UP: |
| 1215 png_ptr->do_filter = PNG_FILTER_UP; break; | 1197 png_ptr->do_filter = PNG_FILTER_UP; break; |
| 1216 case PNG_FILTER_VALUE_AVG: | 1198 case PNG_FILTER_VALUE_AVG: |
| 1217 png_ptr->do_filter = PNG_FILTER_AVG; break; | 1199 png_ptr->do_filter = PNG_FILTER_AVG; break; |
| 1218 case PNG_FILTER_VALUE_PAETH: | 1200 case PNG_FILTER_VALUE_PAETH: |
| 1219 png_ptr->do_filter = PNG_FILTER_PAETH; break; | 1201 png_ptr->do_filter = PNG_FILTER_PAETH; break; |
| 1220 default: png_ptr->do_filter = (png_byte)filters; break; | 1202 default: png_ptr->do_filter = (png_byte)filters; break; |
| 1221 #else | 1203 #else |
| 1222 default: png_warning(png_ptr, "Unknown row filter for method 0"); | 1204 default: png_warning(png_ptr, "Unknown row filter for method 0"); |
| 1205 break; |
| 1223 #endif /* PNG_WRITE_FILTER_SUPPORTED */ | 1206 #endif /* PNG_WRITE_FILTER_SUPPORTED */ |
| 1224 } | 1207 } |
| 1225 | 1208 |
| 1226 /* If we have allocated the row_buf, this means we have already started | 1209 /* If we have allocated the row_buf, this means we have already started |
| 1227 * with the image and we should have allocated all of the filter buffers | 1210 * with the image and we should have allocated all of the filter buffers |
| 1228 * that have been selected. If prev_row isn't already allocated, then | 1211 * that have been selected. If prev_row isn't already allocated, then |
| 1229 * it is too late to start using the filters that need it, since we | 1212 * it is too late to start using the filters that need it, since we |
| 1230 * will be missing the data in the previous row. If an application | 1213 * will be missing the data in the previous row. If an application |
| 1231 * wants to start and stop using particular filters during compression, | 1214 * wants to start and stop using particular filters during compression, |
| 1232 * it should start out with all of the filters, and then add and | 1215 * it should start out with all of the filters, and then add and |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1303 * question as to whether it can be improved upon by trying to keep the | 1286 * question as to whether it can be improved upon by trying to keep the |
| 1304 * filtered data going to zlib more consistent, hopefully resulting in | 1287 * filtered data going to zlib more consistent, hopefully resulting in |
| 1305 * better compression. | 1288 * better compression. |
| 1306 */ | 1289 */ |
| 1307 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* GRR 970116 */ | 1290 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* GRR 970116 */ |
| 1308 void PNGAPI | 1291 void PNGAPI |
| 1309 png_set_filter_heuristics(png_structp png_ptr, int heuristic_method, | 1292 png_set_filter_heuristics(png_structp png_ptr, int heuristic_method, |
| 1310 int num_weights, png_doublep filter_weights, | 1293 int num_weights, png_doublep filter_weights, |
| 1311 png_doublep filter_costs) | 1294 png_doublep filter_costs) |
| 1312 { | 1295 { |
| 1313 int i; | 1296 PNG_UNUSED(png_ptr) |
| 1314 | 1297 PNG_UNUSED(heuristic_method) |
| 1315 png_debug(1, "in png_set_filter_heuristics"); | 1298 PNG_UNUSED(num_weights) |
| 1316 | 1299 PNG_UNUSED(filter_weights) |
| 1317 if (png_ptr == NULL) | 1300 PNG_UNUSED(filter_costs) |
| 1318 return; | |
| 1319 if (heuristic_method >= PNG_FILTER_HEURISTIC_LAST) | |
| 1320 { | |
| 1321 png_warning(png_ptr, "Unknown filter heuristic method"); | |
| 1322 return; | |
| 1323 } | |
| 1324 | |
| 1325 if (heuristic_method == PNG_FILTER_HEURISTIC_DEFAULT) | |
| 1326 { | |
| 1327 heuristic_method = PNG_FILTER_HEURISTIC_UNWEIGHTED; | |
| 1328 } | |
| 1329 | |
| 1330 if (num_weights < 0 || filter_weights == NULL || | |
| 1331 heuristic_method == PNG_FILTER_HEURISTIC_UNWEIGHTED) | |
| 1332 { | |
| 1333 num_weights = 0; | |
| 1334 } | |
| 1335 | |
| 1336 png_ptr->num_prev_filters = (png_byte)num_weights; | |
| 1337 png_ptr->heuristic_method = (png_byte)heuristic_method; | |
| 1338 | |
| 1339 if (num_weights > 0) | |
| 1340 { | |
| 1341 if (png_ptr->prev_filters == NULL) | |
| 1342 { | |
| 1343 png_ptr->prev_filters = (png_bytep)png_malloc(png_ptr, | |
| 1344 (png_uint_32)(png_sizeof(png_byte) * num_weights)); | |
| 1345 | |
| 1346 /* To make sure that the weighting starts out fairly */ | |
| 1347 for (i = 0; i < num_weights; i++) | |
| 1348 { | |
| 1349 png_ptr->prev_filters[i] = 255; | |
| 1350 } | |
| 1351 } | |
| 1352 | |
| 1353 if (png_ptr->filter_weights == NULL) | |
| 1354 { | |
| 1355 png_ptr->filter_weights = (png_uint_16p)png_malloc(png_ptr, | |
| 1356 (png_uint_32)(png_sizeof(png_uint_16) * num_weights)); | |
| 1357 | |
| 1358 png_ptr->inv_filter_weights = (png_uint_16p)png_malloc(png_ptr, | |
| 1359 (png_uint_32)(png_sizeof(png_uint_16) * num_weights)); | |
| 1360 for (i = 0; i < num_weights; i++) | |
| 1361 { | |
| 1362 png_ptr->inv_filter_weights[i] = | |
| 1363 png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; | |
| 1364 } | |
| 1365 } | |
| 1366 | |
| 1367 for (i = 0; i < num_weights; i++) | |
| 1368 { | |
| 1369 if (filter_weights[i] < 0.0) | |
| 1370 { | |
| 1371 png_ptr->inv_filter_weights[i] = | |
| 1372 png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; | |
| 1373 } | |
| 1374 else | |
| 1375 { | |
| 1376 png_ptr->inv_filter_weights[i] = | |
| 1377 (png_uint_16)((double)PNG_WEIGHT_FACTOR*filter_weights[i]+0.5); | |
| 1378 png_ptr->filter_weights[i] = | |
| 1379 (png_uint_16)((double)PNG_WEIGHT_FACTOR/filter_weights[i]+0.5); | |
| 1380 } | |
| 1381 } | |
| 1382 } | |
| 1383 | |
| 1384 /* If, in the future, there are other filter methods, this would | |
| 1385 * need to be based on png_ptr->filter. | |
| 1386 */ | |
| 1387 if (png_ptr->filter_costs == NULL) | |
| 1388 { | |
| 1389 png_ptr->filter_costs = (png_uint_16p)png_malloc(png_ptr, | |
| 1390 (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST)); | |
| 1391 | |
| 1392 png_ptr->inv_filter_costs = (png_uint_16p)png_malloc(png_ptr, | |
| 1393 (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST)); | |
| 1394 | |
| 1395 for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) | |
| 1396 { | |
| 1397 png_ptr->inv_filter_costs[i] = | |
| 1398 png_ptr->filter_costs[i] = PNG_COST_FACTOR; | |
| 1399 } | |
| 1400 } | |
| 1401 | |
| 1402 /* Here is where we set the relative costs of the different filters. We | |
| 1403 * should take the desired compression level into account when setting | |
| 1404 * the costs, so that Paeth, for instance, has a high relative cost at low | |
| 1405 * compression levels, while it has a lower relative cost at higher | |
| 1406 * compression settings. The filter types are in order of increasing | |
| 1407 * relative cost, so it would be possible to do this with an algorithm. | |
| 1408 */ | |
| 1409 for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) | |
| 1410 { | |
| 1411 if (filter_costs == NULL || filter_costs[i] < 0.0) | |
| 1412 { | |
| 1413 png_ptr->inv_filter_costs[i] = | |
| 1414 png_ptr->filter_costs[i] = PNG_COST_FACTOR; | |
| 1415 } | |
| 1416 else if (filter_costs[i] >= 1.0) | |
| 1417 { | |
| 1418 png_ptr->inv_filter_costs[i] = | |
| 1419 (png_uint_16)((double)PNG_COST_FACTOR / filter_costs[i] + 0.5); | |
| 1420 png_ptr->filter_costs[i] = | |
| 1421 (png_uint_16)((double)PNG_COST_FACTOR * filter_costs[i] + 0.5); | |
| 1422 } | |
| 1423 } | |
| 1424 } | 1301 } |
| 1425 #endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ | 1302 #endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ |
| 1426 | 1303 |
| 1427 void PNGAPI | 1304 void PNGAPI |
| 1428 png_set_compression_level(png_structp png_ptr, int level) | 1305 png_set_compression_level(png_structp png_ptr, int level) |
| 1429 { | 1306 { |
| 1430 png_debug(1, "in png_set_compression_level"); | 1307 png_debug(1, "in png_set_compression_level"); |
| 1431 | 1308 |
| 1432 if (png_ptr == NULL) | 1309 if (png_ptr == NULL) |
| 1433 return; | 1310 return; |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1593 png_write_image(png_ptr, info_ptr->row_pointers); | 1470 png_write_image(png_ptr, info_ptr->row_pointers); |
| 1594 | 1471 |
| 1595 /* It is REQUIRED to call this to finish writing the rest of the file */ | 1472 /* It is REQUIRED to call this to finish writing the rest of the file */ |
| 1596 png_write_end(png_ptr, info_ptr); | 1473 png_write_end(png_ptr, info_ptr); |
| 1597 | 1474 |
| 1598 PNG_UNUSED(transforms) /* Quiet compiler warnings */ | 1475 PNG_UNUSED(transforms) /* Quiet compiler warnings */ |
| 1599 PNG_UNUSED(params) | 1476 PNG_UNUSED(params) |
| 1600 } | 1477 } |
| 1601 #endif | 1478 #endif |
| 1602 #endif /* PNG_WRITE_SUPPORTED */ | 1479 #endif /* PNG_WRITE_SUPPORTED */ |
| OLD | NEW |