source: extensions/edit_gmaps/admin/include/JPEG.php @ 9412

Last change on this file since 9412 was 9412, checked in by cljosse, 13 years ago
File size: 38.5 KB
Line 
1<?php
2
3/******************************************************************************
4*
5* Filename:     JPEG.php
6*
7* Description:  Provides functions for reading and writing information to/from
8*               JPEG format files
9*
10* Author:      Evan Hunter
11*
12* Date:         23/7/2004
13*
14* Project:      PHP JPEG Metadata Toolkit
15*
16* Revision:     1.10
17*
18* Changes:      1.00 -> 1.10 : changed put_jpeg_header_data to check if the data
19*                              being written exists
20*
21* URL:          http://electronics.ozhiker.com
22*
23* Copyright:    Copyright " . $auteur . " 2004
24*
25* License:      This file is part of the PHP JPEG Metadata Toolkit.
26*
27*               The PHP JPEG Metadata Toolkit is free software; you can
28*               redistribute it and/or modify it under the terms of the
29*               GNU General Public License as published by the Free Software
30*               Foundation; either version 2 of the License, or (at your
31*               option) any later version.
32*
33*               The PHP JPEG Metadata Toolkit is distributed in the hope
34*               that it will be useful, but WITHOUT ANY WARRANTY; without
35*               even the implied warranty of MERCHANTABILITY or FITNESS
36*               FOR A PARTICULAR PURPOSE.  See the GNU General Public License
37*               for more details.
38*
39*               You should have received a copy of the GNU General Public
40*               License along with the PHP JPEG Metadata Toolkit; if not,
41*               write to the Free Software Foundation, Inc., 59 Temple
42*               Place, Suite 330, Boston, MA  02111-1307  USA
43*
44*               If you require a different license for commercial or other
45*               purposes, please contact the author: evan@ozhiker.com
46*
47******************************************************************************/
48
49
50
51
52/******************************************************************************
53*
54* Function:     get_jpeg_header_data
55*
56* Description:  Reads all the JPEG header segments from an JPEG image file into an
57*               array
58*
59* Parameters:   filename - the filename of the file to JPEG file to read
60*
61* Returns:      headerdata - Array of JPEG header segments
62*               FALSE - if headers could not be read
63*
64******************************************************************************/
65
66function get_jpeg_header_data( $filename )
67{
68
69        // prevent refresh from aborting file operations and hosing file
70        ignore_user_abort(true);
71
72
73        // Attempt to open the jpeg file - the at symbol supresses the error message about
74        // not being able to open files. The file_exists would have been used, but it
75        // does not work with files fetched over http or ftp.
76        $filehnd = @fopen($filename, 'rb');
77
78        // Check if the file opened successfully
79        if ( ! $filehnd  )
80        {
81                // Could't open the file - exit
82                echo "<p>Could not open file $filename</p>\n";
83                return FALSE;
84        }
85
86
87        // Read the first two characters
88        $data = network_safe_fread( $filehnd, 2 );
89
90        // Check that the first two characters are 0xFF 0xDA  (SOI - Start of image)
91        if ( $data != "\xFF\xD8" )
92        {
93                // No SOI (FF D8) at start of file - This probably isn't a JPEG file - close file and return;
94                echo "<p>This probably is not a JPEG file</p>\n";
95                fclose($filehnd);
96                return FALSE;
97        }
98
99
100        // Read the third character
101        $data = network_safe_fread( $filehnd, 2 );
102
103        // Check that the third character is 0xFF (Start of first segment header)
104        if ( $data{0} != "\xFF" )
105        {
106                // NO FF found - close file and return - JPEG is probably corrupted
107                fclose($filehnd);
108                return FALSE;
109        }
110
111        // Flag that we havent yet hit the compressed image data
112        $hit_compressed_image_data = FALSE;
113
114
115        // Cycle through the file until, one of: 1) an EOI (End of image) marker is hit,
116        //                                       2) we have hit the compressed image data (no more headers are allowed after data)
117        //                                       3) or end of file is hit
118
119        while ( ( $data{1} != "\xD9" ) && (! $hit_compressed_image_data) && ( ! feof( $filehnd ) ))
120        {
121                // Found a segment to look at.
122                // Check that the segment marker is not a Restart marker - restart markers don't have size or data after them
123                if (  ( ord($data{1}) < 0xD0 ) || ( ord($data{1}) > 0xD7 ) )
124                {
125                        // Segment isn't a Restart marker
126                        // Read the next two bytes (size)
127                        $sizestr = network_safe_fread( $filehnd, 2 );
128
129                        // convert the size bytes to an integer
130                        $decodedsize = unpack ("nsize", $sizestr);
131
132                        // Save the start position of the data
133                        $segdatastart = ftell( $filehnd );
134
135                        // Read the segment data with length indicated by the previously read size
136                        $segdata = network_safe_fread( $filehnd, $decodedsize['size'] - 2 );
137
138
139                        // Store the segment information in the output array
140                        $headerdata[] = array(  "SegType" => ord($data{1}),
141                                                "SegName" => $GLOBALS[ "JPEG_Segment_Names" ][ ord($data{1}) ],
142                                                "SegDesc" => $GLOBALS[ "JPEG_Segment_Descriptions" ][ ord($data{1}) ],
143                                                "SegDataStart" => $segdatastart,
144                                                "SegData" => $segdata );
145                }
146
147                // If this is a SOS (Start Of Scan) segment, then there is no more header data - the compressed image data follows
148                if ( $data{1} == "\xDA" )
149                {
150                        // Flag that we have hit the compressed image data - exit loop as no more headers available.
151                        $hit_compressed_image_data = TRUE;
152                }
153                else
154                {
155                        // Not an SOS - Read the next two bytes - should be the segment marker for the next segment
156                        $data = network_safe_fread( $filehnd, 2 );
157
158                        // Check that the first byte of the two is 0xFF as it should be for a marker
159                        if ( $data{0} != "\xFF" )
160                        {
161                                // NO FF found - close file and return - JPEG is probably corrupted
162                                fclose($filehnd);
163                                return FALSE;
164                        }
165                }
166        }
167
168        // Close File
169        fclose($filehnd);
170        // Alow the user to abort from now on
171        ignore_user_abort(false);
172
173        // Return the header data retrieved
174        return $headerdata;
175}
176
177
178/******************************************************************************
179* End of Function:     get_jpeg_header_data
180******************************************************************************/
181
182
183
184
185/******************************************************************************
186*
187* Function:     put_jpeg_header_data
188*
189* Description:  Writes JPEG header data into a JPEG file. Takes an array in the
190*               same format as from get_jpeg_header_data, and combines it with
191*               the image data of an existing JPEG file, to create a new JPEG file
192*               WARNING: As this function will replace all JPEG headers,
193*                        including SOF etc, it is best to read the jpeg headers
194*                        from a file, alter them, then put them back on the same
195*                        file. If a SOF segment wer to be transfered from one
196*                        file to another, the image could become unreadable unless
197*                        the images were idenical size and configuration
198*
199*
200* Parameters:   old_filename - the JPEG file from which the image data will be retrieved
201*               new_filename - the name of the new JPEG to create (can be same as old_filename)
202*               jpeg_header_data - a JPEG header data array in the same format
203*                                  as from get_jpeg_header_data
204*
205* Returns:      TRUE - on Success
206*               FALSE - on Failure
207*
208******************************************************************************/
209
210function put_jpeg_header_data( $old_filename, $new_filename, $jpeg_header_data )
211{
212
213        // Change: added check to ensure data exists, as of revision 1.10
214        // Check if the data to be written exists
215        if ( $jpeg_header_data == FALSE )
216        {
217                // Data to be written not valid - abort
218                return FALSE;
219        }
220
221        // extract the compressed image data from the old file
222        $compressed_image_data = get_jpeg_image_data( $old_filename );
223
224        // Check if the extraction worked
225        if ( ( $compressed_image_data === FALSE ) || ( $compressed_image_data === NULL ) )
226        {
227                // Couldn't get image data from old file
228                return FALSE;
229        }
230
231
232        // Cycle through new headers
233        foreach ($jpeg_header_data as $segno => $segment)
234        {
235                // Check that this header is smaller than the maximum size
236                if ( strlen($segment['SegData']) > 0xfffd )
237                {
238                        // Could't open the file - exit
239                        echo "<p>A Header is too large to fit in JPEG segment</p>\n";
240                        return FALSE;
241                }
242        }
243
244        ignore_user_abort(true);    ## prevent refresh from aborting file operations and hosing file
245
246
247        // Attempt to open the new jpeg file
248        $newfilehnd = @fopen($new_filename, 'wb');
249        // Check if the file opened successfully
250        if ( ! $newfilehnd  )
251        {
252                // Could't open the file - exit
253                echo "<p>Could not open file $new_filename</p>\n";
254                return FALSE;
255        }
256
257        // Write SOI
258        fwrite( $newfilehnd, "\xFF\xD8" );
259
260        // Cycle through new headers, writing them to the new file
261        foreach ($jpeg_header_data as $segno => $segment)
262        {
263
264                // Write segment marker
265                fwrite( $newfilehnd, sprintf( "\xFF%c", $segment['SegType'] ) );
266
267                // Write segment size
268                fwrite( $newfilehnd, pack( "n", strlen($segment['SegData']) + 2 ) );
269
270                // Write segment data
271                fwrite( $newfilehnd, $segment['SegData'] );
272        }
273
274        // Write the compressed image data
275        fwrite( $newfilehnd, $compressed_image_data );
276
277        // Write EOI
278        fwrite( $newfilehnd, "\xFF\xD9" );
279
280        // Close File
281        fclose($newfilehnd);
282
283        // Alow the user to abort from now on
284        ignore_user_abort(false);
285
286
287        return TRUE;
288
289}
290
291/******************************************************************************
292* End of Function:     put_jpeg_header_data
293******************************************************************************/
294
295
296
297/******************************************************************************
298*
299* Function:     get_jpeg_Comment
300*
301* Description:  Retreives the contents of the JPEG Comment (COM = 0xFFFE) segment if one
302*               exists
303*
304* Parameters:   jpeg_header_data - the JPEG header data, as retrieved
305*                                  from the get_jpeg_header_data function
306*
307* Returns:      string - Contents of the Comment segement
308*               FALSE - if the comment segment couldnt be found
309*
310******************************************************************************/
311
312function get_jpeg_Comment( $jpeg_header_data )
313{
314        //Cycle through the header segments until COM is found or we run out of segments
315        $i = 0;
316        while ( ( $i < count( $jpeg_header_data) )  && ( $jpeg_header_data[$i]['SegName'] != "COM" ) )
317        {
318                $i++;
319        }
320
321        // Check if a COM segment has been found
322        if (  $i < count( $jpeg_header_data) )
323        {
324                // A COM segment was found, return it's contents
325                return $jpeg_header_data[$i]['SegData'];
326        }
327        else
328        {
329                // No COM segment found
330                return FALSE;
331        }
332}
333
334/******************************************************************************
335* End of Function:     get_jpeg_Comment
336******************************************************************************/
337
338
339/******************************************************************************
340*
341* Function:     put_jpeg_Comment
342*
343* Description:  Creates a new JPEG Comment segment from a string, and inserts
344*               this segment into the supplied JPEG header array
345*
346* Parameters:   jpeg_header_data - a JPEG header data array in the same format
347*                                  as from get_jpeg_header_data, into which the
348*                                  new Comment segment will be put
349*               $new_Comment - a string containing the new Comment
350*
351* Returns:      jpeg_header_data - the JPEG header data array with the new
352*                                  JPEG Comment segment added
353*
354******************************************************************************/
355
356function put_jpeg_Comment( $jpeg_header_data, $new_Comment )
357{
358        //Cycle through the header segments
359        for( $i = 0; $i < count( $jpeg_header_data ); $i++ )
360        {
361                // If we find an COM header,
362                if ( strcmp ( $jpeg_header_data[$i]['SegName'], "COM" ) == 0 )
363                {
364                        // Found a preexisting Comment block - Replace it with the new one and return.
365                        $jpeg_header_data[$i]['SegData'] = $new_Comment;
366                        return $jpeg_header_data;
367                }
368        }
369
370
371
372        // No preexisting Comment block found, find where to put it by searching for the highest app segment
373        $i = 0;
374        while ( ( $i < count( $jpeg_header_data ) ) && ( $jpeg_header_data[$i]["SegType"] >= 0xE0 ) )
375        {
376                $i++;
377        }
378
379
380        // insert a Comment segment new at the position found of the header data.
381        array_splice($jpeg_header_data, $i , 0, array( array(   "SegType" => 0xFE,
382                                                                "SegName" => $GLOBALS[ "JPEG_Segment_Names" ][ 0xFE ],
383                                                                "SegDesc" => $GLOBALS[ "JPEG_Segment_Descriptions" ][ 0xFE ],
384                                                                "SegData" => $new_Comment ) ) );
385        return $jpeg_header_data;
386}
387
388/******************************************************************************
389* End of Function:     put_jpeg_Comment
390******************************************************************************/
391
392
393
394
395/******************************************************************************
396*
397* Function:     Interpret_Comment_to_HTML
398*
399* Description:  Generates html showing the contents of any JPEG Comment segment
400*
401* Parameters:   jpeg_header_data - the JPEG header data, as retrieved
402*                                  from the get_jpeg_header_data function
403*
404* Returns:      output - the HTML
405*
406******************************************************************************/
407
408function Interpret_Comment_to_HTML( $jpeg_header_data )
409{
410        // Create a string to receive the output
411        $output = "";
412
413        // read the comment segment
414        $comment = get_jpeg_Comment( $jpeg_header_data );
415
416        // Check if the comment segment was valid
417        if ( $comment !== FALSE )
418        {
419                // Comment exists - add it to the output
420                $output .= "<fieldset id='comment' class='fieldset' ><legend>JPEG Comment</legend>";
421                $output .= "<p class=\"JPEG_Comment_Text\">$comment</p>\n";
422                $output .= "</fieldset>";
423        }
424
425        // Return the result
426        return $output;
427}
428
429/******************************************************************************
430* End of Function:     Interpret_Comment_to_HTML
431******************************************************************************/
432
433
434
435
436/******************************************************************************
437*
438* Function:     get_jpeg_intrinsic_values
439*
440* Description:  Retreives information about the intrinsic characteristics of the
441*               jpeg image, such as Bits per Component, Height and Width.
442*
443* Parameters:   jpeg_header_data - the JPEG header data, as retrieved
444*                                  from the get_jpeg_header_data function
445*
446* Returns:      array - An array containing the intrinsic JPEG values
447*               FALSE - if the comment segment couldnt be found
448*
449******************************************************************************/
450
451function get_jpeg_intrinsic_values( $jpeg_header_data )
452{
453        // Create a blank array for the output
454        $Outputarray = array( );
455
456        //Cycle through the header segments until Start Of Frame (SOF) is found or we run out of segments
457        $i = 0;
458        while ( ( $i < count( $jpeg_header_data) )  && ( substr( $jpeg_header_data[$i]['SegName'], 0, 3 ) != "SOF" ) )
459        {
460                $i++;
461        }
462
463        // Check if a SOF segment has been found
464        if ( substr( $jpeg_header_data[$i]['SegName'], 0, 3 ) == "SOF" )
465        {
466                // SOF segment was found, extract the information
467
468                $data = $jpeg_header_data[$i]['SegData'];
469
470                // First byte is Bits per component
471                $Outputarray['Bits per Component'] = ord( $data{0} );
472
473                // Second and third bytes are Image Height
474                $Outputarray['Image Height'] = ord( $data{ 1 } ) * 256 + ord( $data{ 2 } );
475
476                // Forth and fifth bytes are Image Width
477                $Outputarray['Image Width'] = ord( $data{ 3 } ) * 256 + ord( $data{ 4 } );
478
479                // Sixth byte is number of components
480                $numcomponents = ord( $data{ 5 } );
481
482                // Following this is a table containing information about the components
483                for( $i = 0; $i < $numcomponents; $i++ )
484                {
485                        $Outputarray['Components'][] = array (  'Component Identifier' => ord( $data{ 6 + $i * 3 } ),
486                                                                'Horizontal Sampling Factor' => ( ord( $data{ 7 + $i * 3 } ) & 0xF0 ) / 16,
487                                                                'Vertical Sampling Factor' => ( ord( $data{ 7 + $i * 3 } ) & 0x0F ),
488                                                                'Quantization table destination selector' => ord( $data{ 8 + $i * 3 } ) );
489                }
490        }
491        else
492        {
493                // Couldn't find Start Of Frame segment, hence can't retrieve info
494                return FALSE;
495        }
496
497        return $Outputarray;
498}
499
500
501/******************************************************************************
502* End of Function:     get_jpeg_intrinsic_values
503******************************************************************************/
504
505
506
507
508
509/******************************************************************************
510*
511* Function:     Interpret_intrinsic_values_to_HTML
512*
513* Description:  Generates html showing some of the intrinsic JPEG values which
514*               were retrieved with the get_jpeg_intrinsic_values function
515*
516* Parameters:   values - the JPEG intrinsic values, as read from get_jpeg_intrinsic_values
517*
518* Returns:      OutputStr - A string containing the HTML
519*
520******************************************************************************/
521
522function Interpret_intrinsic_values_to_HTML( $values )
523{
524        // Check values are valid
525        if ( $values != FALSE )
526        {
527                // Write Heading
528                $OutputStr = "<fieldset class='fieldset' id='Intrinsic_JPEG_Information' ><legend>Intrinsic JPEG Information</legend>";
529
530                // Create Table
531                $OutputStr .= "<table class=\"JPEG_Intrinsic_Table\" border=1>\n";
532
533                                         
534                        $tabval=$IPTC_Record;
535                        $tabval['Type_src']="Intrinsic_JPEG";
536
537                // Put image height and width into table
538                        $tabval['Tag Name']="Image Height"; 
539                        $tabval['Text Value']=  $values['Image Height'] . " pixels";
540$OutputStr .=OutPut_exif($tabval);
541                         $tabval['Tag Name']="Image Width'"; 
542                         $tabval['Text Value']=  $values['Image Width'] . " pixels";
543                         $OutputStr .=OutPut_exif($tabval);
544                // Put colour depth into table
545                $tabval['Tag Name']="Colour Depth";
546               
547                if ( count( $values['Components'] ) == 1 )
548                {
549                      $tabval['Text Value']=$values['Bits per Component'] . " bit Monochrome";   
550                   
551                }
552                else
553                {
554                       $tabval['Text Value']= ($values['Bits per Component'] * count( $values['Components'] ) ) . " bit";
555                }
556$OutputStr .=OutPut_exif($tabval);
557                // Close Table
558                $OutputStr .= "</table></fieldset>";
559
560                // Return html
561                return $OutputStr;
562        }
563}
564
565/******************************************************************************
566* End of Function:     Interpret_intrinsic_values_to_HTML
567******************************************************************************/
568
569
570
571
572
573
574
575/******************************************************************************
576*
577* Function:     get_jpeg_image_data
578*
579* Description:  Retrieves the compressed image data part of the JPEG file
580*
581* Parameters:   filename - the filename of the JPEG file to read
582*
583* Returns:      compressed_data - A string containing the compressed data
584*               FALSE - if retrieval failed
585*
586******************************************************************************/
587
588function get_jpeg_image_data( $filename )
589{
590
591        // prevent refresh from aborting file operations and hosing file
592        ignore_user_abort(true);
593
594        // Attempt to open the jpeg file
595        $filehnd = @fopen($filename, 'rb');
596
597        // Check if the file opened successfully
598        if ( ! $filehnd  )
599        {
600                // Could't open the file - exit
601                return FALSE;
602        }
603
604
605        // Read the first two characters
606        $data = network_safe_fread( $filehnd, 2 );
607
608        // Check that the first two characters are 0xFF 0xDA  (SOI - Start of image)
609        if ( $data != "\xFF\xD8" )
610        {
611                // No SOI (FF D8) at start of file - close file and return;
612                fclose($filehnd);
613                return FALSE;
614        }
615
616
617
618        // Read the third character
619        $data = network_safe_fread( $filehnd, 2 );
620
621        // Check that the third character is 0xFF (Start of first segment header)
622        if ( $data{0} != "\xFF" )
623        {
624                // NO FF found - close file and return
625                fclose($filehnd);
626                return;
627        }
628
629        // Flag that we havent yet hit the compressed image data
630        $hit_compressed_image_data = FALSE;
631
632
633        // Cycle through the file until, one of: 1) an EOI (End of image) marker is hit,
634        //                                       2) we have hit the compressed image data (no more headers are allowed after data)
635        //                                       3) or end of file is hit
636
637        while ( ( $data{1} != "\xD9" ) && (! $hit_compressed_image_data) && ( ! feof( $filehnd ) ))
638        {
639                // Found a segment to look at.
640                // Check that the segment marker is not a Restart marker - restart markers don't have size or data after them
641                if (  ( ord($data{1}) < 0xD0 ) || ( ord($data{1}) > 0xD7 ) )
642                {
643                        // Segment isn't a Restart marker
644                        // Read the next two bytes (size)
645                        $sizestr = network_safe_fread( $filehnd, 2 );
646
647                        // convert the size bytes to an integer
648                        $decodedsize = unpack ("nsize", $sizestr);
649
650                         // Read the segment data with length indicated by the previously read size
651                        $segdata = network_safe_fread( $filehnd, $decodedsize['size'] - 2 );
652                }
653
654                // If this is a SOS (Start Of Scan) segment, then there is no more header data - the compressed image data follows
655                if ( $data{1} == "\xDA" )
656                {
657                        // Flag that we have hit the compressed image data - exit loop after reading the data
658                        $hit_compressed_image_data = TRUE;
659
660                        // read the rest of the file in
661                        // Can't use the filesize function to work out
662                        // how much to read, as it won't work for files being read by http or ftp
663                        // So instead read 1Mb at a time till EOF
664
665                        $compressed_data = "";
666                        do
667                        {
668                                $compressed_data .= network_safe_fread( $filehnd, 1048576 );
669                        } while( ! feof( $filehnd ) );
670
671                        // Strip off EOI and anything after
672                        $EOI_pos = strpos( $compressed_data, "\xFF\xD9" );
673                        $compressed_data = substr( $compressed_data, 0, $EOI_pos );
674                }
675                else
676                {
677                        // Not an SOS - Read the next two bytes - should be the segment marker for the next segment
678                        $data = network_safe_fread( $filehnd, 2 );
679
680                        // Check that the first byte of the two is 0xFF as it should be for a marker
681                        if ( $data{0} != "\xFF" )
682                        {
683                                // Problem - NO FF foundclose file and return";
684                                fclose($filehnd);
685                                return;
686                        }
687                }
688        }
689
690        // Close File
691        fclose($filehnd);
692
693        // Alow the user to abort from now on
694        ignore_user_abort(false);
695
696
697        // Return the compressed data if it was found
698        if ( $hit_compressed_image_data )
699        {
700                return $compressed_data;
701        }
702        else
703        {
704                return FALSE;
705        }
706}
707
708
709/******************************************************************************
710* End of Function:     get_jpeg_image_data
711******************************************************************************/
712
713
714
715
716
717
718
719/******************************************************************************
720*
721* Function:     Generate_JPEG_APP_Segment_HTML
722*
723* Description:  Generates html showing information about the Application (APP)
724*               segments which are present in the JPEG file
725*
726* Parameters:   jpeg_header_data - the JPEG header data, as retrieved
727*                                  from the get_jpeg_header_data function
728*
729* Returns:      output - A string containing the HTML
730*
731******************************************************************************/
732
733function Generate_JPEG_APP_Segment_HTML( $jpeg_header_data )
734{
735        if ( $jpeg_header_data == FALSE )
736        {
737                return "";
738        }
739
740
741        // Write Heading
742        $output = "<fieldset class='fieldset' id='Application_Metadata_Segments' ><legend>Application Metadata Segments(JPEG)</legend>";
743
744        // Create table
745        $output .= "<table class=\"JPEG_APP_Segments_Table\" border=1>\n";
746        // Cycle through each segment in the array
747 
748
749        foreach( $jpeg_header_data as $jpeg_header )
750        {
751                        $tabval=$jpeg_header ;
752                        $tabval['Type_src']="jpeg";
753                        $tabval['Tag Name']=""; 
754                        $tabval['Text Value']= "N.C";   
755                // Check if the segment is a APP segment
756
757                if ( ( $jpeg_header['SegType'] >= 0xE0 ) && ( $jpeg_header['SegType'] <= 0xEF ) )
758                {
759                        // This is an APP segment
760
761                        // Read APP Segment Name - a Null terminated string at the start of the segment
762                        $seg_name = strtok($jpeg_header['SegData'], "\x00");
763
764                        // Some Segment names are either too long or not meaningfull, so
765                        // we should clean them up
766
767                        if ( $seg_name == "http://ns.adobe.com/xap/1.0/" )
768                        {
769                                $seg_name = "XAP/RDF (\"http://ns.adobe.com/xap/1.0/\")";
770                        }
771                        elseif ( $seg_name == "Photoshop 3.0" )
772                        {
773                                $seg_name = "Photoshop IRB (\"Photoshop 3.0\")";
774                        }
775                        elseif ( ( strncmp ( $seg_name, "[picture info]", 14) == 0 ) ||
776                                 ( strncmp ( $seg_name, "\x0a\x09\x09\x09\x09[picture info]", 19) == 0 ) )
777                        {
778                                $seg_name = "[picture info]";
779                        }
780                        elseif (  strncmp ( $seg_name, "Type=", 5) == 0 )
781                        {
782                                $seg_name = "Epson Info";
783                        }
784                        elseif ( ( strncmp ( $seg_name, "HHHHHHHHHHHHHHH", 15) == 0 ) ||
785                                 ( strncmp ( $seg_name, "@s33", 5) == 0 ) )
786                        {
787                                $seg_name = "HP segment full of \"HHHHH\"";
788                        }
789
790
791                        // Clean the segment name so it doesn't cause problems with HTML
792                        $seg_name = htmlentities( $seg_name );
793
794                        // Output a Table row containing this APP segment
795                        $tabval['Type_src']=$seg_name; 
796                        $tabval['Tag Name']= $jpeg_header['SegName'];
797                        $tabval['Text Value']=  strlen( $jpeg_header['SegData']). " bytes"    ;   
798$output .= OutPut_exif($tabval) ;
799        //                $output .= "<tr class=\"JPEG_APP_Segments_Table_Row\"><td class=\"JPEG_APP_Segments_Caption_Cell\">$seg_name</td><td class=\"JPEG_APP_Segments_Type_Cell\">" . $jpeg_header['SegName'] . "</td><td  class=\"JPEG_APP_Segments_Size_Cell\" align=\"right\">" . strlen( $jpeg_header['SegData']). " bytes</td></tr>\n";
800                }
801        }
802
803        // Close the table
804        $output .= "</table></fieldset>";
805
806        // Return the HTML
807        return $output;
808}
809
810
811/******************************************************************************
812* End of Function:     Generate_JPEG_APP_Segment_HTML
813******************************************************************************/
814
815
816
817
818/******************************************************************************
819*
820* Function:     network_safe_fread
821*
822* Description:  Retrieves data from a file. This function is required since
823*               the fread function will not always return the requested number
824*               of characters when reading from a network stream or pipe
825*
826* Parameters:   file_handle - the handle of a file to read from
827*               length - the number of bytes requested
828*
829* Returns:      data - the data read from the file. may be less than the number
830*                      requested if EOF was hit
831*
832******************************************************************************/
833
834function network_safe_fread( $file_handle, $length )
835{
836        // Create blank string to receive data
837        $data = "";
838
839        // Keep reading data from the file until either EOF occurs or we have
840        // retrieved the requested number of bytes
841
842        while ( ( !feof( $file_handle ) ) && ( strlen($data) < $length ) )
843        {
844                $data .= fread( $file_handle, $length-strlen($data) );
845        }
846
847        // return the data read
848        return $data;
849}
850
851/******************************************************************************
852* End of Function:     network_safe_fread
853******************************************************************************/
854
855
856
857
858/******************************************************************************
859* Global Variable:      JPEG_Segment_Names
860*
861* Contents:     The names of the JPEG segment markers, indexed by their marker number
862*
863******************************************************************************/
864
865$GLOBALS[ "JPEG_Segment_Names" ] = array(
866
8670xC0 =>  "SOF0",  0xC1 =>  "SOF1",  0xC2 =>  "SOF2",  0xC3 =>  "SOF4",
8680xC5 =>  "SOF5",  0xC6 =>  "SOF6",  0xC7 =>  "SOF7",  0xC8 =>  "JPG",
8690xC9 =>  "SOF9",  0xCA =>  "SOF10", 0xCB =>  "SOF11", 0xCD =>  "SOF13",
8700xCE =>  "SOF14", 0xCF =>  "SOF15",
8710xC4 =>  "DHT",   0xCC =>  "DAC",
872
8730xD0 =>  "RST0",  0xD1 =>  "RST1",  0xD2 =>  "RST2",  0xD3 =>  "RST3",
8740xD4 =>  "RST4",  0xD5 =>  "RST5",  0xD6 =>  "RST6",  0xD7 =>  "RST7",
875
8760xD8 =>  "SOI",   0xD9 =>  "EOI",   0xDA =>  "SOS",   0xDB =>  "DQT",
8770xDC =>  "DNL",   0xDD =>  "DRI",   0xDE =>  "DHP",   0xDF =>  "EXP",
878
8790xE0 =>  "APP0",  0xE1 =>  "APP1",  0xE2 =>  "APP2",  0xE3 =>  "APP3",
8800xE4 =>  "APP4",  0xE5 =>  "APP5",  0xE6 =>  "APP6",  0xE7 =>  "APP7",
8810xE8 =>  "APP8",  0xE9 =>  "APP9",  0xEA =>  "APP10", 0xEB =>  "APP11",
8820xEC =>  "APP12", 0xED =>  "APP13", 0xEE =>  "APP14", 0xEF =>  "APP15",
883
884
8850xF0 =>  "JPG0",  0xF1 =>  "JPG1",  0xF2 =>  "JPG2",  0xF3 =>  "JPG3",
8860xF4 =>  "JPG4",  0xF5 =>  "JPG5",  0xF6 =>  "JPG6",  0xF7 =>  "JPG7",
8870xF8 =>  "JPG8",  0xF9 =>  "JPG9",  0xFA =>  "JPG10", 0xFB =>  "JPG11",
8880xFC =>  "JPG12", 0xFD =>  "JPG13",
889
8900xFE =>  "COM",   0x01 =>  "TEM",   0x02 =>  "RES",
891
892);
893
894/******************************************************************************
895* End of Global Variable:     JPEG_Segment_Names
896******************************************************************************/
897
898
899/******************************************************************************
900* Global Variable:      JPEG_Segment_Descriptions
901*
902* Contents:     The descriptions of the JPEG segment markers, indexed by their marker number
903*
904******************************************************************************/
905
906$GLOBALS[ "JPEG_Segment_Descriptions" ] = array(
907
908/* JIF Marker byte pairs in JPEG Interchange Format sequence */
9090xC0 => "Start Of Frame (SOF) Huffman  - Baseline DCT",
9100xC1 =>  "Start Of Frame (SOF) Huffman  - Extended sequential DCT",
9110xC2 =>  "Start Of Frame Huffman  - Progressive DCT (SOF2)",
9120xC3 =>  "Start Of Frame Huffman  - Spatial (sequential) lossless (SOF3)",
9130xC5 =>  "Start Of Frame Huffman  - Differential sequential DCT (SOF5)",
9140xC6 =>  "Start Of Frame Huffman  - Differential progressive DCT (SOF6)",
9150xC7 =>  "Start Of Frame Huffman  - Differential spatial (SOF7)",
9160xC8 =>  "Start Of Frame Arithmetic - Reserved for JPEG extensions (JPG)",
9170xC9 =>  "Start Of Frame Arithmetic - Extended sequential DCT (SOF9)",
9180xCA =>  "Start Of Frame Arithmetic - Progressive DCT (SOF10)",
9190xCB =>  "Start Of Frame Arithmetic - Spatial (sequential) lossless (SOF11)",
9200xCD =>  "Start Of Frame Arithmetic - Differential sequential DCT (SOF13)",
9210xCE =>  "Start Of Frame Arithmetic - Differential progressive DCT (SOF14)",
9220xCF =>  "Start Of Frame Arithmetic - Differential spatial (SOF15)",
9230xC4 =>  "Define Huffman Table(s) (DHT)",
9240xCC =>  "Define Arithmetic coding conditioning(s) (DAC)",
925
9260xD0 =>  "Restart with modulo 8 count 0 (RST0)",
9270xD1 =>  "Restart with modulo 8 count 1 (RST1)",
9280xD2 =>  "Restart with modulo 8 count 2 (RST2)",
9290xD3 =>  "Restart with modulo 8 count 3 (RST3)",
9300xD4 =>  "Restart with modulo 8 count 4 (RST4)",
9310xD5 =>  "Restart with modulo 8 count 5 (RST5)",
9320xD6 =>  "Restart with modulo 8 count 6 (RST6)",
9330xD7 =>  "Restart with modulo 8 count 7 (RST7)",
934
9350xD8 =>  "Start of Image (SOI)",
9360xD9 =>  "End of Image (EOI)",
9370xDA =>  "Start of Scan (SOS)",
9380xDB =>  "Define quantization Table(s) (DQT)",
9390xDC =>  "Define Number of Lines (DNL)",
9400xDD =>  "Define Restart Interval (DRI)",
9410xDE =>  "Define Hierarchical progression (DHP)",
9420xDF =>  "Expand Reference Component(s) (EXP)",
943
9440xE0 =>  "Application Field 0 (APP0) - usually JFIF or JFXX",
9450xE1 =>  "Application Field 1 (APP1) - usually EXIF or XMP/RDF",
9460xE2 =>  "Application Field 2 (APP2) - usually Flashpix",
9470xE3 =>  "Application Field 3 (APP3)",
9480xE4 =>  "Application Field 4 (APP4)",
9490xE5 =>  "Application Field 5 (APP5)",
9500xE6 =>  "Application Field 6 (APP6)",
9510xE7 =>  "Application Field 7 (APP7)",
952
9530xE8 =>  "Application Field 8 (APP8)",
9540xE9 =>  "Application Field 9 (APP9)",
9550xEA =>  "Application Field 10 (APP10)",
9560xEB =>  "Application Field 11 (APP11)",
9570xEC =>  "Application Field 12 (APP12) - usually [picture info]",
9580xED =>  "Application Field 13 (APP13) - usually photoshop IRB / IPTC",
9590xEE =>  "Application Field 14 (APP14)",
9600xEF =>  "Application Field 15 (APP15)",
961
962
9630xF0 =>  "Reserved for JPEG extensions (JPG0)",
9640xF1 =>  "Reserved for JPEG extensions (JPG1)",
9650xF2 =>  "Reserved for JPEG extensions (JPG2)",
9660xF3 =>  "Reserved for JPEG extensions (JPG3)",
9670xF4 =>  "Reserved for JPEG extensions (JPG4)",
9680xF5 =>  "Reserved for JPEG extensions (JPG5)",
9690xF6 =>  "Reserved for JPEG extensions (JPG6)",
9700xF7 =>  "Reserved for JPEG extensions (JPG7)",
9710xF8 =>  "Reserved for JPEG extensions (JPG8)",
9720xF9 =>  "Reserved for JPEG extensions (JPG9)",
9730xFA =>  "Reserved for JPEG extensions (JPG10)",
9740xFB =>  "Reserved for JPEG extensions (JPG11)",
9750xFC =>  "Reserved for JPEG extensions (JPG12)",
9760xFD =>  "Reserved for JPEG extensions (JPG13)",
977
9780xFE =>  "Comment (COM)",
9790x01 =>  "For temp private use arith code (TEM)",
9800x02 =>  "Reserved (RES)",
981
982);
983
984/******************************************************************************
985* End of Global Variable:     JPEG_Segment_Descriptions
986******************************************************************************/
987
988
989
990?>
Note: See TracBrowser for help on using the repository browser.