Merge pull request #1235 from rouault/imf
[openjpeg.git] / tests / pdf2jp2.c
1 /*
2  * Copyright (c) 2014, Mathieu Malaterre <mathieu.malaterre@voxxl.com>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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.
13  *
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.
25  */
26
27 /*
28  * Extract all JP2 files contained within a PDF file.
29  *
30  * Technically you could simply use mutool, eg:
31  *
32  * $ mutool show -be -o obj58.jp2 Bug691816.pdf 58
33  *
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
38  */
39
40 /*
41  * Add support for other signatures:
42  * 
43  * obj<</Subtype/Image/Length 110494/Filter/JPXDecode/BitsPerComponent 8/ColorSpace/DeviceRGB/Width 712/Height 1052>>stream
44  */
45 #define _GNU_SOURCE
46 #include <string.h>
47 #include <stdio.h>
48 #include <stddef.h>
49 #include <assert.h>
50
51 int main(int argc, char *argv[])
52 {
53 #define NUMJP2 32
54   int i, c = 0;
55   long offets[NUMJP2];
56   char buffer[512];
57 #define BUFLEN 4096
58   int cont = 1;
59   FILE *f;
60   size_t nread;
61   char haystack[BUFLEN];
62   const char needle[] = "JPXDecode";
63
64   const size_t nlen = strlen( needle );
65   const size_t flen = BUFLEN - nlen;
66   char *fpos = haystack + nlen;
67   const char *filename;
68   if( argc < 2 ) return 1;
69
70   filename = argv[1];
71
72   memset( haystack, 0, nlen );
73
74   f = fopen( filename, "rb" );
75   while( cont )
76     {
77     const char *ret;
78     size_t hlen;
79     nread = fread(fpos, 1, flen, f);
80     hlen = nlen + nread;
81     ret = memmem( haystack, hlen, needle, nlen);
82     if( ret )
83       {
84       const long cpos = ftell(f);
85       const ptrdiff_t diff = ret - haystack;
86       assert( diff >= 0 );
87       /*fprintf( stdout, "Found it: %lx\n", (ptrdiff_t)cpos - (ptrdiff_t)hlen + diff);*/
88       offets[c++] = (ptrdiff_t)cpos - (ptrdiff_t)hlen + diff;
89       }
90     cont = (nread == flen);
91     memcpy( haystack, haystack + nread, nlen );
92     }
93
94   assert( feof( f ) );
95
96   for( i = 0; i < c; ++i )
97     {
98     int s, len = 0;
99     char *r;
100     const int ret = fseek(f, offets[i], SEEK_SET);
101     assert( ret == 0 );
102     r = fgets(buffer, sizeof(buffer), f);
103     assert( r );
104     /*fprintf( stderr, "DEBUG: %s", r );*/
105     s = sscanf(r, "JPXDecode]/Length  %d/Width %*d/BitsPerComponent %*d/Height %*d", &len);
106     if( s == 0 )
107       { // try again harder
108       const int ret = fseek(f, offets[i] - 40, SEEK_SET); // 40 is magic number
109       assert( ret == 0 );
110       r = fgets(buffer, sizeof(buffer), f);
111       assert( r );
112       const char needle2[] = "/Length";
113       char * s2 = strstr(buffer, needle2);
114       s = sscanf(s2, "/Length  %d/", &len);
115       }
116     if( s == 1 )
117       {
118       FILE *jp2;
119       int j;
120       char jp2fn[512];
121       sprintf( jp2fn, "%s.%d.jp2", filename, i );
122       jp2 = fopen( jp2fn, "wb" );
123       for( j = 0; j < len; ++j )
124         {
125         int v = fgetc(f);
126         int ret2 = fputc(v, jp2);
127         assert( ret2 != EOF );
128         }
129       fclose( jp2 );
130 #if 0
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 );
136 #endif
137       }
138     }
139   fclose(f);
140
141   return 0;
142 }