caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Florent Monnier <fmonnier@linux-nantes.fr.eu.org>
To: caml-list@yquem.inria.fr
Subject: Re: [Caml-list] Portable PNG exporter
Date: Mon, 22 Sep 2008 16:47:21 +0200	[thread overview]
Message-ID: <200809221647.21886.fmonnier@linux-nantes.fr.eu.org> (raw)
In-Reply-To: <20080920230351.GA9757@annexia.org>

> For reference, I've found the easiest way to export PNGs (in any
> language, not just OCaml) is to use netpbm.

Probably with any language, but perhaps not any OS ?

>                                              Simply fork pnmtopng
> using Unix.open_process_out and write a PPM file.  A PPM file has such
> a simple format that you can write it directly from just about any
> language, even a shell script.
>
>   P3 <width> <height> 255
>   followed by <width>x<height>x3 RGB triplets (in decimal, separated
>   by writespace)

You can reduce the amount of exchanged datas using binary ppm instead of ascii 
ppm. In such case the format is:

  P6\n<width in ascii> <height in ascii>\n255\n
  followed by <width>x<height>x3 RGB triplets of octect (in binary)

Here is the OCaml code I use, as well for jpeg:

let output_ppm ~oc ~img:(_, r_channel, g_channel, b_channel) =
  let width = Bigarray.Array2.dim1 r_channel
  and height = Bigarray.Array2.dim2 r_channel in
  Printf.fprintf oc "P6\n%d %d\n255\n" width height;
  for y = 0 to pred height do
    for x = 0 to pred width do
      (* output_byte doesn't raise any exception about the range *)
      output_char oc (char_of_int r_channel.{x,y});
      output_char oc (char_of_int g_channel.{x,y});
      output_char oc (char_of_int b_channel.{x,y});
    done;
  done;
  output_char oc '\n';
  flush oc
;;

(* you can use different conversion commands (convert is from ImageMagick) *)
let print_jpeg ~img ?(quality=96) () =
  let cmd = Printf.sprintf "cjpeg -quality %d" quality in
  (*
  let cmd = Printf.sprintf "ppmtojpeg -quality %d" quality in
  let cmd = Printf.sprintf "convert ppm:- -quality %d jpg:-" quality in
  *)
  let ic, oc = Unix.open_process cmd in
  output_ppm ~img ~oc;
  try
    while true do
      let c = input_char ic in
      print_char c
    done
  with End_of_file -> ()
;;

(* output any of the hundred formats ImageMagick knows *)
let print_file ~img ~format =
  let cmd = Printf.sprintf "convert ppm:- %s:-" format in
  let ic, oc = Unix.open_process cmd in
  output_ppm ~img ~oc;
  try
    while true do
      let c = input_char ic in
      print_char c
    done
  with End_of_file -> ()
;;

let new_img ~width ~height =
  let all_channels =
    let kind = Bigarray.int8_unsigned
    and layout = Bigarray.c_layout
    in
    Bigarray.Array3.create kind layout 3 width height
  in
  let r_channel = Bigarray.Array3.slice_left_2 all_channels 0
  and g_channel = Bigarray.Array3.slice_left_2 all_channels 1
  and b_channel = Bigarray.Array3.slice_left_2 all_channels 2
  in
  (all_channels,
   r_channel,
   g_channel,
   b_channel)
;;
_________________________________________

Anyway I'm very pleased to see this png exporter, while it's allways usefull 
to remove an external dependency !
Thanks for this piece of code !

-- 
Florent


  reply	other threads:[~2008-09-22 18:49 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-09-20 17:37 Janne Hellsten
2008-09-20 23:03 ` [Caml-list] " Richard Jones
2008-09-22 14:47   ` Florent Monnier [this message]
2008-09-22 14:59   ` Janne Hellsten
2008-09-22 15:56     ` Daniel Bünzli
2008-09-21  0:47 ` Jon Harrop
2008-09-21 19:50 ` malc
2008-09-21 20:02   ` Janne Hellsten

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200809221647.21886.fmonnier@linux-nantes.fr.eu.org \
    --to=fmonnier@linux-nantes.fr.eu.org \
    --cc=caml-list@yquem.inria.fr \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).