An example of using libexif to set JPEG Orientation Tag

来源:互联网 发布:天界翅膀进阶数据 编辑:程序博客网 时间:2024/05/16 17:43

An example of using libexif to set JPEG Orientation Tag :http://www.jwz.org/blog/2008/12/cocoa-exif-rotation/



#include <stdio.h>#include <stdlib.h>#include <libexif/exif-data.h>intmain(int argc, char *argv[]) {  if(argc != 2) {    printf("Usage: foo <image>\n");    exit(1);  }  int orientation = 0;  ExifData *exifData = exif_data_new_from_file(argv[1]);  if (exifData) {    ExifByteOrder byteOrder = exif_data_get_byte_order(exifData);    ExifEntry *exifEntry = exif_data_get_entry(exifData,                                               EXIF_TAG_ORIENTATION);    if (exifEntry)      orientation = exif_get_short(exifEntry->data, byteOrder);    exif_data_free(exifData);  }  /*        0th Row      0th Column     1  top          left side     2  top          right side     3  bottom       right side     4  bottom       left side     5  left side    top     6  right side   top     7  right side   bottom     8  left side    bottom  */  if(orientation != 0) {    printf("orientation == %d\n", orientation);  }  exit(0);}



在Github上找到了一个不错的代码,但本人能力有限,还未曾看懂,希望高手看懂后能给解释下。

BTW,关于Exif orientation Tag,有个非常详尽的资料:http://sylvana.net/jpegcrop/exif_orientation.html

(介绍各个方向所对应的tag的值)


[cpp] view plaincopyprint?
  1. <span style="font-size: 14px;">/*
  2. * jpegtran.c
  3. *
  4. * Copyright (C) 1995-1997, Thomas G. Lane.
  5. * This file is part of the Independent JPEG Group's software.
  6. * For conditions of distribution and use, see the accompanying README file.
  7. *
  8. * plenty of changes by Gerd Hoffmann <kraxel@bytesex.org>, with focus on
  9. * digital image processing and sane exif handling:
  10. *
  11. *   - does transformations only (flip/rotate/transpose/transverse).
  12. *   - also transforms the exif thumbnail if present.
  13. *   - can automatically figure transformation from the
  14. *     exif orientation tag.
  15. *   - updates the exif orientation tag.
  16. *   - updates the exif pixel dimension tags.
  17. *
  18. * This file contains a command-line user interface for JPEG transcoding.
  19. * It is very similar to cjpeg.c, but provides lossless transcoding between
  20. * different JPEG file formats.  It also provides some lossless and sort-of-
  21. * lossless transformations of JPEG data.
  22. */ 
  23.  
  24. #include <stdio.h> 
  25. #include <stdlib.h> 
  26. #include <stddef.h> 
  27. #include <unistd.h> 
  28. #include <errno.h> 
  29. #include <string.h> 
  30. #include <utime.h> 
  31. #include <setjmp.h> 
  32. #include <sys/stat.h> 
  33. #include <sys/types.h> 
  34.  
  35. #include <jpeglib.h> 
  36. #include "transupp.h"       /* Support routines for jpegtran */ 
  37. #include "jpegtools.h" 
  38.  
  39. #include "misc.h" 
  40.  
  41. #include <libexif/exif-data.h> 
  42. #include <libexif/exif-utils.h> 
  43. #include <libexif/exif-ifd.h> 
  44. #include <libexif/exif-tag.h> 
  45.  
  46. static int do_transform(struct jpeg_decompress_struct *src, 
  47.             struct jpeg_compress_struct   *dst, 
  48.             JXFORM_CODE transform, 
  49.             unsigned char *comment, 
  50.             char *thumbnail, int tsize, 
  51.             unsigned int flags); 
  52.  
  53. static JXFORM_CODE transmagic[] = { 
  54.     [ 1 ] = JXFORM_NONE, 
  55.     [ 2 ] = JXFORM_FLIP_H, 
  56.     [ 3 ] = JXFORM_ROT_180, 
  57.     [ 4 ] = JXFORM_FLIP_V, 
  58.     [ 5 ] = JXFORM_TRANSPOSE, 
  59.     [ 6 ] = JXFORM_ROT_90, 
  60.     [ 7 ] = JXFORM_TRANSVERSE, 
  61.     [ 8 ] = JXFORM_ROT_270, 
  62. }; 
  63.  
  64. #if 0 
  65. static char *transname[] = { 
  66.     [ JXFORM_NONE ]       = "none"
  67.     [ JXFORM_FLIP_H ]     = "flip h"
  68.     [ JXFORM_FLIP_V ]     = "flip v"
  69.     [ JXFORM_TRANSPOSE ]  = "transpose"
  70.     [ JXFORM_TRANSVERSE ] = "transverse"
  71.     [ JXFORM_ROT_90 ]     = "rot 90"
  72.     [ JXFORM_ROT_180 ]    = "rot 190"
  73.     [ JXFORM_ROT_270 ]    = "rot 270"
  74. }; 
  75. #endif 
  76.  
  77. /* ---------------------------------------------------------------------- */ 
  78.  
  79. /* libjpeg error handler -- exit via longjump */ 
  80. struct longjmp_error_mgr { 
  81.     struct jpeg_error_mgr jpeg; 
  82.     jmp_buf setjmp_buffer; 
  83. }; 
  84.  
  85. static void longjmp_error_exit(j_common_ptr cinfo) 
  86.     struct longjmp_error_mgr *h = (struct longjmp_error_mgr*)cinfo->err; 
  87.     (*cinfo->err->output_message)(cinfo); 
  88.     longjmp(h->setjmp_buffer, 1); 
  89.  
  90. /* ---------------------------------------------------------------------- */ 
  91.  
  92. static long get_int(ExifData *ed, ExifEntry *ee) 
  93.     ExifByteOrder o = exif_data_get_byte_order(ed); 
  94.     long value; 
  95.      
  96.     switch (ee->format) { 
  97.     case EXIF_FORMAT_SHORT: 
  98.     value = exif_get_short (ee->data, o); 
  99.     break
  100.     case EXIF_FORMAT_LONG: 
  101.     value = exif_get_long (ee->data, o); 
  102.     break
  103.     case EXIF_FORMAT_SLONG: 
  104.     value = exif_get_slong (ee->data, o); 
  105.     break
  106.     default
  107.     fprintf(stderr,"get_int oops\n"); 
  108.     exit(1); 
  109.     } 
  110.     return value; 
  111.  
  112. static void set_int(ExifData *ed, ExifEntry *ee,long value) 
  113.     ExifByteOrder o = exif_data_get_byte_order(ed); 
  114.  
  115.     switch (ee->format) { 
  116.     case EXIF_FORMAT_SHORT: 
  117.     exif_set_short (ee->data, o, value); 
  118.     break
  119.     case EXIF_FORMAT_LONG: 
  120.     exif_set_long (ee->data, o, value); 
  121.     break
  122.     case EXIF_FORMAT_SLONG: 
  123.     exif_set_slong (ee->data, o, value); 
  124.     break
  125.     default
  126.     fprintf(stderr,"set_int oops\n"); 
  127.     exit(1); 
  128.     } 
  129.  
  130. static void update_orientation(ExifData *ed,int ifd, int orientation) 
  131.     ExifEntry *ee; 
  132.  
  133.     ee = exif_content_get_entry(ed->ifd[ifd], 0x0112); 
  134.     if (NULL == ee) 
  135.     return
  136.     set_int(ed,ee,orientation); 
  137.  
  138. static void update_dimension(ExifData *ed, JXFORM_CODE transform, 
  139.                  int src_x,int src_y) 
  140.     static struct
  141.     int idf; 
  142.     int tag; 
  143.     int x; 
  144.     } fields[] = { 
  145.     { 
  146.         .idf = EXIF_IFD_EXIF, 
  147.         .tag = EXIF_TAG_PIXEL_X_DIMENSION, 
  148.         .x   = 1, 
  149.     },{ 
  150.         .idf = EXIF_IFD_EXIF, 
  151.         .tag = EXIF_TAG_PIXEL_Y_DIMENSION, 
  152.         .x   = 0, 
  153.     },{ 
  154.         .idf = EXIF_IFD_INTEROPERABILITY, 
  155.         .tag = EXIF_TAG_RELATED_IMAGE_WIDTH, 
  156.         .x   = 1, 
  157.     },{ 
  158.         .idf = EXIF_IFD_INTEROPERABILITY, 
  159.         .tag = EXIF_TAG_RELATED_IMAGE_LENGTH, 
  160.         .x   = 0, 
  161.     } 
  162.     }; 
  163.     ExifEntry *ee; 
  164.     int i; 
  165.  
  166.     for (i = 0; i < sizeof(fields)/sizeof(fields[0]); i++) { 
  167.     ee = exif_content_get_entry(ed->ifd[fields[i].idf], fields[i].tag); 
  168.     if (!ee) 
  169.         continue
  170.     switch (transform) { 
  171.     case JXFORM_ROT_90: 
  172.     case JXFORM_ROT_270: 
  173.     case JXFORM_TRANSPOSE: 
  174.     case JXFORM_TRANSVERSE: 
  175.         /* x/y reversed */ 
  176.         set_int(ed, ee, fields[i].x ? src_y : src_x); 
  177.         break
  178.     default
  179.         /* normal */ 
  180.         set_int(ed, ee, fields[i].x ? src_x : src_y); 
  181.         break
  182.     } 
  183.     } 
  184.  
  185. static int get_orientation(ExifData *ed) 
  186.     ExifEntry *ee; 
  187.  
  188.     ee = exif_content_get_entry(ed->ifd[EXIF_IFD_0], 0x0112); 
  189.     if (NULL == ee) 
  190.     return 1; /* top - left */ 
  191.     return get_int(ed,ee); 
  192.  
  193. /* ---------------------------------------------------------------------- */ 
  194.  
  195. struct th { 
  196.     struct jpeg_decompress_struct src; 
  197.     struct jpeg_compress_struct   dst; 
  198.     struct jpeg_error_mgr jsrcerr, jdsterr; 
  199.     unsigned char *in; 
  200.     unsigned char *out; 
  201.     int isize, osize; 
  202. }; 
  203.  
  204. static void thumbnail_src_init(struct jpeg_decompress_struct *cinfo) 
  205.     struct th *h  = container_of(cinfo,struct th, src); 
  206.     cinfo->src->next_input_byte = h->in; 
  207.     cinfo->src->bytes_in_buffer = h->isize; 
  208.  
  209. static int thumbnail_src_fill(struct jpeg_decompress_struct *cinfo) 
  210.     fprintf(stderr,"jpeg: panic: no more thumbnail input data\n"); 
  211.     exit(1); 
  212.  
  213. static void thumbnail_src_skip(struct jpeg_decompress_struct *cinfo, 
  214.                    long num_bytes) 
  215.     cinfo->src->next_input_byte += num_bytes; 
  216.  
  217. static void thumbnail_src_term(struct jpeg_decompress_struct *cinfo) 
  218.     /* nothing */ 
  219.  
  220. static void thumbnail_dest_init(struct jpeg_compress_struct *cinfo) 
  221.     struct th *h  = container_of(cinfo,struct th, dst); 
  222.     h->osize = h->isize * 2; 
  223.     h->out   = malloc(h->osize); 
  224.     cinfo->dest->next_output_byte = h->out; 
  225.     cinfo->dest->free_in_buffer   = h->osize; 
  226.  
  227. static boolean thumbnail_dest_flush(struct jpeg_compress_struct *cinfo) 
  228.     fprintf(stderr,"jpeg: panic: output buffer full\n"); 
  229.     exit(1); 
  230.  
  231. static void thumbnail_dest_term(struct jpeg_compress_struct *cinfo) 
  232.     struct th *h  = container_of(cinfo,struct th, dst); 
  233.     h->osize -= cinfo->dest->free_in_buffer; 
  234.  
  235. static struct jpeg_source_mgr thumbnail_src = { 
  236.     .init_source         = thumbnail_src_init, 
  237.     .fill_input_buffer   = thumbnail_src_fill, 
  238.     .skip_input_data     = thumbnail_src_skip, 
  239.     .resync_to_restart   = jpeg_resync_to_restart, 
  240.     .term_source         = thumbnail_src_term, 
  241. }; 
  242.  
  243. static struct jpeg_destination_mgr thumbnail_dst = { 
  244.     .init_destination    = thumbnail_dest_init, 
  245.     .empty_output_buffer = thumbnail_dest_flush, 
  246.     .term_destination    = thumbnail_dest_term, 
  247. }; 
  248.  
  249. static void do_thumbnail(ExifData *ed, JXFORM_CODE transform) 
  250.     struct th th; 
  251.  
  252.     if (JXFORM_NONE == transform) 
  253.     return
  254.      
  255.     memset(&th,0,sizeof(th)); 
  256.     th.in    = ed->data; 
  257.     th.isize = ed->size; 
  258.      
  259.     /* setup src */ 
  260.     th.src.err = jpeg_std_error(&th.jsrcerr); 
  261.     jpeg_create_decompress(&th.src); 
  262.     th.src.src = &thumbnail_src; 
  263.      
  264.     /* setup dst */ 
  265.     th.dst.err = jpeg_std_error(&th.jdsterr); 
  266.     jpeg_create_compress(&th.dst); 
  267.     th.dst.dest = &thumbnail_dst; 
  268.  
  269.     /* transform image */ 
  270.     do_transform(&th.src,&th.dst,transform,NULL,NULL,0,JFLAG_TRANSFORM_IMAGE); 
  271.  
  272.     /* cleanup */ 
  273.     jpeg_destroy_decompress(&th.src); 
  274.     jpeg_destroy_compress(&th.dst); 
  275.  
  276.     /* replace thumbnail */ 
  277.     free(ed->data); 
  278.     ed->data = th.out; 
  279.     ed->size = th.osize; 
  280.  
  281. static void do_exif(struct jpeg_decompress_struct *src, 
  282.             JXFORM_CODE *transform, 
  283.             char *thumbnail,int tsize, 
  284.             unsigned int flags) 
  285.     jpeg_saved_marker_ptr mark; 
  286.     ExifData *ed = NULL; 
  287.     unsigned char *data; 
  288.     unsigned int  size; 
  289.      
  290.     for (mark = src->marker_list; NULL != mark; mark = mark->next) { 
  291.     if (mark->marker != JPEG_APP0 +1) 
  292.         continue
  293.     ed = exif_data_new_from_data(mark->data,mark->data_length); 
  294.     break
  295.     } 
  296.     if (flags & JFLAG_UPDATE_THUMBNAIL) { 
  297.     if (NULL == ed) 
  298.         ed = exif_data_new(); 
  299.     if (NULL == mark) { 
  300.         mark = src->mem->alloc_large((j_common_ptr)src,JPOOL_IMAGE,sizeof(*mark)); 
  301.         memset(mark,0,sizeof(*mark)); 
  302.         mark->marker = JPEG_APP0 +1; 
  303.         mark->next = src->marker_list; 
  304.         src->marker_list = mark; 
  305.     } 
  306.     if (ed->data) 
  307.         free(ed->data); 
  308.     ed->data = thumbnail; 
  309.     ed->size = tsize; 
  310.     } 
  311.     if (NULL == ed) 
  312.     return
  313.  
  314.     if (-1 == *transform) { 
  315.     /* automagic image transformation */ 
  316.     int orientation = get_orientation(ed); 
  317.     *transform = JXFORM_NONE; 
  318.     if (orientation >= 1 && orientation <= 8) 
  319.         *transform = transmagic[orientation]; 
  320. #if 0 
  321.     if (debug) 
  322.         fprintf(stderr,"autotrans: %s\n",transname[*transform]); 
  323. #endif 
  324.     } 
  325.  
  326.     /* update exif data */ 
  327.     if (flags & JFLAG_UPDATE_ORIENTATION) { 
  328.     update_orientation(ed,EXIF_IFD_0,1); 
  329.     update_orientation(ed,EXIF_IFD_1,1); 
  330.     } 
  331.     if (ed->data && ed->data[0] == 0xff && ed->data[1] == 0xd8 && 
  332.     (flags & JFLAG_TRANSFORM_THUMBNAIL)) 
  333.     do_thumbnail(ed,*transform); 
  334.     update_dimension(ed, (flags & JFLAG_TRANSFORM_IMAGE) ? *transform : JXFORM_NONE, 
  335.              src->image_width, src->image_height); 
  336.  
  337.     /* build new exif data block */ 
  338.     exif_data_save_data(ed,&data,&size); 
  339.     exif_data_unref(ed); 
  340.  
  341.     /* update jpeg APP1 (EXIF) marker */ 
  342.     mark->data = src->mem->alloc_large((j_common_ptr)src,JPOOL_IMAGE,size); 
  343.     mark->original_length = size; 
  344.     mark->data_length = size; 
  345.     memcpy(mark->data,data,size); 
  346.     free(data); 
  347.  
  348. /* ---------------------------------------------------------------------- */ 
  349.  
  350. static void do_comment(struct jpeg_decompress_struct *src, 
  351.                unsigned char *comment) 
  352.     jpeg_saved_marker_ptr mark; 
  353.     int size; 
  354.  
  355.     /* find or create comment marker */ 
  356.     for (mark = src->marker_list;; mark = mark->next) { 
  357.     if (mark->marker == JPEG_COM) 
  358.         break
  359.     if (NULL == mark->next) { 
  360.         mark->next = src->mem->alloc_large((j_common_ptr)src,JPOOL_IMAGE, 
  361.                            sizeof(*mark)); 
  362.         mark = mark->next; 
  363.         memset(mark,0,sizeof(*mark)); 
  364.         mark->marker = JPEG_COM; 
  365.         break
  366.     } 
  367.     } 
  368.  
  369.     /* update comment marker */ 
  370.     size = strlen(comment) +1; 
  371.     mark->data = src->mem->alloc_large((j_common_ptr)src,JPOOL_IMAGE,size); 
  372.     mark->original_length = size; 
  373.     mark->data_length = size; 
  374.     memcpy(mark->data,comment,size); 
  375.  
  376. static int do_transform(struct jpeg_decompress_struct *src, 
  377.             struct jpeg_compress_struct *dst, 
  378.             JXFORM_CODE transform, 
  379.             unsigned char *comment, 
  380.             char *thumbnail, int tsize, 
  381.             unsigned int flags) 
  382.     jvirt_barray_ptr * src_coef_arrays; 
  383.     jvirt_barray_ptr * dst_coef_arrays; 
  384.     jpeg_transform_info transformoption; 
  385.  
  386.     jcopy_markers_setup(src, JCOPYOPT_ALL); 
  387.     if (JPEG_HEADER_OK != jpeg_read_header(src, TRUE)) 
  388.     return -1; 
  389.  
  390.     do_exif(src,&transform,thumbnail,tsize,flags); 
  391.     if (-1 == transform) 
  392.     transform = JXFORM_NONE; 
  393.     if (!(flags & JFLAG_TRANSFORM_IMAGE)) 
  394.     transform = JXFORM_NONE; 
  395.     if ((flags & JFLAG_UPDATE_COMMENT) && NULL != comment) 
  396.     do_comment(src,comment); 
  397.  
  398.     memset(&transformoption,0,sizeof(transformoption)); 
  399.     transformoption.transform = transform; 
  400.     transformoption.trim      = FALSE; 
  401.     transformoption.force_grayscale = FALSE; 
  402.  
  403.     /* Any space needed by a transform option must be requested before
  404.      * jpeg_read_coefficients so that memory allocation will be done right.
  405.      */ 
  406.     jtransform_request_workspace(src, &transformoption); 
  407.     src_coef_arrays = jpeg_read_coefficients(src); 
  408.     jpeg_copy_critical_parameters(src, dst); 
  409.     dst_coef_arrays = jtransform_adjust_parameters 
  410.     (src, dst, src_coef_arrays, &transformoption); 
  411.      
  412.     /* Start compressor (note no image data is actually written here) */ 
  413.     jpeg_write_coefficients(dst, dst_coef_arrays); 
  414.      
  415.     /* Copy to the output file any extra markers that we want to preserve */ 
  416.     jcopy_markers_execute(src, dst, JCOPYOPT_ALL); 
  417.      
  418.     /* Execute image transformation, if any */ 
  419.     jtransform_execute_transformation(src, dst, 
  420.                       src_coef_arrays, 
  421.                       &transformoption); 
  422.      
  423.     /* Finish compression and release memory */ 
  424.     jpeg_finish_compress(dst); 
  425.     jpeg_finish_decompress(src); 
  426.  
  427.     return 0; 
  428.  
  429. /* ---------------------------------------------------------------------- */ 
  430.  
  431. int jpeg_transform_fp(FILE *in,FILE *out, 
  432.               JXFORM_CODE transform, 
  433.               unsigned char *comment, 
  434.               char *thumbnail, int tsize, 
  435.               unsigned int flags) 
  436.     struct jpeg_decompress_struct src; 
  437.     struct jpeg_compress_struct   dst; 
  438.     struct jpeg_error_mgr jdsterr; 
  439.     struct longjmp_error_mgr jsrcerr; 
  440.      
  441.     /* setup src */ 
  442.     src.err = jpeg_std_error(&jsrcerr.jpeg); 
  443.     jsrcerr.jpeg.error_exit = longjmp_error_exit; 
  444.     if (setjmp(jsrcerr.setjmp_buffer)) 
  445.     /* something went wrong within the jpeg library ... */ 
  446.     goto oops; 
  447.     jpeg_create_decompress(&src); 
  448.     jpeg_stdio_src(&src, in); 
  449.      
  450.     /* setup dst */ 
  451.     dst.err = jpeg_std_error(&jdsterr); 
  452.     jpeg_create_compress(&dst); 
  453.     jpeg_stdio_dest(&dst, out); 
  454.  
  455.     /* transform image */ 
  456.     do_transform(&src,&dst,transform,comment,thumbnail,tsize,flags); 
  457.  
  458.     /* cleanup */ 
  459.     jpeg_destroy_decompress(&src); 
  460.     jpeg_destroy_compress(&dst); 
  461.     return 0; 
  462.  
  463. oops: 
  464.     jpeg_destroy_decompress(&src); 
  465.     jpeg_destroy_compress(&dst); 
  466.     return -1; 
  467.  
  468. int jpeg_transform_files(char *infile,char *outfile, 
  469.              JXFORM_CODE transform, 
  470.              unsigned char *comment, 
  471.              char *thumbnail,int tsize, 
  472.              unsigned int flags) 
  473.     int rc; 
  474.     FILE *in; 
  475.     FILE *out; 
  476.      
  477.     /* open infile */ 
  478.     in = fopen(infile,"r"); 
  479.     if (NULL == in) { 
  480.     fprintf(stderr,"open %s: %s\n",infile,strerror(errno)); 
  481.     return -1; 
  482.     } 
  483.      
  484.     /* open outfile */ 
  485.     out = fopen(outfile,"w"); 
  486.     if (NULL == out) { 
  487.     fprintf(stderr,"open %s: %s\n",outfile,strerror(errno)); 
  488.     fclose(in); 
  489.     return -1; 
  490.     } 
  491.  
  492.     /* go! */ 
  493.     rc = jpeg_transform_fp(in,out,transform,comment,thumbnail,tsize,flags); 
  494.     fclose(in); 
  495.     fclose(out); 
  496.  
  497.     return rc; 
  498.  
  499. int jpeg_transform_inplace(char *file, 
  500.                JXFORM_CODE transform, 
  501.                unsigned char *comment, 
  502.                char *thumbnail, int tsize, 
  503.                unsigned int flags) 
  504.     char *tmpfile; 
  505.     char *bakfile; 
  506.     struct stat st; 
  507.     int fd; 
  508.     FILE *in  = NULL; 
  509.     FILE *out = NULL; 
  510.  
  511.     /* are we allowed to write to the file? */ 
  512.     if (0 != access(file,W_OK)) { 
  513.     fprintf(stderr,"access %s: %s\n",file,strerror(errno)); 
  514.     return -1; 
  515.     } 
  516.  
  517.     /* open infile */ 
  518.     in = fopen(file,"r"); 
  519.     if (NULL == in) { 
  520.     fprintf(stderr,"open %s: %s\n",file,strerror(errno)); 
  521.     return -1; 
  522.     } 
  523.      
  524.     /* open tmpfile */ 
  525.     tmpfile = malloc(strlen(file)+10); 
  526.     sprintf(tmpfile,"%s.XXXXXX",file); 
  527.     fd = mkstemp(tmpfile); 
  528.     if (-1 == fd) { 
  529.     fprintf(stderr,"mkstemp(%s): %s\n",tmpfile,strerror(errno)); 
  530.     goto oops; 
  531.     } 
  532.     out = fdopen(fd,"w"); 
  533.  
  534.     /* copy owner and permissions */ 
  535.     if (-1 == fstat(fileno(in),&st)) { 
  536.     fprintf(stderr,"fstat(%s): %s\n",file,strerror(errno)); 
  537. //  goto oops; 
  538.     } 
  539.     if (-1 == fchown(fileno(out),st.st_uid,st.st_gid)) { 
  540.     fprintf(stderr,"fchown(%s): %s\n",tmpfile,strerror(errno)); 
  541. //  goto oops; 
  542.     } 
  543.     if (-1 == fchmod(fileno(out),st.st_mode)) { 
  544.     fprintf(stderr,"fchmod(%s): %s\n",tmpfile,strerror(errno)); 
  545. //  goto oops; 
  546.     } 
  547.  
  548.     /* transform */ 
  549.     if (0 != jpeg_transform_fp(in,out,transform,comment,thumbnail,tsize,flags)) 
  550.     goto oops; 
  551.  
  552.     /* worked ok -- commit */ 
  553.     fclose(in); 
  554.     fclose(out); 
  555.     if (flags & JFLAG_FILE_BACKUP) { 
  556.     bakfile = malloc(strlen(file)+2); 
  557.     sprintf(bakfile,"%s~",file); 
  558.     rename(file,bakfile); 
  559.     free(bakfile); 
  560.     } 
  561.     rename(tmpfile,file); 
  562.     if (flags & JFLAG_FILE_KEEP_TIME) { 
  563.     struct utimbuf u; 
  564.     u.actime = st.st_atime; 
  565.     u.modtime = st.st_mtime; 
  566.     utime(file,&u); 
  567.     } 
  568.          
  569.     /* cleanup & return */ 
  570.     free(tmpfile); 
  571.     return 0; 
  572.  
  573. oops: 
  574.     /* something went wrong -- rollback */ 
  575.     if (in) 
  576.     fclose(in); 
  577.     if (out) { 
  578.     fclose(out); 
  579.     unlink(tmpfile); 
  580.     } 
  581.     return -1; 
  582. }</span> 
0 0
原创粉丝点击