ftp.nice.ch/pub/next/connectivity/news/NewsBase.3.02.s.tar.gz#/NewsBase302.source/jpegv3/nxJfif.c

This is nxJfif.c in view mode; [Download] [Up]

/* write_jfif() converts NeXT raster bitmaps into a JPEG stream.
 * front end to Independent JPEG Group's software. 
 * For conditions of distribution and use, see the accompanying README file.
 */

/*
 * Include file for declaring JPEG data structures.
 * This file also includes some system headers like <stdio.h>;
 * if you prefer, you can include "jconfig.h" and "jpegdata.h" instead.
 */

#include <c.h>
#include <libc.h>
#include "jinclude.h"
#include <streams/streams.h>


static unsigned char *ptr;
static int alpha;
static int delta;

static void
no_op(compress_info_ptr cinfo)
{
}

static void
get_input_row (compress_info_ptr cinfo, JSAMPARRAY pixel_row)
/* Read next row of pixels into pixel_row[][] */
{
  register JSAMPROW ptr0, ptr1, ptr2;
  register long col;

  if (cinfo->input_components == 1 && alpha == 0) {
    // grayscale no alpha
    bcopy(ptr, pixel_row[0], cinfo->image_width);
    ptr += cinfo->image_width + delta;
    return;
  } else if (cinfo->input_components == 3) {
    // color with or without alpha
    ptr0 = pixel_row[0];
    ptr1 = pixel_row[1];
    ptr2 = pixel_row[2];
    for (col = 0; col < cinfo->image_width; col++) {
      *ptr0++ = (JSAMPLE) *ptr++; /* red */
      *ptr1++ = (JSAMPLE) *ptr++; /* green */
      *ptr2++ = (JSAMPLE) *ptr++; /* blue */
      if (alpha) {
        ++ptr;
      }
    }
    ptr += delta;
    return;
  } else if (cinfo->input_components == 1 && alpha == 1) {
    // grayscale and alpha
    ptr0 = pixel_row[0];
    for (col = 0; col < cinfo->image_width; col++) {
      *ptr0++ = (JSAMPLE) *ptr; 
      ptr += 2;
    }
    ptr += delta;
    return;
  } else {
    fprintf(stderr, "%d is illegal number of color components.\n",
      cinfo->input_components);
    exit(-1);
  }
}

/*
 * This routine must determine what output JPEG file format is to be written,
 * and make any other compression parameter changes that are desirable.
 * This routine gets control after the input file header has been read
 * (i.e., right after input_init has been called).  You could combine its
 * functions into input_init, or even into the main control routine, but
 * if you have several different input_init routines, it's a definite win
 * to keep this separate.  You MUST supply this routine even if it's a no-op.
 */

static void
c_ui_method_selection (compress_info_ptr cinfo)
{
  /* If the input is gray scale, generate a monochrome JPEG file. */
  if (cinfo->in_color_space == CS_GRAYSCALE)
    j_monochrome_default(cinfo);
  /* For now, always select JFIF output format. */
  jselwjfif(cinfo);
}

/* write_jfif() is used to convert a NeXT bitmap into a JPEG stream.
 * It can handle bitmaps with 8 bits per sample only.  bpp can be used
 * to specify the presence of the aplpha component and bytesPerRow can
 * be used specify the presence of row padding.
 */

void write_jfif(NXStream *stream, unsigned char *data, int width, int height,
    int spp, int bps, int bpp, int bytesPerRow, int quality)
{
  /* These three structs contain JPEG parameters and working data.
   * They must survive for the duration of parameter setup and one
   * call to jpeg_compress; typically, making them local data in the
   * calling routine is the best strategy.
   */
  struct compress_info_struct cinfo;
  struct compress_methods_struct c_methods;
  struct external_methods_struct e_methods;

    cinfo.image_width = width;           /* width in pixels */
    cinfo.image_height = height;         /* height in pixels */
    cinfo.input_components = spp;        /* or 1 for grayscale */
    if (spp == 3 || spp == 4) {
        spp = 3;
        cinfo.in_color_space = CS_RGB;   /* or CS_GRAYSCALE for grayscale */
    } else if (spp == 1 || spp == 2) {
        spp = 1;
        cinfo.in_color_space = CS_GRAYSCALE;
    } else {
        fprintf(stderr, "%d is illegal for samples/pixel.\n", spp);
        exit(-1);
    }
    if (bps != 8) {
        fprintf(stderr, "%d is illegal for bits/samples.\n", bps);
    }		
    cinfo.data_precision = bps;       /* bits per pixel component value */
    alpha = (bpp - spp * bps) / 8;    /* take care of alpha component */
    delta = bytesPerRow - (bpp * width) / 8;  /* take care of row fill bytes */
  /* Initialize the system-dependent method pointers. */
  cinfo.methods = &c_methods;	/* links to method structs */
  cinfo.emethods = &e_methods;
  /* Here we use the default JPEG error handler, which will just print
   * an error message on stderr and call exit().  See the second half of
   * this file for an example of more graceful error recovery.
   */
  jselerror(&e_methods);	/* select std error/trace message routines */
  /* Here we use the standard memory manager provided with the JPEG code.
   * In some cases you might want to replace the memory manager, or at
   * least the system-dependent part of it, with your own code.
   */
  jselmemmgr(&e_methods);	/* select std memory allocation routines */
  /* If the compressor requires full-image buffers (for entropy-coding
   * optimization or a noninterleaved JPEG file), it will create temporary
   * files for anything that doesn't fit within the maximum-memory setting.
   * (Note that temp files are NOT needed if you use the default parameters.)
   * You can change the default maximum-memory setting by changing
   * e_methods.max_memory_to_use after jselmemmgr returns.
   * On some systems you may also need to set up a signal handler to
   * ensure that temporary files are deleted if the program is interrupted.
   * (This is most important if you are on MS-DOS and use the jmemdos.c
   * memory manager back end; it will try to grab extended memory for
   * temp files, and that space will NOT be freed automatically.)
   * See jcmain.c or jdmain.c for an example signal handler.
   */

  /* Here, set up pointers to your own routines for input data handling
   * and post-init parameter selection.
   */
  c_methods.input_init = no_op;
  c_methods.get_input_row = get_input_row;
  c_methods.input_term = no_op;
  c_methods.c_ui_method_selection = c_ui_method_selection;

  /* Set up default JPEG parameters in the cinfo data structure. */
  j_c_defaults(&cinfo, quality, FALSE);
  /* Note: 75 is the recommended default quality level; you may instead pass
   * a user-specified quality level.  Be aware that values below 25 will cause
   * non-baseline JPEG files to be created (and a warning message to that
   * effect to be emitted on stderr).  This won't bother our decoder, but some
   * commercial JPEG implementations may choke on non-baseline JPEG files.
   * If you want to force baseline compatibility, pass TRUE instead of FALSE.
   * (If non-baseline files are fine, but you could do without that warning
   * message, set e_methods.trace_level to -1.)
   */

  /* At this point you can modify the default parameters set by j_c_defaults
   * as needed.  For a minimal implementation, you shouldn't need to change
   * anything.  See jcmain.c for some examples of what you might change.
   */

  cinfo.input_file = NULL;	/* if no actual input file involved */
  cinfo.output_file = stream;
  ptr = data;
  jpeg_compress(&cinfo);

  /* Note: if you want to compress more than one image, we recommend you
   * repeat this whole routine.  You MUST repeat the j_c_defaults()/alter
   * parameters/jpeg_compress() sequence, as some data structures allocated
   * in j_c_defaults are freed upon exit from jpeg_compress.
   */
}



These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.