Skip to content

Commit

Permalink
Add --keep-icc-profile and --jpeg-keep-all-metadata #26
Browse files Browse the repository at this point in the history
  • Loading branch information
JayXon committed Dec 4, 2016
1 parent 4aa5b30 commit 866d4ad
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 28 deletions.
20 changes: 15 additions & 5 deletions formats/jpeg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

const uint8_t Jpeg::header_magic[] = { 0xFF, 0xD8, 0xFF };
bool Jpeg::keep_exif_ = false;
bool Jpeg::keep_icc_profile_ = false;
bool Jpeg::keep_all_metadata_ = false;

namespace {

Expand Down Expand Up @@ -51,9 +53,19 @@ size_t Jpeg::Leanify(size_t size_leanified /*= 0*/) {
/* Specify data source for decompression */
jpeg_mem_src(&srcinfo, fp_, size_);

if (keep_exif_) {
if (keep_exif_ || keep_all_metadata_) {
jpeg_save_markers(&srcinfo, JPEG_APP0 + 1, 0xFFFF);
}
if (keep_icc_profile_ || keep_all_metadata_) {
jpeg_save_markers(&srcinfo, JPEG_APP0 + 2, 0xFFFF);
}
if (keep_all_metadata_) {
// Save the rest APPn markers.
for (int i = 3; i < 16; i++)
jpeg_save_markers(&srcinfo, JPEG_APP0 + i, 0xFFFF);
// Save comments.
jpeg_save_markers(&srcinfo, JPEG_COM, 0xFFFF);
}

(void)jpeg_read_header(&srcinfo, true);

Expand All @@ -79,11 +91,9 @@ size_t Jpeg::Leanify(size_t size_leanified /*= 0*/) {
/* Start compressor (note no image data is actually written here) */
jpeg_write_coefficients(&dstinfo, coef_arrays);

if (keep_exif_) {
if (keep_exif_ || keep_icc_profile_ || keep_all_metadata_) {
for (auto marker = srcinfo.marker_list; marker; marker = marker->next) {
if (marker->marker == JPEG_APP0 + 1) {
jpeg_write_marker(&dstinfo, marker->marker, marker->data, marker->data_length);
}
jpeg_write_marker(&dstinfo, marker->marker, marker->data, marker->data_length);
}
}

Expand Down
2 changes: 2 additions & 0 deletions formats/jpeg.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ class Jpeg : public Format {

static const uint8_t header_magic[3];
static bool keep_exif_;
static bool keep_icc_profile_;
static bool keep_all_metadata_;
};

#endif // FORMATS_JPEG_H_
54 changes: 32 additions & 22 deletions formats/png.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ using std::endl;
using std::vector;

const uint8_t Png::header_magic[] = { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A };
bool Png::keep_icc_profile_ = false;

size_t Png::Leanify(size_t size_leanified /*= 0*/) {
// header
Expand Down Expand Up @@ -50,37 +51,44 @@ size_t Png::Leanify(size_t size_leanified /*= 0*/) {
// read chunk type
chunk_type = *(uint32_t*)(p_read + 4);

// judge the case of first letter
// remove all ancillary chunks except tRNS and APNG chunks and npTc
// tRNS has transparency information
if (chunk_type & 0x20) {
if (chunk_type == 0x54414449) {
// save IDAT chunk address
idat_addr = p_write;
}

bool should_remove = [&]() {
// Check the case of first letter, keep all critical chunks.
if ((chunk_type & 0x20) == 0)
return false;

// Remove all ancillary chunks except the following.
switch (chunk_type) {
case 0x4C546361: // acTL APNG
case 0x4C546366: // fcTL APNG
case 0x54416466: // fdAT APNG TODO: use Zopfli to recompress fdAT
case 0x6354706E: // npTc Android 9Patch images (*.9.png)
break;
return false;

case 0x534E5274: // tRNS transparent
// tRNS must be before IDAT according to PNG spec
if (idat_addr == nullptr)
break;
// Fallthrough to remove it
// tRNS must be before IDAT according to PNG spec
return idat_addr != nullptr;
case 0x50434369: // iCCP ICC profile
return !keep_icc_profile_;
default:
if (is_verbose) {
// chunk name
for (int i = 4; i < 8; i++)
cout << static_cast<char>(p_read[i]);

cout << " chunk removed, " << chunk_length << " bytes." << endl;
}
// remove this chunk
p_read += chunk_length;
continue;
return true;
}
} else if (chunk_type == 0x54414449) {
// save IDAT chunk address
idat_addr = p_write;
}();
if (should_remove) {
if (is_verbose) {
// chunk name
for (int i = 4; i < 8; i++)
cout << static_cast<char>(p_read[i]);

cout << " chunk removed, " << chunk_length << " bytes." << endl;
}
// remove this chunk
p_read += chunk_length;
continue;
}

// move this chunk
Expand All @@ -103,6 +111,8 @@ size_t Png::Leanify(size_t size_leanified /*= 0*/) {
zopflipng_options.lossy_transparent = true;
// see the switch above for information about these chunks
zopflipng_options.keepchunks = { "acTL", "fcTL", "fdAT", "npTc" };
if (keep_icc_profile_)
zopflipng_options.keepchunks.push_back("iCCP");
zopflipng_options.num_iterations = iterations;
zopflipng_options.num_iterations_large = iterations;

Expand Down
1 change: 1 addition & 0 deletions formats/png.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class Png : public Format {
size_t Leanify(size_t size_leanified = 0) override;

static const uint8_t header_magic[8];
static bool keep_icc_profile_;
};

#endif // FORMATS_PNG_H_
14 changes: 13 additions & 1 deletion main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "version.h"

#include "formats/jpeg.h"
#include "formats/png.h"

using std::cerr;
using std::cout;
Expand Down Expand Up @@ -85,7 +86,11 @@ void PrintInfo() {
" -f, --fastmode Fast mode, no recompression.\n"
" -q, --quiet No output to stdout.\n"
" -v, --verbose Verbose output.\n"
" --keep-exif Do not remove Exif.\n";
" --keep-exif Do not remove Exif.\n"
" --keep-icc-profile Do not remove ICC profile.\n"
"\n"
"JPEG specific option:\n"
" --jpeg-keep-all-metadata Do not remove any metadata or comments in JPEG.\n";

PauseIfNotTerminal();
}
Expand Down Expand Up @@ -169,6 +174,13 @@ int main(int argc, char* argv[]) {
} else if (STRCMP(argv[i] + j + 1, "keep-exif") == 0) {
j += 9;
Jpeg::keep_exif_ = true;
} else if (STRCMP(argv[i] + j + 1, "keep-icc-profile") == 0) {
j += 16;
Jpeg::keep_icc_profile_ = true;
Png::keep_icc_profile_ = true;
} else if (STRCMP(argv[i] + j + 1, "jpeg-keep-all-metadata") == 0) {
j += 22;
Jpeg::keep_all_metadata_ = true;
} else {
#ifdef _WIN32
char mbs[64] = { 0 };
Expand Down

0 comments on commit 866d4ad

Please sign in to comment.