example.c
上传用户:zlh9724
上传日期:2007-01-04
资源大小:1991k
文件大小:15k
源码类别:

浏览器

开发平台:

Unix_Linux

  1. /* example.c - an example of using libpng */
  2. /* this is an example of how to use libpng to read and write
  3.    png files.  The file libpng.txt is much more verbose then
  4.    this.  If you have not read it, do so first.  This was
  5.    designed to be a starting point of an implementation.
  6.    This is not officially part of libpng, and therefore
  7.    does not require a copyright notice.
  8.    This file does not currently compile, because it is missing
  9.    certain parts, like allocating memory to hold an image.
  10.    You will have to supply these parts to get it to compile.
  11.    */
  12. #include <png.h>
  13. /* check to see if a file is a png file using png_check_sig() */
  14. int check_png(char * file_name)
  15. {
  16.    FILE *fp;
  17.    char buf[8];
  18.    int ret;
  19.    fp = fopen(file_name, "rb");
  20.    if (!fp)
  21.       return 0;
  22.    ret = fread(buf, 1, 8, fp);
  23.    fclose(fp);
  24.    if (ret != 8)
  25.       return 0;
  26.    ret = png_check_sig(buf, 8);
  27.    return (ret);
  28. }
  29. /* read a png file.  You may want to return an error code if the read
  30.    fails (depending upon the failure). */
  31. void read_png(char *file_name)
  32. {
  33.    FILE *fp;
  34. png_structp png_ptr;
  35.    png_infop info_ptr;
  36.    /* open the file */
  37.    fp = fopen(file_name, "rb");
  38.    if (!fp)
  39.       return;
  40.    /* allocate the necessary structures */
  41.    png_ptr = malloc(sizeof (png_struct));
  42.    if (!png_ptr)
  43.    {
  44.       fclose(fp);
  45.       return;
  46.    }
  47.    info_ptr = malloc(sizeof (png_info));
  48.    if (!info_ptr)
  49.    {
  50.       fclose(fp);
  51.       free(png_ptr);
  52.       return;
  53.    }
  54.    /* set error handling */
  55.    if (setjmp(png_ptr->jmpbuf))
  56.    {
  57.       png_read_destroy(png_ptr, info_ptr, (png_info *)0);
  58.       fclose(fp);
  59.       free(png_ptr);
  60.       free(info_ptr);
  61.       /* If we get here, we had a problem reading the file */
  62.       return;
  63.    }
  64.    /* initialize the structures, info first for error handling */
  65.    png_info_init(info_ptr);
  66.    png_read_init(png_ptr);
  67.    /* set up the input control if you are using standard C streams */
  68.    png_init_io(png_ptr, fp);
  69. /* if you are using replacement read functions, here you would call */
  70. png_set_read_fn(png_ptr, (void *)io_ptr, user_read_fn);
  71. /* where io_ptr is a structure you want available to the callbacks */
  72. /* if you are using replacement message functions, here you would call */
  73. png_set_message_fn(png_ptr, (void *)msg_ptr, user_error_fn, user_warning_fn);
  74. /* where msg_ptr is a structure you want available to the callbacks */
  75. /* read the file information */
  76. png_read_info(png_ptr, info_ptr);
  77. /* set up the transformations you want.  Note that these are
  78.       all optional.  Only call them if you want them */
  79.    /* expand paletted colors into true rgb */
  80.    if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
  81.       png_set_expand(png_ptr);
  82.    /* expand grayscale images to the full 8 bits */
  83.    if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY &&
  84.       info_ptr->bit_depth < 8)
  85.       png_set_expand(png_ptr);
  86.    /* expand images with transparency to full alpha channels */
  87.    if (info_ptr->valid & PNG_INFO_tRNS)
  88.       png_set_expand(png_ptr);
  89.    /* Set the background color to draw transparent and alpha
  90. images over */
  91.    png_color_16 my_background;
  92.    if (info_ptr->valid & PNG_INFO_bKGD)
  93.       png_set_background(png_ptr, &(info_ptr->background),
  94. PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
  95. else
  96. png_set_background(png_ptr, &my_background,
  97.          PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
  98.    /* tell libpng to handle the gamma conversion for you */
  99.    if (info_ptr->valid & PNG_INFO_gAMA)
  100.       png_set_gamma(png_ptr, screen_gamma, info_ptr->gamma);
  101.    else
  102.       png_set_gamma(png_ptr, screen_gamma, 0.45);
  103.    /* tell libpng to strip 16 bit depth files down to 8 bits */
  104.    if (info_ptr->bit_depth == 16)
  105. png_set_strip_16(png_ptr);
  106.    /* dither rgb files down to 8 bit palettes & reduce palettes
  107.       to the number of colors available on your screen */
  108.    if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
  109.    {
  110.       if (info_ptr->valid & PNG_INFO_PLTE)
  111.          png_set_dither(png_ptr, info_ptr->palette,
  112.             info_ptr->num_palette, max_screen_colors,
  113.                info_ptr->histogram);
  114.       else
  115.       {
  116.          png_color std_color_cube[MAX_SCREEN_COLORS] =
  117.             {/* ... colors ... */};
  118.          png_set_dither(png_ptr, std_color_cube, MAX_SCREEN_COLORS,
  119.             MAX_SCREEN_COLORS, NULL);
  120.       }
  121. }
  122.    /* invert monocrome files */
  123.    if (info_ptr->bit_depth == 1 &&
  124.       info_ptr->color_type == PNG_COLOR_GRAY)
  125.       png_set_invert(png_ptr);
  126.    /* shift the pixels down to their true bit depth */
  127.    if (info_ptr->valid & PNG_INFO_sBIT &&
  128.       info_ptr->bit_depth > info_ptr->sig_bit)
  129.       png_set_shift(png_ptr, &(info_ptr->sig_bit));
  130.    /* pack pixels into bytes */
  131.    if (info_ptr->bit_depth < 8)
  132.       png_set_packing(png_ptr);
  133.    /* flip the rgb pixels to bgr */
  134.    if (info_ptr->color_type == PNG_COLOR_TYPE_RGB ||
  135. info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
  136.       png_set_bgr(png_ptr);
  137.    /* swap bytes of 16 bit files to least significant bit first */
  138.    if (info_ptr->bit_depth == 16)
  139.       png_set_swap(png_ptr);
  140.    /* add a filler byte to rgb files */
  141.    if (info_ptr->bit_depth == 8 &&
  142.       info_ptr->color_type == PNG_COLOR_TYPE_RGB)
  143.       png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
  144.    /* turn on interlace handling if you are not using png_read_image() */
  145.    if (info_ptr->interlace_type)
  146.       number_passes = png_set_interlace_handling(png_ptr);
  147.    else
  148.       number_passes = 1;
  149. /* optional call to update palette with transformations */
  150.    png_start_read_image(png_ptr);
  151.    /* optional call to update the info structure */
  152.    png_read_update_info(png_ptr, info_ptr);
  153.    /* allocate the memory to hold the image using the fields
  154.       of png_info. */
  155.    /* the easiest way to read the image */
  156.    png_bytep row_pointers[height];
  157.    png_read_image(png_ptr, row_pointers);
  158.    /* the other way to read images - deal with interlacing */
  159.    for (pass = 0; pass < number_passes; pass++)
  160.    {
  161.       /* Read the image using the "sparkle" effect. */
  162. png_read_rows(png_ptr, row_pointers, NULL, number_of_rows);
  163.       /* If you are only reading on row at a time, this works */
  164.       for (y = 0; y < height; y++)
  165.       {
  166.          png_bytep row_pointers = row[y];
  167.          png_read_rows(png_ptr, &row_pointers, NULL, 1);
  168.       }
  169.       /* to get the rectangle effect, use the third parameter */
  170.       png_read_rows(png_ptr, NULL, row_pointers, number_of_rows);
  171.       /* if you want to display the image after every pass, do
  172.          so here */
  173.    }
  174.    /* read the rest of the file, getting any additional chunks
  175.       in info_ptr */
  176. png_read_end(png_ptr, info_ptr);
  177.    /* clean up after the read, and free any memory allocated */
  178.    png_read_destroy(png_ptr, info_ptr, (png_infop)0);
  179.    /* free the structures */
  180.    free(png_ptr);
  181.    free(info_ptr);
  182.    /* close the file */
  183.    fclose(fp);
  184.    /* that's it */
  185.    return;
  186. }
  187. /* progressively read a file */
  188. /* these will normally not be global unless you are only
  189. reading in one image at a time */
  190. png_structp png_ptr;
  191. png_infop info_ptr;
  192. int
  193. initialize_png_reader()
  194. {
  195. png_ptr = malloc(sizeof (png_struct));
  196. if (!png_ptr)
  197. return -1;
  198. info_ptr = malloc(sizeof (png_info));
  199. if (!info_ptr)
  200. {
  201. free(png_ptr);
  202. return -1;
  203. }
  204. if (setjmp(png_ptr->jmpbuf))
  205. {
  206. png_read_destroy(png_ptr, info_ptr, (png_info *)0);
  207. /* free pointers before returning, if necessary */
  208. free(png_ptr);
  209. free(info_ptr);
  210. return -1;
  211. }
  212. png_info_init(info_ptr);
  213. png_read_init(png_ptr);
  214. /* this one's new.  You will need to provide all three
  215. function callbacks, even if you aren't using them all.
  216. You can put a void pointer in place of the NULL, and
  217. retrieve the pointer from inside the callbacks using
  218. the function png_get_progressive_ptr(png_ptr); */
  219. png_set_progressive_read_fn(png_ptr, NULL,
  220. info_callback, row_callback, end_callback);
  221. return 0;
  222. }
  223. int
  224. process_data(png_bytep buffer, png_uint_32 length)
  225. {
  226. if (setjmp(png_ptr->jmpbuf))
  227. {
  228. png_read_destroy(png_ptr, info_ptr, (png_info *)0);
  229. free(png_ptr);
  230. free(info_ptr);
  231. return -1;
  232. }
  233. /* this one's new also.  Simply give it a chunk of data
  234. from the file stream (in order, of course).  On Segmented
  235. machines, don't give it any more then 64K.  The library
  236. seems to run fine with sizes of 4K, although you can give
  237. it much less if necessary (I assume you can give it chunks
  238. of 1 byte, but I haven't tried less then 256 bytes yet).
  239. When this function returns, you may want to display any
  240. rows that were generated in the row callback. */
  241. png_process_data(png_ptr, info_ptr, buffer, length);
  242. return 0;
  243. }
  244. info_callback(png_structp png_ptr, png_infop info)
  245. {
  246. /* do any setup here, including setting any of the transformations
  247. mentioned in the Reading PNG files section.  For now, you _must_
  248. call either png_start_read_image() or png_read_update_info()
  249. after all the transformations are set (even if you don't set
  250. any).  You may start getting rows before png_process_data()
  251. returns, so this is your last chance to prepare for that. */
  252. }
  253. row_callback(png_structp png_ptr, png_bytep new_row,
  254. png_uint_32 row_num, int pass)
  255. {
  256. /* this function is called for every row in the image.  If the
  257. image is interlacing, and you turned on the interlace handler,
  258. this function will be called for every row in every pass.
  259. Some of these rows will not be changed from the previous pass.
  260. When the row is not changed, the new_row variable will be NULL.
  261. The rows and passes are called in order, so you don't really
  262. need the row_num and pass, but I'm supplying them because it
  263. may make your life easier.
  264. For the non-NULL rows of interlaced images, you must call
  265. png_progressive_combine_row() passing in the row and the
  266. old row.  You can call this function for NULL rows (it will
  267. just return) and for non-interlaced images (it just does the
  268. memcpy for you) if it will make the code easier.  Thus, you
  269. can just do this for all cases: */
  270. png_progressive_combine_row(png_ptr, old_row, new_row);
  271. /* where old_row is what was displayed for previous rows.  Note
  272. that the first pass (pass == 0 really) will completely cover
  273. the old row, so the rows do not have to be initialized.  After
  274. the first pass (and only for interlaced images), you will have
  275. to pass the current row, and the function will combine the
  276. old row and the new row. */
  277. }
  278. end_callback(png_structp png_ptr, png_infop info)
  279. {
  280. /* this function is called when the whole image has been read,
  281. including any chunks after the image (up to and including
  282. the IEND).  You will usually have the same info chunk as you
  283. had in the header, although some data may have been added
  284. to the comments and time fields.
  285. Most people won't do much here, perhaps setting a flag that
  286. marks the image as finished. */
  287. }
  288. /* write a png file */
  289. void write_png(char *file_name, ... other image information ...)
  290. {
  291.    FILE *fp;
  292. png_structp png_ptr;
  293. png_infop info_ptr;
  294.    /* open the file */
  295.    fp = fopen(file_name, "wb");
  296.    if (!fp)
  297.       return;
  298.    /* allocate the necessary structures */
  299.    png_ptr = malloc(sizeof (png_struct));
  300.    if (!png_ptr)
  301.    {
  302.       fclose(fp);
  303.       return;
  304.    }
  305.    info_ptr = malloc(sizeof (png_info));
  306.    if (!info_ptr)
  307.    {
  308.       fclose(fp);
  309.       free(png_ptr);
  310.       return;
  311.    }
  312.    /* set error handling */
  313. if (setjmp(png_ptr->jmpbuf))
  314.    {
  315.       png_write_destroy(png_ptr);
  316.       fclose(fp);
  317.       free(png_ptr);
  318.       free(info_ptr);
  319.       /* If we get here, we had a problem reading the file */
  320.       return;
  321.    }
  322.    /* initialize the structures */
  323.    png_info_init(info_ptr);
  324.    png_write_init(png_ptr);
  325.    /* set up the output control if you are using standard C streams */
  326.    png_init_io(png_ptr, fp);
  327. /* if you are using replacement write functions, here you would call */
  328. png_set_write_fn(png_ptr, (void *)io_ptr, user_write_fn, user_flush_fn);
  329. /* where io_ptr is a structure you want available to the callbacks */
  330. /* if you are using replacement message functions, here you would call */
  331. png_set_message_fn(png_ptr, (void *)msg_ptr, user_error_fn, user_warning_fn);
  332. /* where msg_ptr is a structure you want available to the callbacks */
  333. /* set the file information here */
  334.    info_ptr->width = ;
  335.    info_ptr->height = ;
  336.    etc.
  337.    /* set the palette if there is one */
  338.    info_ptr->valid |= PNG_INFO_PLTE;
  339.    info_ptr->palette = malloc(256 * sizeof (png_color));
  340.    info_ptr->num_palette = 256;
  341.    ... set palette colors ...
  342.    /* optional significant bit chunk */
  343.    info_ptr->valid |= PNG_INFO_sBIT;
  344. /* if we are dealing with a grayscale image then */
  345. info_ptr->sig_bit.gray = true_bit_depth;
  346. /* otherwise, if we are dealing with a color image then */
  347. info_ptr->sig_bit.red = true_red_bit_depth;
  348. info_ptr->sig_bit.green = true_green_bit_depth;
  349. info_ptr->sig_bit.blue = true_blue_bit_depth;
  350. /* if the image has an alpha channel then */
  351.    info_ptr->sig_bit.alpha = true_alpha_bit_depth;
  352.   
  353. /* optional gamma chunk is strongly suggested if you have any guess
  354.    as to the correct gamma of the image */
  355. info_ptr->valid |= PNG_INFO_gAMA;
  356.    info_ptr->gamma = gamma;
  357.    /* other optional chunks */
  358.    /* write the file information */
  359.    png_write_info(png_ptr, info_ptr);
  360.    /* set up the transformations you want.  Note that these are
  361.       all optional.  Only call them if you want them */
  362.    /* invert monocrome pixels */
  363.    png_set_invert(png_ptr);
  364.    /* shift the pixels up to a legal bit depth and fill in
  365.       as appropriate to correctly scale the image */
  366.    png_set_shift(png_ptr, &(info_ptr->sig_bit));
  367.    /* pack pixels into bytes */
  368.    png_set_packing(png_ptr);
  369.    /* flip bgr pixels to rgb */
  370.    png_set_bgr(png_ptr);
  371.    /* swap bytes of 16 bit files to most significant bit first */
  372.    png_set_swap(png_ptr);
  373.    /* get rid of filler bytes, pack rgb into 3 bytes.  The
  374.       filler number is not used. */
  375.    png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
  376.    /* turn on interlace handling if you are not using png_write_image() */
  377.    if (interlacing)
  378.       number_passes = png_set_interlace_handling(png_ptr);
  379.    else
  380.       number_passes = 1;
  381.    /* the easiest way to write the image */
  382.    png_bytep row_pointers[height];
  383.    png_write_image(png_ptr, row_pointers);
  384.    /* the other way to write the image - deal with interlacing */
  385.    for (pass = 0; pass < number_passes; pass++)
  386.    {
  387.       /* Write a few rows at a time. */
  388.       png_write_rows(png_ptr, row_pointers, number_of_rows);
  389.       /* If you are only writing one row at a time, this works */
  390.       for (y = 0; y < height; y++)
  391.       {
  392.          png_bytep row_pointers = row[y];
  393.          png_write_rows(png_ptr, &row_pointers, 1);
  394.       }
  395.    }
  396.    /* write the rest of the file */
  397.    png_write_end(png_ptr, info_ptr);
  398.    /* clean up after the write, and free any memory allocated */
  399.    png_write_destroy(png_ptr);
  400.    /* if you malloced the palette, free it here */
  401.    if (info_ptr->palette)
  402.       free(info_ptr->palette);
  403.    /* free the structures */
  404.    free(png_ptr);
  405.    free(info_ptr);
  406.    /* close the file */
  407.    fclose(fp);
  408.    /* that's it */
  409.    return;
  410. }