2 * Copyright (c) 2014, Mathieu Malaterre <mathieu.malaterre@voxxl.com>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 * POSSIBILITY OF SUCH DAMAGE.
28 * Extract all JP2 files contained within a PDF file.
30 * Technically you could simply use mutool, eg:
32 * $ mutool show -be -o obj58.jp2 Bug691816.pdf 58
34 * to extract a given JP2 file from within a PDF
35 * However it happens sometimes that the PDF is itself corrupted, this tools is
36 * a lame PDF parser which only extract stream contained in JPXDecode box
37 * only work on linux since I need memmem function
41 * Add support for other signatures:
43 * obj<</Subtype/Image/Length 110494/Filter/JPXDecode/BitsPerComponent 8/ColorSpace/DeviceRGB/Width 712/Height 1052>>stream
51 int main(int argc, char *argv[])
61 char haystack[BUFLEN];
62 const char needle[] = "JPXDecode";
64 const size_t nlen = strlen( needle );
65 const size_t flen = BUFLEN - nlen;
66 char *fpos = haystack + nlen;
68 if( argc < 2 ) return 1;
72 memset( haystack, 0, nlen );
74 f = fopen( filename, "rb" );
79 nread = fread(fpos, 1, flen, f);
81 ret = memmem( haystack, hlen, needle, nlen);
84 const long cpos = ftell(f);
85 const ptrdiff_t diff = ret - haystack;
87 /*fprintf( stdout, "Found it: %lx\n", (ptrdiff_t)cpos - (ptrdiff_t)hlen + diff);*/
88 offets[c++] = (ptrdiff_t)cpos - (ptrdiff_t)hlen + diff;
90 cont = (nread == flen);
91 memcpy( haystack, haystack + nread, nlen );
96 for( i = 0; i < c; ++i )
100 const int ret = fseek(f, offets[i], SEEK_SET);
102 r = fgets(buffer, sizeof(buffer), f);
104 /*fprintf( stderr, "DEBUG: %s", r );*/
105 s = sscanf(r, "JPXDecode]/Length %d/Width %*d/BitsPerComponent %*d/Height %*d", &len);
107 { // try again harder
108 const int ret = fseek(f, offets[i] - 40, SEEK_SET); // 40 is magic number
110 r = fgets(buffer, sizeof(buffer), f);
112 const char needle2[] = "/Length";
113 char * s2 = strstr(buffer, needle2);
114 s = sscanf(s2, "/Length %d/", &len);
121 sprintf( jp2fn, "%s.%d.jp2", filename, i );
122 jp2 = fopen( jp2fn, "wb" );
123 for( j = 0; j < len; ++j )
126 int ret2 = fputc(v, jp2);
127 assert( ret2 != EOF );
131 /* TODO need to check we reached endstream */
132 r = fgets(buffer, sizeof(buffer), f);
133 fprintf( stderr, "DEBUG: [%s]", r );
134 r = fgets(buffer, sizeof(buffer), f);
135 fprintf( stderr, "DEBUG: [%s]", r );