Example #1
0
bool CBitmapShow::ResetPaletteColor(int*r,int*g,int*b)
{
     int NumberColors=GetNumberColors();
	 for(int k=0;k<NumberColors;k++) 
	 {
		 m_lpBitmapInfo->bmiColors[k].rgbRed=r[k];
	     m_lpBitmapInfo->bmiColors[k].rgbGreen=g[k];
	     m_lpBitmapInfo->bmiColors[k].rgbBlue=b[k];
	 }
	 return CreateDIBPalette();
} 
Example #2
0
bool CBitmapShow::InitialBitmap(int width,int height)
{
     if((Width==width)&&(Height==height)) return true;
	 Width=width;
	 Height=height;
	 if(m_lpBitmapInfo!=NULL) GlobalFreePtr(m_lpBitmapInfo);
	 int colors=GetNumberColors();
	 if(colors==0) colors=256;
	 m_lpBitmapInfo = (LPBITMAPINFO) GlobalAllocPtr(GHND,sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * colors);
	 m_lpBitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	 m_lpBitmapInfo->bmiHeader.biWidth = Width;
	 m_lpBitmapInfo->bmiHeader.biHeight = Height;
	 m_lpBitmapInfo->bmiHeader.biCompression=GetCompressionKind();
	 m_lpBitmapInfo->bmiHeader.biSizeImage = 0;
	 m_lpBitmapInfo->bmiHeader.biXPelsPerMeter = 0;
	 m_lpBitmapInfo->bmiHeader.biYPelsPerMeter = 0;
	 m_lpBitmapInfo->bmiHeader.biPlanes = 1;
	 m_lpBitmapInfo->bmiHeader.biBitCount =GetBitCount();
	 m_lpBitmapInfo->bmiHeader.biClrUsed = 0;
	 m_lpBitmapInfo->bmiHeader.biClrImportant = 0;
	 ILineBytes=WIDTHBYTES(Width*GetBitCount());
	 m_lpBitmapInfo->bmiHeader.biSizeImage=ILineBytes*Height;
     for(int k=0;k<colors;k++) m_lpBitmapInfo->bmiColors[k].rgbRed=m_lpBitmapInfo->bmiColors[k].rgbGreen=m_lpBitmapInfo->bmiColors[k].rgbBlue=k;
	 if(!CreateDIBPalette())
	 {
         if(m_lpBitmapInfo!=NULL) GlobalFreePtr(m_lpBitmapInfo);
         m_lpBitmapInfo=NULL;
		 return false;
	 }
	 if(lpDIBBits!=NULL) GlobalFreePtr(lpDIBBits);
     lpDIBBits=NULL;
     lpDIBBits=(unsigned char*)GlobalAllocPtr(GHND,ILineBytes*Height);
	 if(lpDIBBits==NULL)
	 {
         if(m_lpBitmapInfo!=NULL) GlobalFreePtr(m_lpBitmapInfo);
         m_lpBitmapInfo=NULL;
         if(Palette!=NULL) delete Palette;
		 Palette=NULL;
		 return false;
	 }
	 return true;
}
Example #3
0
BOOL CBitmapShow::CreateDIBPalette()
{
	if(Palette!=NULL)
	{
		delete Palette;
		Palette=NULL;
	}
	int NumberColors=GetNumberColors();
	if(NumberColors==0) return TRUE;
	CPalette*pPal;
	pPal=new CPalette;
	LPLOGPALETTE lpPal;
	HANDLE hLogPal;
	HPALETTE hPal=NULL;
	int i;
	hLogPal=::GlobalAlloc(GHND,sizeof(LOGPALETTE)+sizeof(PALETTEENTRY)*NumberColors);
	if(hLogPal==0)
	{
		delete pPal;
		return FALSE;
	}
	lpPal=(LPLOGPALETTE)::GlobalLock((HGLOBAL)hLogPal);
	lpPal->palVersion=PALVERSION;
	lpPal->palNumEntries=(WORD)NumberColors;
	for(int i=0;i<NumberColors;i++)
	{
		lpPal->palPalEntry[i].peRed=m_lpBitmapInfo->bmiColors[i].rgbRed;
		lpPal->palPalEntry[i].peGreen=m_lpBitmapInfo->bmiColors[i].rgbGreen;
		lpPal->palPalEntry[i].peBlue=m_lpBitmapInfo->bmiColors[i].rgbBlue;
		lpPal->palPalEntry[i].peFlags=0;
	}
	BOOL bResult=pPal->CreatePalette(lpPal);
	::GlobalUnlock((HGLOBAL)hLogPal);
	::GlobalFree((HGLOBAL)hLogPal);
    Palette=pPal;
    return bResult;
}
Example #4
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   W r i t e H I S T O G R A M I m a g e                                     %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  WriteHISTOGRAMImage() writes an image to a file in Histogram format.
%  The image shows a histogram of the color (or gray) values in the image.  The
%  image consists of three overlaid histograms:  a red one for the red channel,
%  a green one for the green channel, and a blue one for the blue channel.  The
%  image comment contains a list of unique pixel values and the number of times
%  each occurs in the image.
%
%  This method is strongly based on a similar one written by
%  [email protected] which in turn is based on ppmhistmap of netpbm.
%
%  The format of the WriteHISTOGRAMImage method is:
%
%      MagickBooleanType WriteHISTOGRAMImage(const ImageInfo *image_info,
%        Image *image,ExceptionInfo *exception)
%
%  A description of each parameter follows.
%
%    o image_info: the image info.
%
%    o image:  The image.
%
%    o exception: return any errors or warnings in this structure.
%
*/
static MagickBooleanType WriteHISTOGRAMImage(const ImageInfo *image_info,
  Image *image,ExceptionInfo *exception)
{
#define HistogramDensity  "256x200"

  char
    filename[MagickPathExtent];

  const char
    *option;

  Image
    *histogram_image;

  ImageInfo
    *write_info;

  MagickBooleanType
    status;

  PixelInfo
    *histogram;

  double
    maximum,
    scale;

  RectangleInfo
    geometry;

  register const Quantum
    *p;

  register Quantum
    *q,
    *r;

  register ssize_t
    x;

  size_t
    length;

  ssize_t
    y;

  /*
    Allocate histogram image.
  */
  assert(image_info != (const ImageInfo *) NULL);
  assert(image_info->signature == MagickCoreSignature);
  assert(image != (Image *) NULL);
  assert(image->signature == MagickCoreSignature);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
      image_info->filename);
  SetGeometry(image,&geometry);
  if (image_info->density == (char *) NULL)
    (void) ParseAbsoluteGeometry(HistogramDensity,&geometry);
  else
    (void) ParseAbsoluteGeometry(image_info->density,&geometry);
  histogram_image=CloneImage(image,geometry.width,geometry.height,MagickTrue,
    exception);
  if (histogram_image == (Image *) NULL)
    ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
  (void) SetImageStorageClass(histogram_image,DirectClass,exception);
  /*
    Allocate histogram count arrays.
  */
  length=MagickMax((size_t) ScaleQuantumToChar(QuantumRange)+1UL,
    histogram_image->columns);
  histogram=(PixelInfo *) AcquireQuantumMemory(length,sizeof(*histogram));
  if (histogram == (PixelInfo *) NULL)
    {
      histogram_image=DestroyImage(histogram_image);
      ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
    }
  /*
    Initialize histogram count arrays.
  */
  (void) ResetMagickMemory(histogram,0,length*sizeof(*histogram));
  for (y=0; y < (ssize_t) image->rows; y++)
  {
    p=GetVirtualPixels(image,0,y,image->columns,1,exception);
    if (p == (const Quantum *) NULL)
      break;
    for (x=0; x < (ssize_t) image->columns; x++)
    {
      if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
        histogram[ScaleQuantumToChar(GetPixelRed(image,p))].red++;
      if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
        histogram[ScaleQuantumToChar(GetPixelGreen(image,p))].green++;
      if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
        histogram[ScaleQuantumToChar(GetPixelBlue(image,p))].blue++;
      p+=GetPixelChannels(image);
    }
  }
  maximum=histogram[0].red;
  for (x=0; x < (ssize_t) histogram_image->columns; x++)
  {
    if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
        (maximum < histogram[x].red))
      maximum=histogram[x].red;
    if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
        (maximum < histogram[x].green))
      maximum=histogram[x].green;
    if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
        (maximum < histogram[x].blue))
      maximum=histogram[x].blue;
  }
  scale=0.0;
  if (fabs(maximum) >= MagickEpsilon)
    scale=(double) histogram_image->rows/maximum;
  /*
    Initialize histogram image.
  */
  (void) QueryColorCompliance("#000000",AllCompliance,
    &histogram_image->background_color,exception);
  (void) SetImageBackgroundColor(histogram_image,exception);
  for (x=0; x < (ssize_t) histogram_image->columns; x++)
  {
    q=GetAuthenticPixels(histogram_image,x,0,1,histogram_image->rows,exception);
    if (q == (Quantum *) NULL)
      break;
    if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
      {
        y=(ssize_t) ceil(histogram_image->rows-scale*histogram[x].red-0.5);
        r=q+y*GetPixelChannels(histogram_image);
        for ( ; y < (ssize_t) histogram_image->rows; y++)
        {
          SetPixelRed(histogram_image,QuantumRange,r);
          r+=GetPixelChannels(histogram_image);
        }
      }
    if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
      {
        y=(ssize_t) ceil(histogram_image->rows-scale*histogram[x].green-0.5);
        r=q+y*GetPixelChannels(histogram_image);
        for ( ; y < (ssize_t) histogram_image->rows; y++)
        {
          SetPixelGreen(histogram_image,QuantumRange,r);
          r+=GetPixelChannels(histogram_image);
        }
      }
    if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
      {
        y=(ssize_t) ceil(histogram_image->rows-scale*histogram[x].blue-0.5);
        r=q+y*GetPixelChannels(histogram_image);
        for ( ; y < (ssize_t) histogram_image->rows; y++)
        {
          SetPixelBlue(histogram_image,QuantumRange,r);
          r+=GetPixelChannels(histogram_image);
        }
      }
    if (SyncAuthenticPixels(histogram_image,exception) == MagickFalse)
      break;
    status=SetImageProgress(image,SaveImageTag,y,histogram_image->rows);
    if (status == MagickFalse)
      break;
  }
  histogram=(PixelInfo *) RelinquishMagickMemory(histogram);
  option=GetImageOption(image_info,"histogram:unique-colors");
  if ((option == (const char *) NULL) || (IsStringTrue(option) != MagickFalse))
    {
      FILE
        *file;

      int
        unique_file;

      /*
        Add a unique colors as an image comment.
      */
      file=(FILE *) NULL;
      unique_file=AcquireUniqueFileResource(filename);
      if (unique_file != -1)
        file=fdopen(unique_file,"wb");
      if ((unique_file != -1) && (file != (FILE *) NULL))
        {
          char
            *property;

          (void) GetNumberColors(image,file,exception);
          (void) fclose(file);
          property=FileToString(filename,~0UL,exception);
          if (property != (char *) NULL)
            {
              (void) SetImageProperty(histogram_image,"comment",property,
                exception);
              property=DestroyString(property);
            }
        }
      (void) RelinquishUniqueFileResource(filename);
    }
  /*
    Write Histogram image.
  */
  (void) CopyMagickString(histogram_image->filename,image_info->filename,
    MagickPathExtent);
  write_info=CloneImageInfo(image_info);
  *write_info->magick='\0';
  (void) SetImageInfo(write_info,1,exception);
  if ((*write_info->magick == '\0') ||
      (LocaleCompare(write_info->magick,"HISTOGRAM") == 0))
    (void) FormatLocaleString(histogram_image->filename,MagickPathExtent,
      "miff:%s",write_info->filename);
  histogram_image->blob=DetachBlob(histogram_image->blob);
  histogram_image->blob=CloneBlobInfo(image->blob);
  status=WriteImage(write_info,histogram_image,exception);
  image->blob=DetachBlob(image->blob);
  image->blob=CloneBlobInfo(histogram_image->blob);
  histogram_image=DestroyImage(histogram_image);
  write_info=DestroyImageInfo(write_info);
  return(status);
}
Example #5
0
void draw_tiger_map (Widget w,
        char *filenm,
        int destination_pixmap,
        int nocache) {  // For future implementation of a "refresh cached map" option
    char file[MAX_FILENAME];        // Complete path/name of image file
    char short_filenm[MAX_FILENAME];
    FILE *f;                        // Filehandle of image file
    char fileimg[MAX_FILENAME];     // Ascii name of image file, read from GEO file
    char tigertmp[MAX_FILENAME*2];  // Used for putting together the tigermap query
    int width, height;
    tiepoint tp[2];                 // Calibration points for map, read in from .geo file
    register long map_c_T, map_c_L; // map delta NW edge coordinates, DNN: these should be signed
    register long tp_c_dx, tp_c_dy; // tiepoint coordinate differences
    unsigned long c_x_min,  c_y_min;// top left coordinates of map inside screen
    unsigned long c_y_max;          // bottom right coordinates of map inside screen
    double c_x;                     // Xastir coordinates 1/100 sec, 0 = 180°W
    double c_y;                     // Xastir coordinates 1/100 sec, 0 =  90°N

    long map_y_0;                   // map pixel pointer prior to TM adjustment
    register long map_x, map_y;     // map pixel pointers, DNN: this was a float, chg to long
    long map_x_min, map_x_max;      // map boundaries for in screen part of map
    long map_y_min, map_y_max;      //
    long map_x_ctr;                 // half map width in pixel
    long map_y_ctr;                 // half map height in pixel
    int map_seen = 0;
    int map_act;
    int map_done;

    long map_c_yc;                  // map center, vert coordinate
    long map_c_xc;                  // map center, hor  coordinate
    double map_c_dx, map_c_dy;      // map coordinates increment (pixel width)
    double c_dx;                    // adjusted map pixel width

    long scr_x,  scr_y;             // screen pixel plot positions
    long scr_xp, scr_yp;            // previous screen plot positions
    int  scr_dx, scr_dy;            // increments in screen plot positions
    long scr_x_mc;                  // map center in screen units

    long scr_c_xr;

    long scale_xa;                  // adjusted for topo maps
    double scale_x_nm;              // nm per Xastir coordinate unit
    long scale_x0;                  // at widest map area

    char local_filename[MAX_FILENAME];
    
    ExceptionInfo exception;
    Image *image;
    ImageInfo *image_info;
    PixelPacket *pixel_pack;
    PixelPacket temp_pack;
    IndexPacket *index_pack;
    int l;
    XColor my_colors[256];
    double left, right, top, bottom, map_width, map_height;
    double lat_center  = 0;
    double long_center = 0;

    char map_it[MAX_FILENAME];
    char tmpstr[100];
    int geo_image_width;        // Image width  from GEO file
    int geo_image_height;       // Image height from GEO file

    // initialize this
    local_filename[0]='\0';

    // Create a shorter filename for display (one that fits the
    // status line more closely).  Subtract the length of the
    // "Indexing " and/or "Loading " strings as well.
    if (strlen(filenm) > (41 - 9)) {
        int avail = 41 - 11;
        int new_len = strlen(filenm) - avail;

        xastir_snprintf(short_filenm,
            sizeof(short_filenm),
            "..%s",
            &filenm[new_len]);
    }
    else {
        xastir_snprintf(short_filenm,
            sizeof(short_filenm),
            "%s",
            filenm);
    }

    xastir_snprintf(map_it,
        sizeof(map_it),
        langcode ("BBARSTA028"),
        short_filenm);
    statusline(map_it,0);       // Loading ...


        
    // Check whether we're indexing or drawing the map
    if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS)
            || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) {

        // We're indexing only.  Save the extents in the index.
        // Force the extents to the edges of the earth for the
        // index file.
        index_update_xastir(filenm, // Filename only
            64800000l,      // Bottom
            0l,             // Top
            0l,             // Left
            129600000l,     // Right
            0);             // Default Map Level

        // Update statusline
        xastir_snprintf(map_it,
            sizeof(map_it),
            langcode ("BBARSTA039"),
            short_filenm);
        statusline(map_it,0);       // Loading/Indexing ...

        return; // Done indexing this file
    }


    // Tiepoint for upper left screen corner
    //
    tp[0].img_x = 0;                // Pixel Coordinates
    tp[0].img_y = 0;                // Pixel Coordinates
    tp[0].x_long = NW_corner_longitude;   // Xastir Coordinates
    tp[0].y_lat  = NW_corner_latitude;    // Xastir Coordinates

    // Tiepoint for lower right screen corner
    //
    tp[1].img_x =  screen_width - 1; // Pixel Coordinates
    tp[1].img_y = screen_height - 1; // Pixel Coordinates 

    tp[1].x_long = SE_corner_longitude; // Xastir Coordinates
    tp[1].y_lat  =  SE_corner_latitude; // Xastir Coordinates

    left = (double)((NW_corner_longitude - 64800000l )/360000.0);   // Lat/long Coordinates
    top = (double)(-((NW_corner_latitude - 32400000l )/360000.0));  // Lat/long Coordinates
    right = (double)((SE_corner_longitude - 64800000l)/360000.0);//Lat/long Coordinates
    bottom = (double)(-((SE_corner_latitude - 32400000l)/360000.0));//Lat/long Coordinates

    map_width = right - left;   // Lat/long Coordinates
    map_height = top - bottom;  // Lat/long Coordinates

    geo_image_width  = screen_width;
    geo_image_height = screen_height;

    long_center = (left + right)/2.0l;
    lat_center  = (top + bottom)/2.0l;

//  Example query to the census map server....
/*        xastir_snprintf(fileimg, sizeof(fileimg), 
        "\'http://tiger.census.gov/cgi-bin/mapper/map.gif?on=CITIES&on=GRID&on=counties&on=majroads&on=places&&on=interstate&on=states&on=ushwy&on=statehwy&lat=%f\046lon=%f\046wid=%f\046ht=%f\046iwd=%i\046iht=%i\'",\
                   lat_center, long_center, map_width, map_height, tp[1].img_x + 1, tp[1].img_y + 1); */

    xastir_snprintf(tigertmp, sizeof(tigertmp), "http://tiger.census.gov/cgi-bin/mapper/map.gif?");

    if (tiger_show_grid)
        strncat(tigertmp, "&on=GRID", sizeof(tigertmp) - 1 - strlen(tigertmp));
    else
        strncat(tigertmp, "&off=GRID", sizeof(tigertmp) - 1 - strlen(tigertmp));

    if (tiger_show_counties)
        strncat(tigertmp, "&on=counties", sizeof(tigertmp) - 1 - strlen(tigertmp));
    else
        strncat(tigertmp, "&off=counties", sizeof(tigertmp) - 1 - strlen(tigertmp));

    if (tiger_show_cities)
        strncat(tigertmp, "&on=CITIES", sizeof(tigertmp) - 1 - strlen(tigertmp));
    else
        strncat(tigertmp, "&off=CITIES", sizeof(tigertmp) - 1 - strlen(tigertmp));

    if (tiger_show_places)
        strncat(tigertmp, "&on=places", sizeof(tigertmp) - 1 - strlen(tigertmp));
    else
        strncat(tigertmp, "&off=places", sizeof(tigertmp) - 1 - strlen(tigertmp));

    if (tiger_show_majroads)
        strncat(tigertmp, "&on=majroads", sizeof(tigertmp) - 1 - strlen(tigertmp));
    else
        strncat(tigertmp, "&off=majroads", sizeof(tigertmp) - 1 - strlen(tigertmp));

    if (tiger_show_streets)
        strncat(tigertmp, "&on=streets", sizeof(tigertmp) - 1 - strlen(tigertmp));
    // Don't turn streets off since this will automagically show up as you zoom in.

    if (tiger_show_railroad)
        strncat(tigertmp, "&on=railroad", sizeof(tigertmp) - 1 - strlen(tigertmp));
    else
        strncat(tigertmp, "&off=railroad", sizeof(tigertmp) - 1 - strlen(tigertmp));

    if (tiger_show_states)
        strncat(tigertmp, "&on=states", sizeof(tigertmp) - 1 - strlen(tigertmp));
    else
        strncat(tigertmp, "&off=states", sizeof(tigertmp) - 1 - strlen(tigertmp));

    if (tiger_show_interstate)
        strncat(tigertmp, "&on=interstate", sizeof(tigertmp) - 1 - strlen(tigertmp));
    else
        strncat(tigertmp, "&off=interstate", sizeof(tigertmp) - 1 - strlen(tigertmp));

    if (tiger_show_ushwy)
        strncat(tigertmp, "&on=ushwy", sizeof(tigertmp) - 1 - strlen(tigertmp));
    else
        strncat(tigertmp, "&off=ushwy", sizeof(tigertmp) - 1 - strlen(tigertmp));

    if (tiger_show_statehwy)
        strncat(tigertmp, "&on=statehwy", sizeof(tigertmp) - 1 - strlen(tigertmp));
    else
        strncat(tigertmp, "&off=statehwy", sizeof(tigertmp) - 1 - strlen(tigertmp));

    if (tiger_show_water)
        strncat(tigertmp, "&on=water", sizeof(tigertmp) - 1 - strlen(tigertmp));
    else
        strncat(tigertmp, "&off=water", sizeof(tigertmp) - 1 - strlen(tigertmp));

    if (tiger_show_lakes)
        strncat(tigertmp, "&on=shorelin", sizeof(tigertmp) - 1 - strlen(tigertmp));
    else
        strncat(tigertmp, "&off=shorelin", sizeof(tigertmp) - 1 - strlen(tigertmp));

    if (tiger_show_misc)
        strncat(tigertmp, "&on=miscell", sizeof(tigertmp) - 1 - strlen(tigertmp));
    else
        strncat(tigertmp, "&off=miscell", sizeof(tigertmp) - 1 - strlen(tigertmp));

    xastir_snprintf(tmpstr, sizeof(tmpstr), "&lat=%f\046lon=%f\046", lat_center, long_center);    
    strncat (tigertmp, tmpstr, sizeof(tigertmp) - 1 - strlen(tigertmp));
    xastir_snprintf(tmpstr, sizeof(tmpstr), "wid=%f\046ht=%f\046", map_width, map_height);
    strncat (tigertmp, tmpstr, sizeof(tigertmp) - 1 - strlen(tigertmp));
    xastir_snprintf(tmpstr, sizeof(tmpstr), "iwd=%i\046iht=%i", tp[1].img_x + 1, tp[1].img_y + 1);
    strncat (tigertmp, tmpstr, sizeof(tigertmp) - 1 - strlen(tigertmp));
    xastir_snprintf(fileimg, sizeof(fileimg), "%s", tigertmp);

    if (debug_level & 512) {
          fprintf(stderr,"left side is %f\n", left);
          fprintf(stderr,"right side is %f\n", right);
          fprintf(stderr,"top  is %f\n", top);
          fprintf(stderr,"bottom is %f\n", bottom);
          fprintf(stderr,"lat center is %f\n", lat_center);
          fprintf(stderr,"long center is %f\n", long_center);
          fprintf(stderr,"screen width is %li\n", screen_width);
          fprintf(stderr,"screen height is %li\n", screen_height);
          fprintf(stderr,"map width is %f\n", map_width);
          fprintf(stderr,"map height is %f\n", map_height);
          fprintf(stderr,"fileimg is %s\n", fileimg);
          fprintf(stderr,"ftp or http file: %s\n", fileimg);
    }


// Hopefully this will eventually allow us to get maps in the background
//    while (sometimeout !=0 && local_filename[0]==NULL){

    if  (local_filename[0]=='\0' ){

        if (debug_level & 512 ) { 
            fprintf(stderr,"tiger_local_file=<%s>\n",local_filename);
        }

        HandlePendingEvents(app_context);
        if (interrupt_drawing_now) {
            // Update to screen
            (void)XCopyArea(XtDisplay(da),
                pixmap,
                XtWindow(da),
                gc,
                0,
                0,
                (unsigned int)screen_width,
                (unsigned int)screen_height,
                0,
                0);
            return;
        }

        get_tiger_local_file(local_filename,fileimg); 

    }

// whackadoodle


    // Tell ImageMagick where to find it
    xastir_snprintf(file,
        sizeof(file),
        "%s",
        local_filename);

    GetExceptionInfo(&exception);

    image_info=CloneImageInfo((ImageInfo *) NULL);

    xastir_snprintf(image_info->filename,
        sizeof(image_info->filename),
        "%s",
        file);

    if (debug_level & 512) {
           fprintf(stderr,"Copied %s into image info.\n", file);
           fprintf(stderr,"image_info got: %s\n", image_info->filename);
           fprintf(stderr,"Entered ImageMagick code.\n");
           fprintf(stderr,"Attempting to open: %s\n", image_info->filename);
    }

    // We do a test read first to see if the file exists, so we
    // don't kill Xastir in the ReadImage routine.
    f = fopen (image_info->filename, "r");
    if (f == NULL) {
        if (debug_level & 512)
            fprintf(stderr,"File could not be read\n");

#ifdef USE_MAP_CACHE

        // clear from cache if bad    
        if (map_cache_del(fileimg)) {
            if (debug_level & 512) {
                fprintf(stderr,"Couldn't delete unreadable map from cache\n");
            }
        }
#endif
         
        if (image_info)
            DestroyImageInfo(image_info);
	DestroyExceptionInfo(&exception);
        return;
    }
    (void)fclose (f);


    image = ReadImage(image_info, &exception);

    if (image == (Image *) NULL) {
        MagickWarning(exception.severity, exception.reason, exception.description);
        //fprintf(stderr,"MagickWarning\n");

#ifdef USE_MAP_CACHE
        // clear from cache if bad    
        if (map_cache_del(fileimg)) {
            if (debug_level & 512) {
                fprintf(stderr,"Couldn't delete map from cache\n");
            }
        }
#endif

        if (image_info)
            DestroyImageInfo(image_info);
	DestroyExceptionInfo(&exception);
        return;
    }


    if (debug_level & 512)
        fprintf(stderr,"Color depth is %i \n", (int)image->depth);

    if (image->colorspace != RGBColorspace) {
        fprintf(stderr,"TBD: I don't think we can deal with colorspace != RGB");
        if (image)
            DestroyImage(image);
        if (image_info)
            DestroyImageInfo(image_info);
	DestroyExceptionInfo(&exception);
        return;
    }

    width = image->columns;
    height = image->rows;

    //  Code to mute the image so it's not as bright.
/*    if (raster_map_intensity < 1.0) {
        char tempstr[30];

        if (debug_level & 512)
            fprintf(stderr,"level=%s\n", tempstr);

        xastir_snprintf(tempstr,
            sizeof(tempstr),
            "%d, 100, 100",
            (int)(raster_map_intensity * 100.0));

        ModulateImage(image, tempstr);
    }
*/


    // If were are drawing to a low bpp display (typically < 8bpp)
    // try to reduce the number of colors in an image.
    // This may take some time, so it would be best to do ahead of
    // time if it is a static image.
#if (MagickLibVersion < 0x0540)
    if (visual_type == NOT_TRUE_NOR_DIRECT && GetNumberColors(image, NULL) > 128) {
#else   // MagickLib >= 540
    if (visual_type == NOT_TRUE_NOR_DIRECT && GetNumberColors(image, NULL, &exception) > 128) {
#endif  // MagickLib Version

        if (image->storage_class == PseudoClass) {
#if (MagickLibVersion < 0x0549)
            CompressColormap(image); // Remove duplicate colors
#else // MagickLib >= 0x0549
            CompressImageColormap(image); // Remove duplicate colors
#endif  // MagickLibVersion < 0x0549
        }

        // Quantize down to 128 will go here...
    }


    pixel_pack = GetImagePixels(image, 0, 0, image->columns, image->rows);
    if (!pixel_pack) {
        fprintf(stderr,"pixel_pack == NULL!!!");
        if (image)
            DestroyImage(image);
        if (image_info)
            DestroyImageInfo(image_info);
	DestroyExceptionInfo(&exception);
        return;
    }


    index_pack = GetIndexes(image);
    if (image->storage_class == PseudoClass && !index_pack) {
        fprintf(stderr,"PseudoClass && index_pack == NULL!!!");
        if (image)
            DestroyImage(image);
        if (image_info)
            DestroyImageInfo(image_info);
	DestroyExceptionInfo(&exception);
        return;
    }


    if (image->storage_class == PseudoClass && image->colors <= 256) {
        for (l = 0; l < (int)image->colors; l++) {
            // Need to check how to do this for ANY image, as ImageMagick can read in all sorts
            // of image files
            temp_pack = image->colormap[l];
            if (debug_level & 512)
                fprintf(stderr,"Colormap color is %i  %i  %i \n",
                       temp_pack.red, temp_pack.green, temp_pack.blue);

            // Here's a tricky bit:  PixelPacket entries are defined as Quantum's.  Quantum
            // is defined in /usr/include/magick/image.h as either an unsigned short or an
            // unsigned char, depending on what "configure" decided when ImageMagick was installed.
            // We can determine which by looking at MaxRGB or QuantumDepth.
            //
            if (QuantumDepth == 16) {   // Defined in /usr/include/magick/image.h
                if (debug_level & 512)
                    fprintf(stderr,"Color quantum is [0..65535]\n");
                my_colors[l].red   = temp_pack.red * raster_map_intensity;
                my_colors[l].green = temp_pack.green * raster_map_intensity;
                my_colors[l].blue  = temp_pack.blue * raster_map_intensity;
            }
            else {  // QuantumDepth = 8
                if (debug_level & 512)
                    fprintf(stderr,"Color quantum is [0..255]\n");
                my_colors[l].red   = (temp_pack.red << 8) * raster_map_intensity;
                my_colors[l].green = (temp_pack.green << 8) * raster_map_intensity;
                my_colors[l].blue  = (temp_pack.blue << 8) * raster_map_intensity;
            }

            // Get the color allocated on < 8bpp displays. pixel color is written to my_colors.pixel
            if (visual_type == NOT_TRUE_NOR_DIRECT) {
//                XFreeColors(XtDisplay(w), cmap, &(my_colors[l].pixel),1,0);
                XAllocColor(XtDisplay(w), cmap, &my_colors[l]);
            }
            else {
                pack_pixel_bits(my_colors[l].red, my_colors[l].green, my_colors[l].blue,
                                &my_colors[l].pixel);
            }

            if (debug_level & 512)
                fprintf(stderr,"Color allocated is %li  %i  %i  %i \n", my_colors[l].pixel,
                       my_colors[l].red, my_colors[l].blue, my_colors[l].green);
        }
    }



    /*
    * Here are the corners of our viewport, using the Xastir
    * coordinate system.  Notice that Y is upside down:
    *
    *   left edge of view = NW_corner_longitude
    *  right edge of view = SE_corner_longitude
    *    top edge of view =  NW_corner_latitude
    * bottom edge of view =  SE_corner_latitude
    *
    * The corners of our map will soon be (after translating the
    * tiepoints to the corners if they're not already there):
    *
    *   left edge of map = tp[0].x_long   in Xastir format
    *  right edge of map = tp[1].x_long
    *    top edge of map = tp[0].y_lat
    * bottom edge of map = tp[1].y_lat
    *
    */
    map_c_L = tp[0].x_long - NW_corner_longitude;     // map left coordinate
    map_c_T = tp[0].y_lat  - NW_corner_latitude;      // map top  coordinate

    tp_c_dx = (long)(tp[1].x_long - tp[0].x_long);//  Width between tiepoints
    tp_c_dy = (long)(tp[1].y_lat  - tp[0].y_lat); // Height between tiepoints


    // Check for tiepoints being in wrong relation to one another
    if (tp_c_dx < 0) 
        tp_c_dx = -tp_c_dx;       // New  width between tiepoints
    if (tp_c_dy < 0) 
        tp_c_dy = -tp_c_dy;       // New height between tiepoints

    // Calculate step size per pixel
    map_c_dx = ((double) tp_c_dx / abs(tp[1].img_x - tp[0].img_x));
    map_c_dy = ((double) tp_c_dy / abs(tp[1].img_y - tp[0].img_y));

    // Scaled screen step size for use with XFillRectangle below
    scr_dx = (int) (map_c_dx / scale_x) + 1;
    scr_dy = (int) (map_c_dy / scale_y) + 1;

    // calculate top left map corner from tiepoints
    if (tp[0].img_x != 0) {
        tp[0].x_long -= (tp[0].img_x * map_c_dx);   // map left edge longitude
        map_c_L = tp[0].x_long - NW_corner_longitude;     // delta ??
        tp[0].img_x = 0;
        if (debug_level & 512)
            fprintf(stderr,"Translated tiepoint_0 x: %d\t%lu\n", tp[0].img_x, tp[0].x_long);
    }
    if (tp[0].img_y != 0) {
        tp[0].y_lat -= (tp[0].img_y * map_c_dy);    // map top edge latitude
        map_c_T = tp[0].y_lat - NW_corner_latitude;
        tp[0].img_y = 0;
        if (debug_level & 512)
            fprintf(stderr,"Translated tiepoint_0 y: %d\t%lu\n", tp[0].img_y, tp[0].y_lat);
    }

    // calculate bottom right map corner from tiepoints
    // map size is geo_image_width / geo_image_height
    if (tp[1].img_x != (geo_image_width - 1) ) {
        tp[1].img_x = geo_image_width - 1;
        tp[1].x_long = tp[0].x_long + (tp[1].img_x * map_c_dx); // right
        if (debug_level & 512)
            fprintf(stderr,"Translated tiepoint_1 x: %d\t%lu\n", tp[1].img_x, tp[1].x_long);
    }
    if (tp[1].img_y != (geo_image_height - 1) ) {
        tp[1].img_y = geo_image_height - 1;
        tp[1].y_lat = tp[0].y_lat + (tp[1].img_y * map_c_dy);   // bottom
        if (debug_level & 512)
            fprintf(stderr,"Translated tiepoint_1 y: %d\t%lu\n", tp[1].img_y, tp[1].y_lat);
    }

    if (debug_level & 512) {
        fprintf(stderr,"X tiepoint width: %ld\n", tp_c_dx);
        fprintf(stderr,"Y tiepoint width: %ld\n", tp_c_dy);
        fprintf(stderr,"Loading imagemap: %s\n", file);
        fprintf(stderr,"\nImage: %s\n", file);
        fprintf(stderr,"Image size %d %d\n", geo_image_width, geo_image_height);
        fprintf(stderr,"XX: %ld YY:%ld Sx %f %d Sy %f %d\n",
            map_c_L, map_c_T, map_c_dx,(int) (map_c_dx / scale_x), map_c_dy, (int) (map_c_dy / scale_y));
        fprintf(stderr,"Image size %d %d\n", width, height);
#if (MagickLibVersion < 0x0540)
        fprintf(stderr,"Unique colors = %d\n", GetNumberColors(image, NULL));
#else // MagickLib < 540
        fprintf(stderr,"Unique colors = %ld\n", GetNumberColors(image, NULL, &exception));
#endif // MagickLib < 540
        fprintf(stderr,"XX: %ld YY:%ld Sx %f %d Sy %f %d\n", map_c_L, map_c_T,
            map_c_dx,(int) (map_c_dx / scale_x), map_c_dy, (int) (map_c_dy / scale_y));
        fprintf(stderr,"image matte is %i\n", image->matte);
    } // debug_level & 512

    // draw the image from the file out to the map screen

    // Get the border values for the X and Y for loops used
    // for the XFillRectangle call later.

    map_c_yc = (tp[0].y_lat + tp[1].y_lat) / 2;     // vert center of map as reference
    map_y_ctr = (long)(height / 2 +0.499);
    scale_x0 = get_x_scale(0,map_c_yc,scale_y);     // reference scaling at vert map center

    map_c_xc  = (tp[0].x_long + tp[1].x_long) / 2;  // hor center of map as reference
    map_x_ctr = (long)(width  / 2 +0.499);
    scr_x_mc  = (map_c_xc - NW_corner_longitude) / scale_x; // screen coordinates of map center

    // calculate map pixel range in y direction that falls into screen area
    c_y_max = 0ul;
    map_y_min = map_y_max = 0l;
    for (map_y_0 = 0, c_y = tp[0].y_lat; map_y_0 < (long)height; map_y_0++, c_y += map_c_dy) {
        scr_y = (c_y - NW_corner_latitude) / scale_y;   // current screen position
        if (scr_y > 0) {
            if (scr_y < screen_height) {
                map_y_max = map_y_0;          // update last map pixel in y
                c_y_max = (unsigned long)c_y;// bottom map inside screen coordinate
            } else
                break;                      // done, reached bottom screen border
        } else {                            // pixel is above screen
            map_y_min = map_y_0;              // update first map pixel in y
        }
    }
    c_y_min = (unsigned long)(tp[0].y_lat + map_y_min * map_c_dy);   // top map inside screen coordinate

        map_x_min = map_x_max = 0l;
        for (map_x = 0, c_x = tp[0].x_long; map_x < (long)width; map_x++, c_x += map_c_dx) {
            scr_x = (c_x - NW_corner_longitude)/ scale_x;  // current screen position
            if (scr_x > 0) {
                if (scr_x < screen_width)
                    map_x_max = map_x;          // update last map pixel in x
                else
                    break;                      // done, reached right screen border
            } else {                            // pixel is left from screen
                map_x_min = map_x;              // update first map pixel in x
            }
        }
        c_x_min = (unsigned long)(tp[0].x_long + map_x_min * map_c_dx);   // left map inside screen coordinate

    scr_yp = -1;
    scr_c_xr = SE_corner_longitude;
    c_dx = map_c_dx;                            // map pixel width
    scale_xa = scale_x0;                        // the compiler likes it ;-)

    map_done = 0;
    map_act  = 0;
    map_seen = 0;
    scr_y = screen_height - 1;


    // loop over map pixel rows
    for (map_y_0 = map_y_min, c_y = (double)c_y_min; (map_y_0 <= map_y_max); map_y_0++, c_y += map_c_dy) {

        HandlePendingEvents(app_context);
        if (interrupt_drawing_now) {
            if (image)
               DestroyImage(image);
            if (image_info)
               DestroyImageInfo(image_info);
            // Update to screen
            (void)XCopyArea(XtDisplay(da),
                pixmap,
                XtWindow(da),
                gc,
                0,
                0,
                (unsigned int)screen_width,
                (unsigned int)screen_height,
                0,
                0);
            DestroyExceptionInfo(&exception);
            return;
        }

        scr_y = (c_y - NW_corner_latitude) / scale_y;
        if (scr_y != scr_yp) {                  // don't do a row twice
            scr_yp = scr_y;                     // remember as previous y
            scr_xp = -1;
            // loop over map pixel columns
            map_act = 0;
            scale_x_nm = calc_dscale_x(0,(long)c_y) / 1852.0;  // nm per Xastir coordinate
            for (map_x = map_x_min, c_x = (double)c_x_min; map_x <= map_x_max; map_x++, c_x += c_dx) {
                scr_x = (c_x - NW_corner_longitude) / scale_x;
                if (scr_x != scr_xp) {      // don't do a pixel twice
                    scr_xp = scr_x;         // remember as previous x
                    map_y = map_y_0;

                    if (map_y >= 0 && map_y <= tp[1].img_y) { // check map boundaries in y direction
                        map_seen = 1;
                        map_act = 1;    // detects blank screen rows (end of map)

                        // now copy a pixel from the map image to the screen
                        l = map_x + map_y * image->columns;
                        if (image->storage_class == PseudoClass) {
                            XSetForeground(XtDisplay(w), gc, my_colors[index_pack[l]].pixel);
                        }
                        else {
                            // It is not safe to assume that the red/green/blue
                            // elements of pixel_pack of type Quantum are the
                            // same as the red/green/blue of an XColor!
                            if (QuantumDepth==16) {
                                my_colors[0].red=pixel_pack[l].red;
                                my_colors[0].green=pixel_pack[l].green;
                                my_colors[0].blue=pixel_pack[l].blue;
                            }
                            else { // QuantumDepth=8
                                // shift the bits of the 8-bit quantity so that
                                // they become the high bigs of my_colors.*
                                my_colors[0].red=pixel_pack[l].red<<8;
                                my_colors[0].green=pixel_pack[l].green<<8;
                                my_colors[0].blue=pixel_pack[l].blue<<8;
                            }
                            // NOW my_colors has the right r,g,b range for
                            // pack_pixel_bits
                            pack_pixel_bits(my_colors[0].red * raster_map_intensity,
                                            my_colors[0].green * raster_map_intensity,
                                            my_colors[0].blue * raster_map_intensity,
                                            &my_colors[0].pixel);
                            XSetForeground(XtDisplay(w), gc, my_colors[0].pixel);
                        }
                        (void)XFillRectangle (XtDisplay (w),pixmap,gc,scr_x,scr_y,scr_dx,scr_dy);
                    } // check map boundaries in y direction
                }
            } // loop over map pixel columns
            if (map_seen && !map_act)
                map_done = 1;
        }
    } // loop over map pixel rows

    if (image)
       DestroyImage(image);
    if (image_info)
       DestroyImageInfo(image_info);
    DestroyExceptionInfo(&exception);
}
Example #6
0
static MagickBooleanType WriteHISTOGRAMImage(const ImageInfo *image_info,
  Image *image)
{
#define HistogramDensity  "256x200"

  ChannelType
    channel;

  char
    filename[MaxTextExtent];

  ExceptionInfo
    *exception;

  FILE
    *file;

  Image
    *histogram_image;

  ImageInfo
    *write_info;

  int
    unique_file;

  long
    y;

  MagickBooleanType
    status;

  MagickPixelPacket
    *histogram;

  MagickRealType
    maximum,
    scale;

  RectangleInfo
    geometry;

  register const PixelPacket
    *p;

  register long
    x;

  register PixelPacket
    *q,
    *r;

  size_t
    length;

  /*
    Allocate histogram image.
  */
  assert(image_info != (const ImageInfo *) NULL);
  assert(image_info->signature == MagickSignature);
  assert(image != (Image *) NULL);
  assert(image->signature == MagickSignature);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
      image_info->filename);
  SetGeometry(image,&geometry);
  if (image_info->density == (char *) NULL)
    (void) ParseAbsoluteGeometry(HistogramDensity,&geometry);
  else
    (void) ParseAbsoluteGeometry(image_info->density,&geometry);
  histogram_image=CloneImage(image,geometry.width,geometry.height,MagickTrue,
    &image->exception);
  if (histogram_image == (Image *) NULL)
    ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
  (void) SetImageStorageClass(histogram_image,DirectClass);
  /*
    Allocate histogram count arrays.
  */
  length=MagickMax((size_t) ScaleQuantumToChar((Quantum) QuantumRange)+1UL,
    histogram_image->columns);
  histogram=(MagickPixelPacket *) AcquireQuantumMemory(length,
    sizeof(*histogram));
  if (histogram == (MagickPixelPacket *) NULL)
    {
      histogram_image=DestroyImage(histogram_image);
      ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
    }
  /*
    Initialize histogram count arrays.
  */
  channel=image_info->channel;
  (void) ResetMagickMemory(histogram,0,length*sizeof(*histogram));
  for (y=0; y < (long) image->rows; y++)
  {
    p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
    if (p == (const PixelPacket *) NULL)
      break;
    for (x=0; x < (long) image->columns; x++)
    {
      if ((channel & RedChannel) != 0)
        histogram[ScaleQuantumToChar(p->red)].red++;
      if ((channel & GreenChannel) != 0)
        histogram[ScaleQuantumToChar(p->green)].green++;
      if ((channel & BlueChannel) != 0)
        histogram[ScaleQuantumToChar(p->blue)].blue++;
      p++;
    }
  }
  maximum=histogram[0].red;
  for (x=0; x < (long) histogram_image->columns; x++)
  {
    if (((channel & RedChannel) != 0) && (maximum < histogram[x].red))
      maximum=histogram[x].red;
    if (((channel & GreenChannel) != 0) && (maximum < histogram[x].green))
      maximum=histogram[x].green;
    if (((channel & BlueChannel) != 0) && (maximum < histogram[x].blue))
      maximum=histogram[x].blue;
  }
  scale=(MagickRealType) histogram_image->rows/maximum;
  /*
    Initialize histogram image.
  */
  exception=(&image->exception);
  (void) QueryColorDatabase("#000000",&histogram_image->background_color,
    &image->exception);
  (void) SetImageBackgroundColor(histogram_image);
  for (x=0; x < (long) histogram_image->columns; x++)
  {
    q=GetAuthenticPixels(histogram_image,x,0,1,histogram_image->rows,exception);
    if (q == (PixelPacket *) NULL)
      break;
    if ((channel & RedChannel) != 0)
      {
        y=(long) (histogram_image->rows-scale*histogram[x].red+0.5);
        r=q+y;
        for ( ; y < (long) histogram_image->rows; y++)
        {
          r->red=(Quantum) QuantumRange;
          r++;
        }
      }
    if ((channel & GreenChannel) != 0)
      {
        y=(long) (histogram_image->rows-scale*histogram[x].green+0.5);
        r=q+y;
        for ( ; y < (long) histogram_image->rows; y++)
        {
          r->green=(Quantum) QuantumRange;
          r++;
        }
      }
    if ((channel & BlueChannel) != 0)
      {
        y=(long) (histogram_image->rows-scale*histogram[x].blue+0.5);
        r=q+y;
        for ( ; y < (long) histogram_image->rows; y++)
        {
          r->blue=(Quantum) QuantumRange;
          r++;
        }
      }
    if (SyncAuthenticPixels(histogram_image,exception) == MagickFalse)
      break;
    status=SetImageProgress(image,SaveImageTag,y,histogram_image->rows);
    if (status == MagickFalse)
      break;
  }
  /*
    Relinquish resources.
  */
  histogram=(MagickPixelPacket *) RelinquishMagickMemory(histogram);
  file=(FILE *) NULL;
  unique_file=AcquireUniqueFileResource(filename);
  if (unique_file != -1)
    file=fdopen(unique_file,"wb");
  if ((unique_file != -1) && (file != (FILE *) NULL))
    {
      char
        *property;

      /*
        Add a histogram as an image comment.
      */
      (void) GetNumberColors(image,file,&image->exception);
      (void) fclose(file);
      property=FileToString(filename,~0UL,&image->exception);
      if (property != (char *) NULL)
        {
          (void) SetImageProperty(histogram_image,"comment",property);
          property=DestroyString(property);
        }
    }
  (void) RelinquishUniqueFileResource(filename);
  /*
    Write Histogram image.
  */
  (void) CopyMagickString(histogram_image->filename,image_info->filename,
    MaxTextExtent);
  write_info=CloneImageInfo(image_info);
  (void) SetImageInfo(write_info,MagickTrue,&image->exception);
  if (LocaleCompare(write_info->magick,"HISTOGRAM") == 0)
    (void) FormatMagickString(histogram_image->filename,MaxTextExtent,
      "miff:%s",write_info->filename);
  status=WriteImage(write_info,histogram_image);
  histogram_image=DestroyImage(histogram_image);
  write_info=DestroyImageInfo(write_info);
  return(status);
}
Example #7
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   I d e n t i f y I m a g e                                                 %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  IdentifyImage() identifies an image by printing its attributes to the file.
%  Attributes include the image width, height, size, and others.
%
%  The format of the IdentifyImage method is:
%
%      MagickBooleanType IdentifyImage(Image *image,FILE *file,
%        const MagickBooleanType verbose)
%
%  A description of each parameter follows:
%
%    o image: The image.
%
%    o file: The file, typically stdout.
%
%    o verbose: A value other than zero prints more detailed information
%      about the image.
%
*/
MagickExport MagickBooleanType IdentifyImage(Image *image,FILE *file,
  const MagickBooleanType verbose)
{
#define IdentifyFormat "    %s:\n      Min: " QuantumFormat  \
  " (%g)\n      Max: " QuantumFormat " (%g)\n"  \
  "      Mean: %g (%g)\n      Standard deviation: %g (%g)\n"

  char
    color[MaxTextExtent],
    format[MaxTextExtent],
    key[MaxTextExtent];

  ColorspaceType
    colorspace;

  const char
    *property,
    *value;

  const MagickInfo
    *magick_info;

  const PixelPacket
    *pixels;

  double
    elapsed_time,
    user_time;

  ExceptionInfo
    *exception;

  Image
    *p;

  ImageType
    type;

  long
    y;

  MagickBooleanType
    ping;

  register long
    i,
    x;

  unsigned long
    scale;

  assert(image != (Image *) NULL);
  assert(image->signature == MagickSignature);
  if (image->debug != MagickFalse)
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
  if (file == (FILE *) NULL)
    file=stdout;
  *format='\0';
  elapsed_time=GetElapsedTime(&image->timer);
  user_time=GetUserTime(&image->timer);
  GetTimerInfo(&image->timer);
  if (verbose == MagickFalse)
    {
      /*
        Display summary info about the image.
      */
      if (*image->magick_filename != '\0')
        if (LocaleCompare(image->magick_filename,image->filename) != 0)
          (void) fprintf(file,"%s=>",image->magick_filename);
       if ((GetPreviousImageInList(image) == (Image *) NULL) &&
           (GetNextImageInList(image) == (Image *) NULL) && (image->scene == 0))
        (void) fprintf(file,"%s ",image->filename);
      else
        (void) fprintf(file,"%s[%lu] ",image->filename,image->scene);
      (void) fprintf(file,"%s ",image->magick);
      if ((image->magick_columns != 0) || (image->magick_rows != 0))
        if ((image->magick_columns != image->columns) ||
            (image->magick_rows != image->rows))
          (void) fprintf(file,"%lux%lu=>",image->magick_columns,
            image->magick_rows);
      (void) fprintf(file,"%lux%lu ",image->columns,image->rows);
      if ((image->page.width != 0) || (image->page.height != 0) ||
          (image->page.x != 0) || (image->page.y != 0))
        (void) fprintf(file,"%lux%lu%+ld%+ld ",image->page.width,
          image->page.height,image->page.x,image->page.y);
      if (image->storage_class == DirectClass)
        {
          (void) fprintf(file,"DirectClass ");
          if (image->total_colors != 0)
            {
              (void) FormatMagickSize(image->total_colors,format);
              (void) fprintf(file,"%s ",format);
            }
        }
      else
        if (image->total_colors <= image->colors)
          (void) fprintf(file,"PseudoClass %luc ",image->colors);
        else
          (void) fprintf(file,"PseudoClass %lu=>%luc ",image->total_colors,
            image->colors);
      (void) fprintf(file,"%lu-bit ",image->depth);
      if (image->error.mean_error_per_pixel != 0.0)
        (void) fprintf(file,"%ld/%f/%fdb ",
          (long) (image->error.mean_error_per_pixel+0.5),
          image->error.normalized_mean_error,
          image->error.normalized_maximum_error);
      if (GetBlobSize(image) != 0)
        {
          (void) FormatMagickSize(GetBlobSize(image),format);
          (void) fprintf(file,"%s ",format);
        }
      if (elapsed_time > 0.06)
        (void) fprintf(file,"%0.3fu %ld:%02ld",user_time,
          (long) (elapsed_time/60.0+0.5),(long) ceil(fmod(elapsed_time,60.0)));
      (void) fprintf(file,"\n");
      (void) fflush(file);
      return(ferror(file) != 0 ? MagickFalse : MagickTrue);
    }
  /*
    Display verbose info about the image.
  */
  exception=AcquireExceptionInfo();
  pixels=AcquireImagePixels(image,0,0,1,1,exception);
  exception=DestroyExceptionInfo(exception);
  ping=pixels == (const PixelPacket *) NULL ? MagickTrue : MagickFalse;
  type=GetImageType(image,&image->exception);
  (void) SignatureImage(image);
  (void) fprintf(file,"Image: %s\n",image->filename);
  if (*image->magick_filename != '\0')
    if (LocaleCompare(image->magick_filename,image->filename) != 0)
      {
        char
          filename[MaxTextExtent];

        GetPathComponent(image->magick_filename,TailPath,filename);
        (void) fprintf(file,"  Base filename: %s\n",filename);
      }
  magick_info=GetMagickInfo(image->magick,&image->exception);
  if ((magick_info == (const MagickInfo *) NULL) ||
      (*GetMagickDescription(magick_info) == '\0'))
    (void) fprintf(file,"  Format: %s\n",image->magick);
  else
    (void) fprintf(file,"  Format: %s (%s)\n",image->magick,
      GetMagickDescription(magick_info));
  (void) fprintf(file,"  Class: %s\n",
    MagickOptionToMnemonic(MagickClassOptions,(long) image->storage_class));
  (void) fprintf(file,"  Geometry: %lux%lu%+ld%+ld\n",image->columns,
    image->rows,image->tile_offset.x,image->tile_offset.y);
  if ((image->magick_columns != 0) || (image->magick_rows != 0))
    if ((image->magick_columns != image->columns) ||
        (image->magick_rows != image->rows))
      (void) fprintf(file,"  Base geometry: %lux%lu\n",image->magick_columns,
        image->magick_rows);
  (void) fprintf(file,"  Type: %s\n",MagickOptionToMnemonic(MagickTypeOptions,
    (long) type));
  (void) fprintf(file,"  Endianess: %s\n",MagickOptionToMnemonic(
    MagickEndianOptions,(long) image->endian));
  /*
    Detail channel depth and extrema.
  */
  colorspace=image->colorspace;
  if (IsGrayImage(image,&image->exception) != MagickFalse)
    colorspace=GRAYColorspace;
  (void) fprintf(file,"  Colorspace: %s\n",
    MagickOptionToMnemonic(MagickColorspaceOptions,(long) colorspace));
  if (ping == MagickFalse)
    {
      ChannelStatistics
        *channel_statistics;

      (void) fprintf(file,"  Depth: %lu-bit\n",GetImageDepth(image,
        &image->exception));
      channel_statistics=GetImageChannelStatistics(image,&image->exception);
      (void) fprintf(file,"  Channel depth:\n");
      switch (colorspace)
      {
        case RGBColorspace:
        default:
        {
          (void) fprintf(file,"    Red: %lu-bit\n",
            channel_statistics[RedChannel].depth);
          (void) fprintf(file,"    Green: %lu-bit\n",
            channel_statistics[GreenChannel].depth);
          (void) fprintf(file,"    Blue: %lu-bit\n",
            channel_statistics[BlueChannel].depth);
          if (image->matte != MagickFalse)
            (void) fprintf(file,"    Alpha: %lu-bit\n",
              channel_statistics[OpacityChannel].depth);
          break;
        }
        case CMYKColorspace:
        {
          (void) fprintf(file,"    Cyan: %lu-bit\n",
            channel_statistics[CyanChannel].depth);
          (void) fprintf(file,"    Magenta: %lu-bit\n",
            channel_statistics[MagentaChannel].depth);
          (void) fprintf(file,"    Yellow: %lu-bit\n",
            channel_statistics[YellowChannel].depth);
          (void) fprintf(file,"    Black: %lu-bit\n",
            channel_statistics[BlackChannel].depth);
          if (image->matte != MagickFalse)
            (void) fprintf(file,"    Alpha: %lu-bit\n",
              channel_statistics[OpacityChannel].depth);
          break;
        }
        case GRAYColorspace:
        {
          (void) fprintf(file,"    Gray: %lu-bit\n",
            channel_statistics[GrayChannel].depth);
          if (image->matte != MagickFalse)
            (void) fprintf(file,"    Alpha: %lu-bit\n",
              channel_statistics[OpacityChannel].depth);
          break;
        }
      }
      scale=QuantumRange/((unsigned long) QuantumRange >> ((unsigned long)
        MAGICKCORE_QUANTUM_DEPTH-channel_statistics[AllChannels].depth));
      (void) fprintf(file,"  Channel statistics:\n");
      switch (colorspace)
      {
        case RGBColorspace:
        default:
        {
          (void) fprintf(file,IdentifyFormat,"Red",(Quantum)
            (channel_statistics[RedChannel].minima/scale),(double)
            channel_statistics[RedChannel].minima/(double) QuantumRange,
            (Quantum) (channel_statistics[RedChannel].maxima/scale),(double)
            channel_statistics[RedChannel].maxima/(double) QuantumRange,
            channel_statistics[RedChannel].mean/(double) scale,
            channel_statistics[RedChannel].mean/(double) QuantumRange,
            channel_statistics[RedChannel].standard_deviation/(double) scale,
            channel_statistics[RedChannel].standard_deviation/(double)
            QuantumRange);
          (void) fprintf(file,IdentifyFormat,"Green",(Quantum)
            (channel_statistics[GreenChannel].minima/scale),(double)
            channel_statistics[GreenChannel].minima/(double) QuantumRange,
            (Quantum) (channel_statistics[GreenChannel].maxima/scale),(double)
            channel_statistics[GreenChannel].maxima/(double) QuantumRange,
            channel_statistics[GreenChannel].mean/(double) scale,
            channel_statistics[GreenChannel].mean/(double) QuantumRange,
            channel_statistics[GreenChannel].standard_deviation/(double) scale,
            channel_statistics[GreenChannel].standard_deviation/(double)
            QuantumRange);
          (void) fprintf(file,IdentifyFormat,"Blue",(Quantum)
            (channel_statistics[BlueChannel].minima/scale),(double)
            channel_statistics[BlueChannel].minima/(double) QuantumRange,
            (Quantum) (channel_statistics[BlueChannel].maxima/scale),(double)
            channel_statistics[BlueChannel].maxima/(double) QuantumRange,
            channel_statistics[BlueChannel].mean/(double) scale,
            channel_statistics[BlueChannel].mean/(double) QuantumRange,
            channel_statistics[BlueChannel].standard_deviation/(double) scale,
            channel_statistics[BlueChannel].standard_deviation/(double)
            QuantumRange);
          break;
        }
        case CMYKColorspace:
        {
          (void) fprintf(file,IdentifyFormat,"Cyan",(Quantum)
            (channel_statistics[CyanChannel].minima/scale),(double)
            channel_statistics[CyanChannel].minima/(double) QuantumRange,
            (Quantum) (channel_statistics[CyanChannel].maxima/scale),(double)
            channel_statistics[CyanChannel].maxima/(double) QuantumRange,
            channel_statistics[CyanChannel].mean/(double) scale,
            channel_statistics[CyanChannel].mean/(double) QuantumRange,
            channel_statistics[CyanChannel].standard_deviation/(double) scale,
            channel_statistics[CyanChannel].standard_deviation/(double)
            QuantumRange);
          (void) fprintf(file,IdentifyFormat,"Magenta",(Quantum)
            (channel_statistics[MagentaChannel].minima/scale),(double)
            channel_statistics[MagentaChannel].minima/(double) QuantumRange,
            (Quantum) (channel_statistics[MagentaChannel].maxima/scale),(double)
            channel_statistics[MagentaChannel].maxima/(double) QuantumRange,
            channel_statistics[MagentaChannel].mean/(double) scale,
            channel_statistics[MagentaChannel].mean/(double) QuantumRange,
            channel_statistics[MagentaChannel].standard_deviation/(double)
            scale,channel_statistics[MagentaChannel].standard_deviation/(double)
            QuantumRange);
          (void) fprintf(file,IdentifyFormat,"Yellow",(Quantum)
            (channel_statistics[YellowChannel].minima/scale),(double)
            channel_statistics[YellowChannel].minima/(double) QuantumRange,
            (Quantum) (channel_statistics[YellowChannel].maxima/scale),(double)
            channel_statistics[YellowChannel].maxima/(double) QuantumRange,
            channel_statistics[YellowChannel].mean/(double) scale,
            channel_statistics[YellowChannel].mean/(double) QuantumRange,
            channel_statistics[YellowChannel].standard_deviation/(double) scale,
            channel_statistics[YellowChannel].standard_deviation/(double)
            QuantumRange);
          (void) fprintf(file,IdentifyFormat,"Black",(Quantum)
            (channel_statistics[BlackChannel].minima/scale),(double)
            channel_statistics[BlackChannel].minima/(double) QuantumRange,
            (Quantum) (channel_statistics[BlackChannel].maxima/scale),(double)
            channel_statistics[BlackChannel].maxima/(double) QuantumRange,
            channel_statistics[BlackChannel].mean/(double) scale,
            channel_statistics[BlackChannel].mean/(double) QuantumRange,
            channel_statistics[BlackChannel].standard_deviation/(double) scale,
            channel_statistics[BlackChannel].standard_deviation/(double)
            QuantumRange);
          break;
        }
        case GRAYColorspace:
        {
          (void) fprintf(file,IdentifyFormat,"Gray",(Quantum)
            (channel_statistics[GrayChannel].minima/scale),(double)
            channel_statistics[GrayChannel].minima/(double) QuantumRange,
            (Quantum) (channel_statistics[GrayChannel].maxima/scale),(double)
            channel_statistics[GrayChannel].maxima/(double) QuantumRange,
            channel_statistics[GrayChannel].mean/(double) scale,
            channel_statistics[GrayChannel].mean/(double) QuantumRange,
            channel_statistics[GrayChannel].standard_deviation/(double) scale,
            channel_statistics[GrayChannel].standard_deviation/(double)
            QuantumRange);
          break;
        }
      }
      if (image->matte != MagickFalse)
        (void) fprintf(file,IdentifyFormat,"Opacity",(Quantum)
          (channel_statistics[OpacityChannel].minima/scale),(double)
          channel_statistics[OpacityChannel].minima/(double) QuantumRange,
          (Quantum) (channel_statistics[OpacityChannel].maxima/scale),(double)
          channel_statistics[OpacityChannel].maxima/(double) QuantumRange,
          channel_statistics[OpacityChannel].mean/(double) scale,
          channel_statistics[OpacityChannel].mean/(double) QuantumRange,
          channel_statistics[OpacityChannel].standard_deviation/(double) scale,
          channel_statistics[OpacityChannel].standard_deviation/(double)
          QuantumRange);
      channel_statistics=(ChannelStatistics *) RelinquishMagickMemory(
        channel_statistics);
      if (colorspace == CMYKColorspace)
        (void) fprintf(file,"  Total ink density: %.0f%%\n",100.0*
          GetImageTotalInkDensity(image)/(double) QuantumRange);
      x=0;
      p=NewImageList();
      if (image->matte != MagickFalse)
        {
          register const IndexPacket
            *indexes;

          register const PixelPacket
            *p;

          p=(PixelPacket *) NULL;
          indexes=(IndexPacket *) NULL;
          for (y=0; y < (long) image->rows; y++)
          {
            p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
            if (p == (const PixelPacket *) NULL)
              break;
            indexes=AcquireIndexes(image);
            for (x=0; x < (long) image->columns; x++)
            {
              if (p->opacity == (Quantum) TransparentOpacity)
                break;
              p++;
            }
            if (x < (long) image->columns)
              break;
          }
          if ((x < (long) image->columns) || (y < (long) image->rows))
            {
              char
                tuple[MaxTextExtent];

              MagickPixelPacket
                pixel;

              GetMagickPixelPacket(image,&pixel);
              SetMagickPixelPacket(image,p,indexes+x,&pixel);
              (void) QueryMagickColorname(image,&pixel,SVGCompliance,
                MagickFalse,tuple,&image->exception);
              (void) fprintf(file,"  Alpha: %s  ",tuple);
              (void) QueryMagickColorname(image,&pixel,SVGCompliance,MagickTrue,
                tuple,&image->exception);
              (void) fprintf(file,"  %s\n",tuple);
            }
        }
      if ((ping == MagickFalse) &&
          (IsHistogramImage(image,&image->exception) != MagickFalse))
        {
          (void) fprintf(file,"  Histogram:\n");
          (void) GetNumberColors(image,file,&image->exception);
        }
    }
Example #8
0
void draw_WMS_map (Widget w,
        char *filenm,
        int destination_pixmap,
        char *URL,
        transparent_color_record *c_trans_color_head,
        int nocache) {  // If non-zero, don't use cached version


    char file[MAX_FILENAME];        // Complete path/name of image file
    char short_filenm[MAX_FILENAME];
    FILE *f;                        // Filehandle of image file
    char fileimg[MAX_FILENAME];     // Ascii name of image file, read from GEO file
    char WMStmp[MAX_FILENAME*2];  // Used for putting together the WMS map query
    int width, height;
    tiepoint tp[2];                 // Calibration points for map, read in from .geo file
    register long map_c_T, map_c_L; // map delta NW edge coordinates, DNN: these should be signed
    register long tp_c_dx, tp_c_dy; // tiepoint coordinate differences
    unsigned long c_x_min,  c_y_min;// top left coordinates of map inside screen
    unsigned long c_y_max;          // bottom right coordinates of map inside screen
    double c_x;                     // Xastir coordinates 1/100 sec, 0 = 180°W
    double c_y;                     // Xastir coordinates 1/100 sec, 0 =  90°N

    long map_y_0;                   // map pixel pointer prior to TM adjustment
    register long map_x, map_y;     // map pixel pointers, DNN: this was a float, chg to long
    long map_x_min, map_x_max;      // map boundaries for in screen part of map
    long map_y_min, map_y_max;      //
    long map_x_ctr;                 // half map width in pixel
    long map_y_ctr;                 // half map height in pixel
    int map_seen = 0;
    int map_act;
    int map_done;

    long map_c_yc;                  // map center, vert coordinate
    long map_c_xc;                  // map center, hor  coordinate
    double map_c_dx, map_c_dy;      // map coordinates increment (pixel width)
    double c_dx;                    // adjusted map pixel width

    long scr_x,  scr_y;             // screen pixel plot positions
    long scr_xp, scr_yp;            // previous screen plot positions
    int  scr_dx, scr_dy;            // increments in screen plot positions
    long scr_x_mc;                  // map center in screen units

    long scr_c_xr;

    long scale_xa;                  // adjusted for topo maps
    double scale_x_nm;              // nm per Xastir coordinate unit
    long scale_x0;                  // at widest map area

    char local_filename[MAX_FILENAME];
    ExceptionInfo exception;
    Image *image;
    ImageInfo *image_info;
    PixelPacket *pixel_pack;
    PixelPacket temp_pack;
    IndexPacket *index_pack;
    int l;
    XColor my_colors[256];
    int trans_skip = 0;             // skip transparent pixel
    double left, right, top, bottom, map_width, map_height;
    double lat_center  = 0;
    double long_center = 0;

    char map_it[MAX_FILENAME];
    char tmpstr[100];
    int geo_image_width;        // Image width  from GEO file
    int geo_image_height;       // Image height from GEO file

    time_t query_start_time, query_end_time; 

#ifdef USE_MAP_CACHE 
    int map_cache_return;
    char * cache_file_id;
#endif  // USE_MAP_CACHE

    char temp_file_path[MAX_VALUE];

    if (debug_level & 512) {
        if (nocache)
            fprintf(stderr,"draw_WMS_map: NOCACHE selected\n");
        else
            fprintf(stderr,"draw_WMS_map: CACHING if enabled\n");
    }

    // Create a shorter filename for display (one that fits the
    // status line more closely).  Subtract the length of the
    // "Indexing " and/or "Loading " strings as well.
    if (strlen(filenm) > (41 - 9)) {
        int avail = 41 - 11;
        int new_len = strlen(filenm) - avail;

        xastir_snprintf(short_filenm,
            sizeof(short_filenm),
            "..%s",
            &filenm[new_len]);
    }
    else {
        xastir_snprintf(short_filenm,
            sizeof(short_filenm),
            "%s",
            filenm);
    }

    xastir_snprintf(map_it,
        sizeof(map_it),
        langcode ("BBARSTA028"),
        short_filenm);
    statusline(map_it,0);       // Loading ...


        
    // Check whether we're indexing or drawing the map
    if ( (destination_pixmap == INDEX_CHECK_TIMESTAMPS)
            || (destination_pixmap == INDEX_NO_TIMESTAMPS) ) {

        // We're indexing only.  Save the extents in the index.
        // Force the extents to the edges of the earth for the
        // index file.
        index_update_xastir(filenm, // Filename only
            64800000l,      // Bottom
            0l,             // Top
            0l,             // Left
            129600000l,     // Right
            0);             // Default Map Level

        // Update statusline
        xastir_snprintf(map_it,
            sizeof(map_it),
            langcode ("BBARSTA039"),
            short_filenm);
        statusline(map_it,0);       // Loading/Indexing ...

        return; // Done indexing this file
    }


    // Tiepoint for upper left screen corner
    //
    tp[0].img_x = 0;                // Pixel Coordinates
    tp[0].img_y = 0;                // Pixel Coordinates
    tp[0].x_long = NW_corner_longitude;   // Xastir Coordinates
    tp[0].y_lat  = NW_corner_latitude;    // Xastir Coordinates


    // Tiepoint for lower right screen corner
    //
    // Here we must use scale_x for both directions because we have
    // square pixels returned by the WMS server.


// Really what we want to do here is to change our bounding box for
// our request to fit square pixels, using scale_x for both
// dimensions, and to change our tiepoints to match.  WMS servers
// currently feed us back square pixels but the spec says that the
// servers should be capable of sending back rectangular pixels, so
// the images we get back may change if we don't request square
// pixels each time.
//
// TODO:  Change our imagesize, bounding rectangle requested, and
// tiepoints to fit square pixels and to use scale_x for both
// dimensions.
//
// Actually, looking at the changes that were made, it looks like we
// _are_ using square pixels and requesting a bounding box based on
// scale_x for both dimensions, so we might be good to go as-is.


    //
    tp[1].img_x =  screen_width - 1; // Pixel Coordinates
    tp[1].img_y = screen_height - 1; // Pixel Coordinates 
    tp[1].x_long = SE_corner_longitude; // Xastir Coordinates

// Modified to use same scale (scale_x) for both dimensions, square
// pixels.  Don't use SE_corner_latitude here as it uses scale_y!
//    tp[1].y_lat  =  NW_corner_latitude + ((screen_height) * scale_y); // Xastir Coordinates
    tp[1].y_lat  =  NW_corner_latitude + ((screen_height) * scale_x); // Xastir Coordinates


    // Again, use scale_x for both directions due to the square
    // pixels returned from the WMS server.
    //
    left = (double)((NW_corner_longitude - 64800000l )/360000.0);   // Lat/long Coordinates
    top = (double)(-((NW_corner_latitude - 32400000l )/360000.0));  // Lat/long Coordinates
    right = (double)((SE_corner_longitude - 64800000l)/360000.0);//Lat/long Coordinates

// Modified to use same scale (scale_x) for both dimensions, square
// pixels.  Don't use SE_corner_latitude here as it uses scale_y!
//    bottom = (double)(-(((NW_corner_latitude + ((screen_height) * scale_y) ) - 32400000l)/360000.0));//Lat/long Coordinates
    bottom = (double)(-(((NW_corner_latitude + ((screen_height) * scale_x) ) - 32400000l)/360000.0));//Lat/long Coordinates


    map_width = right - left;   // Lat/long Coordinates
    map_height = top - bottom;  // Lat/long Coordinates

    geo_image_width  = screen_width;
    geo_image_height = screen_height;

    long_center = (left + right)/2.0l;
    lat_center  = (top + bottom)/2.0l;


//  Example query for a WMS map server....
//  xastir_snprintf(fileimg, sizeof(fileimg), 
//  "\'http://mesonet.tamu.edu/cgi-bin/p-warn?SERVICE=WMS&VERSION=1.1.1&REQUEST=getmap&layers=radar&BBOX=-129.000,52.500,-111.000,42.500&HEIGHT=1000&WIDTH=1800&FORMAT=image/png\'");


//    xastir_snprintf(WMStmp, sizeof(WMStmp),
//        "http://mesonet.tamu.edu/cgi-bin/p-warn?SERVICE=WMS&VERSION=1.1.1&REQUEST=getmap");


    xastir_snprintf(WMStmp, sizeof(WMStmp), "%s", URL);
    strncat(WMStmp, "&REQUEST=getmap", sizeof(WMStmp) - 1 - strlen(WMStmp));
    strncat(WMStmp, "&EXCEPTIONS=INIMAGE", sizeof(WMStmp) - 1 - strlen(WMStmp));

// This specifies a bounding box based on square pixels.
    xastir_snprintf(tmpstr, sizeof(tmpstr),
        "&BBOX=%8.5f,%7.5f,%8.5f,%7.5f",
        left,   // Lower left
        bottom, // Lower left
        right,  // Upper right
        top);   // Upper right
    strncat (WMStmp, tmpstr, sizeof(WMStmp) - 1 - strlen(WMStmp));

    xastir_snprintf(tmpstr, sizeof(tmpstr), "&HEIGHT=%d", geo_image_height);
    strncat (WMStmp, tmpstr, sizeof(WMStmp) - 1 - strlen(WMStmp));

    xastir_snprintf(tmpstr, sizeof(tmpstr), "&WIDTH=%d", geo_image_width);    
    strncat (WMStmp, tmpstr, sizeof(WMStmp) - 1 - strlen(WMStmp));


// These should be specified in the .geo file instead of hard-coded:
//
//    strncat(WMStmp, "&VERSION=1.0.0", sizeof(WMStmp) - 1 - strlen(WMStmp));
//    strncat(WMStmp, "&FORMAT=image/png", sizeof(WMStmp) - 1 - strlen(WMStmp));
//    strncat(WMStmp, "&TRANSPARENT=TRUE", sizeof(WMStmp) - 1 - strlen(WMStmp));
//    strncat(WMStmp, "&BGCOLOR=0xffffff", sizeof(WMStmp) - 1 - strlen(WMStmp));
//    strncat(WMStmp, "&BGCOLOR=0x000000", sizeof(WMStmp) - 1 - strlen(WMStmp));
//    strncat(WMStmp, "&CRS=CRS:84", sizeof(WMStmp) - 1 - strlen(WMStmp));





/*
    xastir_snprintf(WMStmp, sizeof(WMStmp), "http://tiger.census.gov/cgi-bin/mapper/map.png?");

    if (tiger_show_grid)
        strncat(WMStmp, "&on=GRID", sizeof(WMStmp) - 1 - strlen(WMStmp));
    else
        strncat(WMStmp, "&off=GRID", sizeof(WMStmp) - 1 - strlen(WMStmp));

    if (tiger_show_counties)
        strncat(WMStmp, "&on=counties", sizeof(WMStmp) - 1 - strlen(WMStmp));
    else
        strncat(WMStmp, "&off=counties", sizeof(WMStmp) - 1 - strlen(WMStmp));

    if (tiger_show_cities)
        strncat(WMStmp, "&on=CITIES", sizeof(WMStmp) - 1 - strlen(WMStmp));
    else
        strncat(WMStmp, "&off=CITIES", sizeof(WMStmp) - 1 - strlen(WMStmp));

    if (tiger_show_places)
        strncat(WMStmp, "&on=places", sizeof(WMStmp) - 1 - strlen(WMStmp));
    else
        strncat(WMStmp, "&off=places", sizeof(WMStmp) - 1 - strlen(WMStmp));

    if (tiger_show_majroads)
        strncat(WMStmp, "&on=majroads", sizeof(WMStmp) - 1 - strlen(WMStmp));
    else
        strncat(WMStmp, "&off=majroads", sizeof(WMStmp) - 1 - strlen(WMStmp));

    if (tiger_show_streets)
        strncat(WMStmp, "&on=streets", sizeof(WMStmp) - 1 - strlen(WMStmp));
    // Don't turn streets off since this will automagically show up as you zoom in.

    if (tiger_show_railroad)
        strncat(WMStmp, "&on=railroad", sizeof(WMStmp) - 1 - strlen(WMStmp));
    else
        strncat(WMStmp, "&off=railroad", sizeof(WMStmp) - 1 - strlen(WMStmp));

    if (tiger_show_states)
        strncat(WMStmp, "&on=states", sizeof(WMStmp) - 1 - strlen(WMStmp));
    else
        strncat(WMStmp, "&off=states", sizeof(WMStmp) - 1 - strlen(WMStmp));

    if (tiger_show_interstate)
        strncat(WMStmp, "&on=interstate", sizeof(WMStmp) - 1 - strlen(WMStmp));
    else
        strncat(WMStmp, "&off=interstate", sizeof(WMStmp) - 1 - strlen(WMStmp));

    if (tiger_show_ushwy)
        strncat(WMStmp, "&on=ushwy", sizeof(WMStmp) - 1 - strlen(WMStmp));
    else
        strncat(WMStmp, "&off=ushwy", sizeof(WMStmp) - 1 - strlen(WMStmp));

    if (tiger_show_statehwy)
        strncat(WMStmp, "&on=statehwy", sizeof(WMStmp) - 1 - strlen(WMStmp));
    else
        strncat(WMStmp, "&off=statehwy", sizeof(WMStmp) - 1 - strlen(WMStmp));

    if (tiger_show_water)
        strncat(WMStmp, "&on=water", sizeof(WMStmp) - 1 - strlen(WMStmp));
    else
        strncat(WMStmp, "&off=water", sizeof(WMStmp) - 1 - strlen(WMStmp));

    if (tiger_show_lakes)
        strncat(WMStmp, "&on=shorelin", sizeof(WMStmp) - 1 - strlen(WMStmp));
    else
        strncat(WMStmp, "&off=shorelin", sizeof(WMStmp) - 1 - strlen(WMStmp));

    if (tiger_show_misc)
        strncat(WMStmp, "&on=miscell", sizeof(WMStmp) - 1 - strlen(WMStmp));
    else
        strncat(WMStmp, "&off=miscell", sizeof(WMStmp) - 1 - strlen(WMStmp));

    xastir_snprintf(tmpstr, sizeof(tmpstr), "&lat=%f\046lon=%f\046", lat_center, long_center);    
    strncat (WMStmp, tmpstr, sizeof(WMStmp) - 1 - strlen(WMStmp));
    xastir_snprintf(tmpstr, sizeof(tmpstr), "wid=%f\046ht=%f\046", map_width, map_height);
    strncat (WMStmp, tmpstr, sizeof(WMStmp) - 1 - strlen(WMStmp));
    xastir_snprintf(tmpstr, sizeof(tmpstr), "iwd=%i\046iht=%i", tp[1].img_x + 1, tp[1].img_y + 1);
    strncat (WMStmp, tmpstr, sizeof(WMStmp) - 1 - strlen(WMStmp)); */


    xastir_snprintf(fileimg, sizeof(fileimg), "%s", WMStmp);

    if (debug_level & 512) {
          fprintf(stderr,"left side is %f\n", left);
          fprintf(stderr,"right side is %f\n", right);
          fprintf(stderr,"top  is %f\n", top);
          fprintf(stderr,"bottom is %f\n", bottom);
          fprintf(stderr,"lat center is %f\n", lat_center);
          fprintf(stderr,"long center is %f\n", long_center);
          fprintf(stderr,"screen width is %li\n", screen_width);
          fprintf(stderr,"screen height is %li\n", screen_height);
          fprintf(stderr,"map width is %f\n", map_width);
          fprintf(stderr,"map height is %f\n", map_height);
          fprintf(stderr,"fileimg is %s\n", fileimg);
          fprintf(stderr,"ftp or http file: %s\n", fileimg);
    }

    if (debug_level & 512) {
        query_start_time=time(&query_start_time); 
    }


#ifdef USE_MAP_CACHE 

    if (nocache || map_cache_fetch_disable) {

        // Delete old copy from the cache
        if (map_cache_fetch_disable && fileimg[0] != '\0') {
            if (map_cache_del(fileimg)) {
                if (debug_level & 512) {
                    fprintf(stderr,"Couldn't delete old map from cache\n");
                }
            }
        }

        // Simulate a cache miss
        map_cache_return = 1;
    }
    else {
        // Else look for the file in the cache
    	map_cache_return = map_cache_get(fileimg,local_filename); 
    }

	if (debug_level & 512) {
		fprintf(stderr,"map_cache_return: %d\n", map_cache_return);
	}
 

    // Don't use cached version if "nocache" is non-zero
    //	   
    if (nocache || map_cache_return != 0 ) {
        // Caching has not been requested or cached file not found.
        // We must snag the remote file via libcurl or wget.

        if (nocache) {
            xastir_snprintf(local_filename,
                sizeof(local_filename),
                "%s/map.%s",
                 get_user_base_dir("tmp", temp_file_path, sizeof(temp_file_path)),
                "png");
        }
        else {
            cache_file_id = map_cache_fileid();
            xastir_snprintf(local_filename,
                sizeof(local_filename),
                "%s/map_%s.%s",
                get_user_base_dir("map_cache", temp_file_path, sizeof(temp_file_path)),
                cache_file_id,
                "png");
            free(cache_file_id);
        }

#else   // USE_MAP_CACHE

    xastir_snprintf(local_filename,
        sizeof(local_filename),
        "%s/map.%s",
         get_user_base_dir("tmp", temp_file_path, sizeof(temp_file_path)),
        "png");

#endif  // USE_MAP_CACHE


    // Erase any previously existing local file by the same name.
    // This avoids the problem of having an old map image here and
    // the code trying to display it when the download fails.

    unlink( local_filename );

    HandlePendingEvents(app_context);
    if (interrupt_drawing_now) {
        // Update to screen
        (void)XCopyArea(XtDisplay(da),
            pixmap,
            XtWindow(da),
            gc,
            0,
            0,
            (unsigned int)screen_width,
            (unsigned int)screen_height,
            0,
            0);
        return;
    }

    if (fetch_remote_file(fileimg, local_filename)) {
        // Had trouble getting the file.  Abort.
        return;
    }

    // For debugging the MagickError/MagickWarning segfaults.
    //system("cat /dev/null >/var/tmp/xastir_hacker_map.png");

    
#ifdef USE_MAP_CACHE

    // Cache this map only if nocache is zero
    if (!nocache) {
        map_cache_put(fileimg,local_filename);
    }

        } // end if is cached  DHBROWN
#endif // USE_MAP_CACHE


    if (debug_level & 512) {
        fprintf (stderr, "Fetch or query took %d seconds\n", 
            (int) (time(&query_end_time) - query_start_time)); 
    }

    // Set permissions on the file so that any user can overwrite it.
    chmod(local_filename, 0666);

    // Tell ImageMagick where to find it
    xastir_snprintf(file,
        sizeof(file),
        "%s",
        local_filename);

    GetExceptionInfo(&exception);

    image_info=CloneImageInfo((ImageInfo *) NULL);

    xastir_snprintf(image_info->filename,
        sizeof(image_info->filename),
        "%s",
        file);

    if (debug_level & 512) {
           fprintf(stderr,"Copied %s into image info.\n", file);
           fprintf(stderr,"image_info got: %s\n", image_info->filename);
           fprintf(stderr,"Entered ImageMagick code.\n");
           fprintf(stderr,"Attempting to open: %s\n", image_info->filename);
    }

    // We do a test read first to see if the file exists, so we
    // don't kill Xastir in the ReadImage routine.
    f = fopen (image_info->filename, "r");
    if (f == NULL) {
        if (debug_level & 512)
            fprintf(stderr,"File could not be read\n");
        
#ifdef USE_MAP_CACHE
        // clear from cache if bad    
        if (map_cache_del(fileimg)) {
            if (debug_level & 512) {
                fprintf(stderr,"Couldn't delete map from cache\n");
            }
        }
#endif
         
        if (image_info)
            DestroyImageInfo(image_info);
	DestroyExceptionInfo(&exception);
        return;
    }
    (void)fclose (f);


    image = ReadImage(image_info, &exception);

    if (image == (Image *) NULL) {
        MagickWarning(exception.severity, exception.reason, exception.description);
        //fprintf(stderr,"MagickWarning\n");

#ifdef USE_MAP_CACHE
        // clear from cache if bad    
        if (map_cache_del(fileimg)) {
            if (debug_level & 512) {
                fprintf(stderr,"Couldn't delete map from cache\n");
            }
        }
#endif

        if (image_info)
            DestroyImageInfo(image_info);
	DestroyExceptionInfo(&exception);
        return;
    }


    if (debug_level & 512)
        fprintf(stderr,"Color depth is %i \n", (int)image->depth);

/*
    if (image->colorspace != RGBColorspace) {
        fprintf(stderr,"TBD: I don't think we can deal with colorspace != RGB");
        if (image)
            DestroyImage(image);
        if (image_info)
            DestroyImageInfo(image_info);
        DestroyExceptionInfo(&exception);
        return;
    }
*/

    width = image->columns;
    height = image->rows;

    //  Code to mute the image so it's not as bright.
/*    if (raster_map_intensity < 1.0) {
        char tempstr[30];

        if (debug_level & 512)
            fprintf(stderr,"level=%s\n", tempstr);

        xastir_snprintf(tempstr,
            sizeof(tempstr),
            "%d, 100, 100",
            (int)(raster_map_intensity * 100.0));

        ModulateImage(image, tempstr);
    }
*/


    // If were are drawing to a low bpp display (typically < 8bpp)
    // try to reduce the number of colors in an image.
    // This may take some time, so it would be best to do ahead of
    // time if it is a static image.
#if (MagickLibVersion < 0x0540)
    if (visual_type == NOT_TRUE_NOR_DIRECT && GetNumberColors(image, NULL) > 128) {
#else   // MagickLib >= 540
    if (visual_type == NOT_TRUE_NOR_DIRECT && GetNumberColors(image, NULL, &exception) > 128) {
#endif  // MagickLib Version

        if (image->storage_class == PseudoClass) {
#if (MagickLibVersion < 0x0549)
            CompressColormap(image); // Remove duplicate colors
#else // MagickLib >= 0x0549
            CompressImageColormap(image); // Remove duplicate colors
#endif  // MagickLibVersion < 0x0549
        }

        // Quantize down to 128 will go here...
    }


    pixel_pack = GetImagePixels(image, 0, 0, image->columns, image->rows);
    if (!pixel_pack) {
        fprintf(stderr,"pixel_pack == NULL!!!");
        if (image)
            DestroyImage(image);
        if (image_info)
            DestroyImageInfo(image_info);
        DestroyExceptionInfo(&exception);
        return;
    }


    index_pack = GetIndexes(image);
    if (image->storage_class == PseudoClass && !index_pack) {
        fprintf(stderr,"PseudoClass && index_pack == NULL!!!");
        if (image)
            DestroyImage(image);
        if (image_info)
            DestroyImageInfo(image_info);
        DestroyExceptionInfo(&exception);
        return;
    }


    if (image->storage_class == PseudoClass && image->colors <= 256) {
        for (l = 0; l < (int)image->colors; l++) {
            // Need to check how to do this for ANY image, as ImageMagick can read in all sorts
            // of image files
            temp_pack = image->colormap[l];
            if (debug_level & 512)
                fprintf(stderr,"Colormap color is %i  %i  %i \n",
                       temp_pack.red, temp_pack.green, temp_pack.blue);

            // Here's a tricky bit:  PixelPacket entries are defined as Quantum's.  Quantum
            // is defined in /usr/include/magick/image.h as either an unsigned short or an
            // unsigned char, depending on what "configure" decided when ImageMagick was installed.
            // We can determine which by looking at MaxRGB or QuantumDepth.
            //
            if (QuantumDepth == 16) {   // Defined in /usr/include/magick/image.h
                if (debug_level & 512)
                    fprintf(stderr,"Color quantum is [0..65535]\n");
                my_colors[l].red   = temp_pack.red * raster_map_intensity;
                my_colors[l].green = temp_pack.green * raster_map_intensity;
                my_colors[l].blue  = temp_pack.blue * raster_map_intensity;
            }
            else {  // QuantumDepth = 8
                if (debug_level & 512)
                    fprintf(stderr,"Color quantum is [0..255]\n");
                my_colors[l].red   = (temp_pack.red << 8) * raster_map_intensity;
                my_colors[l].green = (temp_pack.green << 8) * raster_map_intensity;
                my_colors[l].blue  = (temp_pack.blue << 8) * raster_map_intensity;
            }

            // Get the color allocated on < 8bpp displays. pixel color is written to my_colors.pixel
            if (visual_type == NOT_TRUE_NOR_DIRECT) {
//                XFreeColors(XtDisplay(w), cmap, &(my_colors[l].pixel),1,0);
                XAllocColor(XtDisplay(w), cmap, &my_colors[l]);
            }
            else {
                pack_pixel_bits(my_colors[l].red, my_colors[l].green, my_colors[l].blue,
                                &my_colors[l].pixel);
            }

            if (debug_level & 512)
                fprintf(stderr,"Color allocated is %li  %i  %i  %i \n", my_colors[l].pixel,
                       my_colors[l].red, my_colors[l].blue, my_colors[l].green);
        }
    }



    /*
    * Here are the corners of our viewport, using the Xastir
    * coordinate system.  Notice that Y is upside down:
    *
    *   left edge of view = NW_corner_longitude
    *  right edge of view = SE_corner_longitude
    *    top edge of view =  NW_corner_latitude
    * bottom edge of view =  SE_corner_latitude
    *
    * The corners of our map will soon be (after translating the
    * tiepoints to the corners if they're not already there):
    *
    *   left edge of map = tp[0].x_long   in Xastir format
    *  right edge of map = tp[1].x_long
    *    top edge of map = tp[0].y_lat
    * bottom edge of map = tp[1].y_lat
    *
    */
    map_c_L = tp[0].x_long - NW_corner_longitude;     // map left coordinate
    map_c_T = tp[0].y_lat  - NW_corner_latitude;      // map top  coordinate

    tp_c_dx = (long)(tp[1].x_long - tp[0].x_long);//  Width between tiepoints
    tp_c_dy = (long)(tp[1].y_lat  - tp[0].y_lat); // Height between tiepoints


    // Check for tiepoints being in wrong relation to one another
    if (tp_c_dx < 0) 
        tp_c_dx = -tp_c_dx;       // New  width between tiepoints
    if (tp_c_dy < 0) 
        tp_c_dy = -tp_c_dy;       // New height between tiepoints

    // Calculate step size per pixel
    map_c_dx = ((double) tp_c_dx / abs(tp[1].img_x - tp[0].img_x));
    map_c_dy = ((double) tp_c_dy / abs(tp[1].img_y - tp[0].img_y));

    // Scaled screen step size for use with XFillRectangle below
    scr_dx = (int) (map_c_dx / scale_x) + 1;
    scr_dy = (int) (map_c_dy / scale_y) + 1;

    // calculate top left map corner from tiepoints
    if (tp[0].img_x != 0) {
        tp[0].x_long -= (tp[0].img_x * map_c_dx);   // map left edge longitude
        map_c_L = tp[0].x_long - NW_corner_longitude;     // delta ??
        tp[0].img_x = 0;
        if (debug_level & 512)
            fprintf(stderr,"Translated tiepoint_0 x: %d\t%lu\n", tp[0].img_x, tp[0].x_long);
    }
    if (tp[0].img_y != 0) {
        tp[0].y_lat -= (tp[0].img_y * map_c_dy);    // map top edge latitude
        map_c_T = tp[0].y_lat - NW_corner_latitude;
        tp[0].img_y = 0;
        if (debug_level & 512)
            fprintf(stderr,"Translated tiepoint_0 y: %d\t%lu\n", tp[0].img_y, tp[0].y_lat);
    }

    // calculate bottom right map corner from tiepoints
    // map size is geo_image_width / geo_image_height
    if (tp[1].img_x != (geo_image_width - 1) ) {
        tp[1].img_x = geo_image_width - 1;
        tp[1].x_long = tp[0].x_long + (tp[1].img_x * map_c_dx); // right
        if (debug_level & 512)
            fprintf(stderr,"Translated tiepoint_1 x: %d\t%lu\n", tp[1].img_x, tp[1].x_long);
    }
    if (tp[1].img_y != (geo_image_height - 1) ) {
        tp[1].img_y = geo_image_height - 1;
        tp[1].y_lat = tp[0].y_lat + (tp[1].img_y * map_c_dy);   // bottom
        if (debug_level & 512)
            fprintf(stderr,"Translated tiepoint_1 y: %d\t%lu\n", tp[1].img_y, tp[1].y_lat);
    }

    if (debug_level & 512) {
        fprintf(stderr,"X tiepoint width: %ld\n", tp_c_dx);
        fprintf(stderr,"Y tiepoint width: %ld\n", tp_c_dy);
        fprintf(stderr,"Loading imagemap: %s\n", file);
        fprintf(stderr,"\nImage: %s\n", file);
        fprintf(stderr,"Image size %d %d\n", geo_image_width, geo_image_height);
        fprintf(stderr,"XX: %ld YY:%ld Sx %f %d Sy %f %d\n",
            map_c_L, map_c_T, map_c_dx,(int) (map_c_dx / scale_x), map_c_dy, (int) (map_c_dy / scale_y));
        fprintf(stderr,"Image size %d %d\n", width, height);
#if (MagickLibVersion < 0x0540)
        fprintf(stderr,"Unique colors = %d\n", GetNumberColors(image, NULL));
#else // MagickLib < 540
        fprintf(stderr,"Unique colors = %ld\n", GetNumberColors(image, NULL, &exception));
#endif // MagickLib < 540
        fprintf(stderr,"XX: %ld YY:%ld Sx %f %d Sy %f %d\n", map_c_L, map_c_T,
            map_c_dx,(int) (map_c_dx / scale_x), map_c_dy, (int) (map_c_dy / scale_y));
        fprintf(stderr,"image matte is %i\n", image->matte);
    } // debug_level & 512

    // draw the image from the file out to the map screen

    // Get the border values for the X and Y for loops used
    // for the XFillRectangle call later.

    map_c_yc = (tp[0].y_lat + tp[1].y_lat) / 2;     // vert center of map as reference
    map_y_ctr = (long)(height / 2 +0.499);
    scale_x0 = get_x_scale(0,map_c_yc,scale_y);     // reference scaling at vert map center

    map_c_xc  = (tp[0].x_long + tp[1].x_long) / 2;  // hor center of map as reference
    map_x_ctr = (long)(width  / 2 +0.499);
    scr_x_mc  = (map_c_xc - NW_corner_longitude) / scale_x; // screen coordinates of map center

    // calculate map pixel range in y direction that falls into screen area
    c_y_max = 0ul;
    map_y_min = map_y_max = 0l;
    for (map_y_0 = 0, c_y = tp[0].y_lat; map_y_0 < (long)height; map_y_0++, c_y += map_c_dy) {
        scr_y = (c_y - NW_corner_latitude) / scale_y;   // current screen position
        if (scr_y > 0) {
            if (scr_y < screen_height) {
                map_y_max = map_y_0;          // update last map pixel in y
                c_y_max = (unsigned long)c_y;// bottom map inside screen coordinate
            } else
                break;                      // done, reached bottom screen border
        } else {                            // pixel is above screen
            map_y_min = map_y_0;              // update first map pixel in y
        }
    }
    c_y_min = (unsigned long)(tp[0].y_lat + map_y_min * map_c_dy);   // top map inside screen coordinate

        map_x_min = map_x_max = 0l;
        for (map_x = 0, c_x = tp[0].x_long; map_x < (long)width; map_x++, c_x += map_c_dx) {
            scr_x = (c_x - NW_corner_longitude)/ scale_x;  // current screen position
            if (scr_x > 0) {
                if (scr_x < screen_width)
                    map_x_max = map_x;          // update last map pixel in x
                else
                    break;                      // done, reached right screen border
            } else {                            // pixel is left from screen
                map_x_min = map_x;              // update first map pixel in x
            }
        }
        c_x_min = (unsigned long)(tp[0].x_long + map_x_min * map_c_dx);   // left map inside screen coordinate

    scr_yp = -1;
    scr_c_xr = SE_corner_longitude;
    c_dx = map_c_dx;                            // map pixel width
    scale_xa = scale_x0;                        // the compiler likes it ;-)

    map_done = 0;
    map_act  = 0;
    map_seen = 0;
    scr_y = screen_height - 1;


    // loop over map pixel rows
    for (map_y_0 = map_y_min, c_y = (double)c_y_min; (map_y_0 <= map_y_max); map_y_0++, c_y += map_c_dy) {

        HandlePendingEvents(app_context);
        if (interrupt_drawing_now) {
            if (image)
                DestroyImage(image);
            if (image_info)
                DestroyImageInfo(image_info);
            // Update to screen
            (void)XCopyArea(XtDisplay(da),
                pixmap,
                XtWindow(da),
                gc,
                0,
                0,
                (unsigned int)screen_width,
                (unsigned int)screen_height,
                0,
                0);
            return;
        }

        scr_y = (c_y - NW_corner_latitude) / scale_y;
        if (scr_y != scr_yp) {                  // don't do a row twice
            scr_yp = scr_y;                     // remember as previous y
            scr_xp = -1;
            // loop over map pixel columns
            map_act = 0;
            scale_x_nm = calc_dscale_x(0,(long)c_y) / 1852.0;  // nm per Xastir coordinate
            for (map_x = map_x_min, c_x = (double)c_x_min; map_x <= map_x_max; map_x++, c_x += c_dx) {
                scr_x = (c_x - NW_corner_longitude) / scale_x;
                if (scr_x != scr_xp) {      // don't do a pixel twice
                    scr_xp = scr_x;         // remember as previous x
                    map_y = map_y_0;

                    if (map_y >= 0 && map_y <= tp[1].img_y) { // check map boundaries in y direction
                        map_seen = 1;
                        map_act = 1;    // detects blank screen rows (end of map)

                        // now copy a pixel from the map image to the screen
                        l = map_x + map_y * image->columns;
                        trans_skip = 1; // possibly transparent
                        if (image->storage_class == PseudoClass) {
                            if ( c_trans_color_head &&
                                    check_trans(my_colors[index_pack[l]],c_trans_color_head)) {
                                trans_skip = 1; // skip it
                            }
                            else {
                                XSetForeground(XtDisplay(w), gc, my_colors[index_pack[l]].pixel);
                                trans_skip = 0; // draw it
                            }
                        }
                        else {
                            // It is not safe to assume that the red/green/blue
                            // elements of pixel_pack of type Quantum are the
                            // same as the red/green/blue of an XColor!
                            if (QuantumDepth==16) {
                                my_colors[0].red=pixel_pack[l].red;
                                my_colors[0].green=pixel_pack[l].green;
                                my_colors[0].blue=pixel_pack[l].blue;
                            }
                            else { // QuantumDepth=8
                                // shift the bits of the 8-bit quantity so that
                                // they become the high bigs of my_colors.*
                                my_colors[0].red=pixel_pack[l].red<<8;
                                my_colors[0].green=pixel_pack[l].green<<8;
                                my_colors[0].blue=pixel_pack[l].blue<<8;
                            }
                            // NOW my_colors has the right r,g,b range for
                            // pack_pixel_bits
                            pack_pixel_bits(my_colors[0].red * raster_map_intensity,
                                            my_colors[0].green * raster_map_intensity,
                                            my_colors[0].blue * raster_map_intensity,
                                            &my_colors[0].pixel);
                            if ( c_trans_color_head &&
                                    check_trans(my_colors[0],c_trans_color_head)) {
                                trans_skip = 1; // skip it
                            }
                            else {
                                XSetForeground(XtDisplay(w), gc, my_colors[0].pixel);
                                trans_skip = 0; // draw it
                            }
                        }

                        // Skip drawing if a transparent pixel
                        if (!trans_skip) {
                            (void)XFillRectangle (XtDisplay (w),pixmap,gc,scr_x,scr_y,scr_dx,scr_dy);
                        }

                    } // check map boundaries in y direction
                }
            } // loop over map pixel columns
            if (map_seen && !map_act)
                map_done = 1;
        }
    } // loop over map pixel rows

    if (image)
       DestroyImage(image);
    if (image_info)
       DestroyImageInfo(image_info);
    DestroyExceptionInfo(&exception);
}
Example #9
0
File: describe.c Project: pedia/cwf
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   D e s c r i b e I m a g e                                                 %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  DescribeImage() describes an image by printing its attributes to the file.
%  Attributes include the image width, height, size, and others.
%
%  The format of the DescribeImage method is:
%
%      void DescribeImage(Image *image,FILE *file,const MagickBool verbose)
%
%  A description of each parameter follows:
%
%    o image: The image.
%
%    o file: The file, typically stdout.
%
%    o verbose: A value other than zero prints more detailed information
%      about the image. Values greater than one enable counting the number of
%      colors in the image.
%
%
*/
MagickExport MagickPassFail DescribeImage(Image *image,FILE *file,
        const MagickBool verbose)
{
    char
    color[MaxTextExtent],
          format[MaxTextExtent];

    const unsigned char
    *profile;

    size_t
    profile_length;

    const ImageAttribute
    *attribute;

    const MagickInfo
    *magick_info;

    double
    elapsed_time,
    user_time;

    unsigned long
    columns,
    rows;

    magick_int64_t
    pixels_per_second;

    Image
    *p;

    long
    y;

    register long
    i,
    x;

    unsigned long
    count;

    assert(image != (Image *) NULL);
    assert(image->signature == MagickSignature);
    assert(file != (FILE *) NULL);
    elapsed_time=GetElapsedTime(&image->timer);
    user_time=GetUserTime(&image->timer);
    GetTimerInfo(&image->timer);
    if (!verbose)
    {
        /*
          Display summary info about the image.
        */
        if (*image->magick_filename != '\0')
            if (LocaleCompare(image->magick_filename,image->filename) != 0)
                (void) fprintf(file,"%.1024s=>",image->magick_filename);
        if ((image->previous == (Image *) NULL) &&
                (image->next == (Image *) NULL) && (image->scene == 0))
            (void) fprintf(file,"%.1024s ",image->filename);
        else
            (void) fprintf(file,"%.1024s[%lu] ",image->filename,image->scene);
        (void) fprintf(file,"%.1024s ",image->magick);
        columns=image->columns;
        rows=image->rows;
        if ((image->magick_columns != 0) || (image->magick_rows != 0))
            if ((image->magick_columns != image->columns) ||
                    (image->magick_rows != image->rows))
            {
                columns=image->magick_columns;
                rows=image->magick_rows;
                (void) fprintf(file,"%lux%lu=>",image->magick_columns,
                               image->magick_rows);
            }
        (void) fprintf(file,"%lux%lu%+ld%+ld ",image->columns,image->rows,
                       image->page.x,image->page.y);
        if (image->storage_class == DirectClass)
        {
            (void) fprintf(file,"DirectClass ");
            if (image->total_colors != 0)
            {
                FormatSize(image->total_colors,format);
                (void) fprintf(file,"%.1024s ",format);
            }
        }
        else if (image->total_colors <= image->colors)
            (void) fprintf(file,"PseudoClass %uc ",image->colors);
        else
        {
            (void) fprintf(file,"PseudoClass %lu=>%uc ",image->total_colors,
                           image->colors);
            (void) fprintf(file,"%ld/%.6f/%.6fe ",
                           (long) image->error.mean_error_per_pixel,
                           image->error.normalized_mean_error,
                           image->error.normalized_maximum_error);
        }
        (void) fprintf(file,"%u-bit ",image->depth);
        if (GetBlobSize(image) != 0)
        {
            FormatSize(GetBlobSize(image),format);
            (void) fprintf(file,"%.1024s ",format);
        }
        (void) fprintf(file,"%0.3fu %ld:%02ld",user_time,
                       (long) (elapsed_time/60.0),
                       (long) ceil(fmod(elapsed_time,60.0)));
        /*
          Only display pixel read rate if the time accumulated is at
          least six times the timer's resolution (typically 0.01 on
          Unix).
        */
        if (elapsed_time >= GetTimerResolution()*6)
        {
            pixels_per_second=(magick_int64_t) ((double) rows*columns/ elapsed_time);
            FormatSize(pixels_per_second,format);
            (void) fprintf(file," (%s pixels/s)",format);
        }
        (void) fprintf(file,"\n");

        return (ferror(file) ? MagickFail : MagickPass);
    }
    /*
      Display verbose info about the image.
    */
    (void) SignatureImage(image);
    if (verbose > 1)
        image->total_colors=GetNumberColors(image,(FILE *) NULL,&image->exception);
    (void) fprintf(file,"Image: %.1024s\n",image->filename);
    magick_info=GetMagickInfo(image->magick,&image->exception);
    if ((magick_info == (const MagickInfo *) NULL) ||
            (*magick_info->description == '\0'))
        (void) fprintf(file,"  Format: %.1024s\n",image->magick);
    else
        (void) fprintf(file,"  Format: %.1024s (%.1024s)\n",image->magick,
                       magick_info->description);
    (void) fprintf(file,"  Geometry: %lux%lu\n",image->columns,image->rows);
    if (image->storage_class == DirectClass)
        (void) fprintf(file,"  Class: DirectClass\n");
    else
        (void) fprintf(file,"  Class: PseudoClass\n");
    if ((image->magick_columns != 0) || (image->magick_rows != 0))
        if ((image->magick_columns != image->columns) ||
                (image->magick_rows != image->rows))
            (void) fprintf(file,"  Base geometry: %lux%lu\n",image->magick_columns,
                           image->magick_rows);
    (void) fprintf(file,"  Type: ");
    switch (GetImageType(image,&image->exception))
    {
    case BilevelType:
        (void) fprintf(file,"bilevel");
        break;
    case GrayscaleType:
        (void) fprintf(file,"grayscale");
        break;
    case GrayscaleMatteType:
        (void) fprintf(file,"grayscale with transparency");
        break;
    case PaletteType:
        (void) fprintf(file,"palette");
        break;
    case PaletteMatteType:
        (void) fprintf(file,"palette with transparency");
        break;
    case TrueColorType:
        (void) fprintf(file,"true color");
        break;
    case TrueColorMatteType:
        (void) fprintf(file,"true color with transparency");
        break;
    case ColorSeparationType:
        (void) fprintf(file,"color separated");
        break;
    case ColorSeparationMatteType:
        (void) fprintf(file,"color separated with transparency");
        break;
    default:
        (void) fprintf(file,"undefined");
        break;
    }
    (void) fprintf(file,"\n");
    (void) fprintf(file,"  Depth: %lu bits-per-pixel component\n",
                   GetImageDepth(image,&image->exception));
    (void) fprintf(file,"  Channel Depths:\n");
    if (image->colorspace == CMYKColorspace)
    {
        (void) fprintf(file,"    Cyan:     %u bits\n",
                       GetImageChannelDepth(image,CyanChannel,&image->exception));
        (void) fprintf(file,"    Magenta:  %u bits\n",
                       GetImageChannelDepth(image,MagentaChannel,&image->exception));
        (void) fprintf(file,"    Yellow:   %u bits\n",
                       GetImageChannelDepth(image,YellowChannel,&image->exception));
        (void) fprintf(file,"    Black:    %u bits\n",
                       GetImageChannelDepth(image,BlackChannel,&image->exception));
    }
    else if ((IsGrayColorspace(image->colorspace)) ||
             (image->is_grayscale == True))
    {
        (void) fprintf(file,"    Gray:     %u bits\n",
                       GetImageChannelDepth(image,RedChannel,&image->exception));
    }
    else
    {
        (void) fprintf(file,"    Red:      %u bits\n",
                       GetImageChannelDepth(image,RedChannel,&image->exception));
        (void) fprintf(file,"    Green:    %u bits\n",
                       GetImageChannelDepth(image,GreenChannel,&image->exception));
        (void) fprintf(file,"    Blue:     %u bits\n",
                       GetImageChannelDepth(image,BlueChannel,&image->exception));
    }
    if (image->matte)
        (void) fprintf(file,"    Opacity:  %u bits\n",
                       GetImageChannelDepth(image,OpacityChannel,&image->exception));
    (void) fprintf(file,"  Channel Statistics:\n");
    {
        ImageStatistics
        statistics;

        (void) GetImageStatistics(image,&statistics,&image->exception);

        if (image->colorspace == CMYKColorspace)
        {
            (void) fprintf(file,"    Cyan:\n");
            (void) fprintf(file,"      Minimum:            %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.red.minimum,
                           statistics.red.minimum);
            (void) fprintf(file,"      Maximum:            %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.red.maximum,
                           statistics.red.maximum);
            (void) fprintf(file,"      Mean:               %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.red.mean,
                           statistics.red.mean);
            (void) fprintf(file,"      Standard Deviation: %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.red.standard_deviation,
                           statistics.red.standard_deviation);
            (void) fprintf(file,"    Magenta:\n");
            (void) fprintf(file,"      Minimum:            %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.green.minimum,
                           statistics.green.minimum);
            (void) fprintf(file,"      Maximum:            %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.green.maximum,
                           statistics.green.maximum);
            (void) fprintf(file,"      Mean:               %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.green.mean,
                           statistics.green.mean);
            (void) fprintf(file,"      Standard Deviation: %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.green.standard_deviation,
                           statistics.green.standard_deviation);
            (void) fprintf(file,"    Yellow:\n");
            (void) fprintf(file,"      Minimum:            %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.blue.minimum,
                           statistics.blue.minimum);
            (void) fprintf(file,"      Maximum:            %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.blue.maximum,
                           statistics.blue.maximum);
            (void) fprintf(file,"      Mean:               %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.blue.mean,
                           statistics.blue.mean);
            (void) fprintf(file,"      Standard Deviation: %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.blue.standard_deviation,
                           statistics.blue.standard_deviation);
            (void) fprintf(file,"    Black:\n");
            (void) fprintf(file,"      Minimum:            %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.opacity.minimum,
                           statistics.opacity.minimum);
            (void) fprintf(file,"      Maximum:            %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.opacity.maximum,
                           statistics.opacity.maximum);
            (void) fprintf(file,"      Mean:               %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.opacity.mean,
                           statistics.opacity.mean);
            (void) fprintf(file,"      Standard Deviation: %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.opacity.standard_deviation,
                           statistics.opacity.standard_deviation);
            /*
            if (image->matte)
              (void) fprintf(file,"    Opacity:\n");
            */
        }
        else if ((IsGrayColorspace(image->colorspace)) ||
                 (image->is_grayscale == True))
        {
            (void) fprintf(file,"    Gray:\n");
            (void) fprintf(file,"      Minimum:            %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.red.minimum,
                           statistics.red.minimum);
            (void) fprintf(file,"      Maximum:            %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.red.maximum,
                           statistics.red.maximum);
            (void) fprintf(file,"      Mean:               %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.red.mean,
                           statistics.red.mean);
            (void) fprintf(file,"      Standard Deviation: %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.red.standard_deviation,
                           statistics.red.standard_deviation);
            if (image->matte)
            {
                (void) fprintf(file,"    Opacity:\n");
                (void) fprintf(file,"      Minimum:            %13.02lf (%1.4f)\n",
                               MaxRGB*statistics.opacity.minimum,
                               statistics.opacity.minimum);
                (void) fprintf(file,"      Maximum:            %13.02lf (%1.4f)\n",
                               MaxRGB*statistics.opacity.maximum,
                               statistics.opacity.maximum);
                (void) fprintf(file,"      Mean:               %13.02lf (%1.4f)\n",
                               MaxRGB*statistics.opacity.mean,
                               statistics.opacity.mean);
                (void) fprintf(file,"      Standard Deviation: %13.02lf (%1.4f)\n",
                               MaxRGB*statistics.opacity.standard_deviation,
                               statistics.opacity.standard_deviation);
            }
        }
        else
        {
            (void) fprintf(file,"    Red:\n");
            (void) fprintf(file,"      Minimum:            %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.red.minimum,
                           statistics.red.minimum);
            (void) fprintf(file,"      Maximum:            %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.red.maximum,
                           statistics.red.maximum);
            (void) fprintf(file,"      Mean:               %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.red.mean,
                           statistics.red.mean);
            (void) fprintf(file,"      Standard Deviation: %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.red.standard_deviation,
                           statistics.red.standard_deviation);
            (void) fprintf(file,"    Green:\n");
            (void) fprintf(file,"      Minimum:            %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.green.minimum,
                           statistics.green.minimum);
            (void) fprintf(file,"      Maximum:            %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.green.maximum,
                           statistics.green.maximum);
            (void) fprintf(file,"      Mean:               %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.green.mean,
                           statistics.green.mean);
            (void) fprintf(file,"      Standard Deviation: %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.green.standard_deviation,
                           statistics.green.standard_deviation);
            (void) fprintf(file,"    Blue:\n");
            (void) fprintf(file,"      Minimum:            %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.blue.minimum,
                           statistics.blue.minimum);
            (void) fprintf(file,"      Maximum:            %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.blue.maximum,
                           statistics.blue.maximum);
            (void) fprintf(file,"      Mean:               %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.blue.mean,
                           statistics.blue.mean);
            (void) fprintf(file,"      Standard Deviation: %13.02lf (%1.4f)\n",
                           MaxRGB*statistics.blue.standard_deviation,
                           statistics.blue.standard_deviation);
            if (image->matte)
            {
                (void) fprintf(file,"    Opacity:\n");
                (void) fprintf(file,"      Minimum:            %13.02lf (%1.4f)\n",
                               MaxRGB*statistics.opacity.minimum,
                               statistics.opacity.minimum);
                (void) fprintf(file,"      Maximum:            %13.02lf (%1.4f)\n",
                               MaxRGB*statistics.opacity.maximum,
                               statistics.opacity.maximum);
                (void) fprintf(file,"      Mean:               %13.02lf (%1.4f)\n",
                               MaxRGB*statistics.opacity.mean,
                               statistics.opacity.mean);
                (void) fprintf(file,"      Standard Deviation: %13.02lf (%1.4f)\n",
                               MaxRGB*statistics.opacity.standard_deviation,
                               statistics.opacity.standard_deviation);
            }
        }
    }
    x=0;
    p=(Image *) NULL;
    if ((image->matte && (strcmp(image->magick,"GIF") != 0)) || image->taint)
    {
        char
        tuple[MaxTextExtent];

        register const PixelPacket
        *p;

        p=(PixelPacket *) NULL;
        for (y=0; y < (long) image->rows; y++)
        {
            p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
            if (p == (const PixelPacket *) NULL)
                break;
            for (x=0; x < (long) image->columns; x++)
            {
                if (p->opacity == TransparentOpacity)
                    break;
                p++;
            }
            if (x < (long) image->columns)
                break;
        }
        if ((x < (long) image->columns) || (y < (long) image->rows))
        {
            GetColorTuple(p,image->depth,image->matte,False,tuple);
            (void) fprintf(file,"  Opacity: %.1024s\t",tuple);
            GetColorTuple(p,image->depth,image->matte,True,tuple);
            (void) fprintf(file,"  %.1024s\n",tuple);
        }
    }
    if (image->storage_class == DirectClass)
    {
        if (image->total_colors != 0)
            (void) fprintf(file,"  Colors: %lu\n",image->total_colors);
    }
    else
    {
        if (image->total_colors <= image->colors)
            (void) fprintf(file,"  Colors: %u\n",image->colors);
        else
            (void) fprintf(file,"  Colors: %lu=>%u\n",image->total_colors,
                           image->colors);
    }
    if (image->storage_class == DirectClass)
    {
        if (image->total_colors < 1024)
            if (verbose > 1)
                (void) GetNumberColors(image,file,&image->exception);
    }
    else
    {
        char
        name[MaxTextExtent];

        register PixelPacket
        *p;

        /*
          Display image colormap.
        */
        p=image->colormap;
        for (i=0; i < (long) image->colors; i++)
        {
            char
            tuple[MaxTextExtent];

            GetColorTuple(p,image->depth,image->matte,False,tuple);
            (void) fprintf(file,"    %lu: %.1024s",i,tuple);
            (void) fprintf(file,"\t");
            (void) QueryColorname(image,p,SVGCompliance,name,&image->exception);
            (void) fprintf(file,"  %.1024s",name);
            (void) fprintf(file,"\n");
            p++;
        }
    }
    if (image->error.mean_error_per_pixel != 0.0)
        (void) fprintf(file,"  Mean Exception Per Pixel: %ld\n",
                       (long) image->error.mean_error_per_pixel);
    if (image->error.normalized_mean_error != 0.0)
        (void) fprintf(file,"  Normalized Mean Exception: %g\n",
                       image->error.normalized_mean_error);
    if (image->error.normalized_maximum_error != 0.0)
        (void) fprintf(file,"  Normalized Maximum Exception: %gn",
                       image->error.normalized_maximum_error);
    if (image->rendering_intent == SaturationIntent)
        (void) fprintf(file,"  Rendering-Intent: saturation\n");
    else if (image->rendering_intent == PerceptualIntent)
        (void) fprintf(file,"  Rendering-Intent: perceptual\n");
    else if (image->rendering_intent == AbsoluteIntent)
        (void) fprintf(file,"  Rendering-Intent: absolute\n");
    else if (image->rendering_intent == RelativeIntent)
        (void) fprintf(file,"  Rendering-Intent: relative\n");
    if (image->gamma != 0.0)
        (void) fprintf(file,"  Gamma: %g\n",image->gamma);
    if ((image->chromaticity.red_primary.x != 0.0) ||
            (image->chromaticity.green_primary.x != 0.0) ||
            (image->chromaticity.blue_primary.x != 0.0) ||
            (image->chromaticity.white_point.x != 0.0))
    {
        /*
          Display image chromaticity.
        */
        (void) fprintf(file,"  Chromaticity:\n");
        (void) fprintf(file,"    red primary: (%g,%g)\n",
                       image->chromaticity.red_primary.x,image->chromaticity.red_primary.y);
        (void) fprintf(file,"    green primary: (%g,%g)\n",
                       image->chromaticity.green_primary.x,
                       image->chromaticity.green_primary.y);
        (void) fprintf(file,"    blue primary: (%g,%g)\n",
                       image->chromaticity.blue_primary.x,image->chromaticity.blue_primary.y);
        (void) fprintf(file,"    white point: (%g,%g)\n",
                       image->chromaticity.white_point.x,image->chromaticity.white_point.y);
    }
    if ((image->tile_info.width*image->tile_info.height) != 0)
        (void) fprintf(file,"  Tile geometry: %lux%lu%+ld%+ld\n",
                       image->tile_info.width,image->tile_info.height,image->tile_info.x,
                       image->tile_info.y);
    if ((image->x_resolution != 0.0) && (image->y_resolution != 0.0))
    {
        /*
          Display image resolution.
        */
        (void) fprintf(file,"  Resolution: %gx%g",image->x_resolution,
                       image->y_resolution);
        if (image->units == UndefinedResolution)
            (void) fprintf(file," pixels\n");
        else if (image->units == PixelsPerInchResolution)
            (void) fprintf(file," pixels/inch\n");
        else if (image->units == PixelsPerCentimeterResolution)
            (void) fprintf(file," pixels/centimeter\n");
        else
            (void) fprintf(file,"\n");
    }
    FormatSize(GetBlobSize(image),format);
    (void) fprintf(file,"  Filesize: %.1024s\n",format);
    fprintf(file,"  Interlace: %s\n",
            InterlaceTypeToString(image->interlace == UndefinedInterlace ?
                                  NoInterlace : image->interlace));
    (void) fprintf(file,"  Orientation: %s\n", OrientationTypeToString(image->orientation));
    (void) QueryColorname(image,&image->background_color,SVGCompliance,color,
                          &image->exception);
    (void) fprintf(file,"  Background Color: %.1024s\n",color);
    (void) QueryColorname(image,&image->border_color,SVGCompliance,color,
                          &image->exception);
    (void) fprintf(file,"  Border Color: %.1024s\n",color);
    (void) QueryColorname(image,&image->matte_color,SVGCompliance,color,
                          &image->exception);
    (void) fprintf(file,"  Matte Color: %.1024s\n",color);
    if ((image->page.width != 0) && (image->page.height != 0))
        (void) fprintf(file,"  Page geometry: %lux%lu%+ld%+ld\n",image->page.width,
                       image->page.height,image->page.x,image->page.y);
    (void) fprintf(file,"  Compose: %s\n",
                   CompositeOperatorToString(image->compose));
    (void) fprintf(file,"  Dispose: ");
    switch (image->dispose)
    {
    case UndefinedDispose:
        (void) fprintf(file,"Undefined\n");
        break;
    case NoneDispose:
        (void) fprintf(file,"None\n");
        break;
    case BackgroundDispose:
        (void) fprintf(file,"Background\n");
        break;
    case PreviousDispose:
        (void) fprintf(file,"Previous\n");
        break;
    default:
        (void) fprintf(file,"\n");
        break;
    }
    if (image->delay != 0)
        (void) fprintf(file,"  Delay: %lu\n",image->delay);
    if (image->iterations != 1)
        (void) fprintf(file,"  Iterations: %lu\n",image->iterations);
    p=image;
    while (p->previous != (Image *) NULL)
        p=p->previous;
    for (count=1; p->next != (Image *) NULL; count++)
        p=p->next;
    if (count > 1)
        (void) fprintf(file,"  Scene: %lu of %lu\n",image->scene,count);
    else if (image->scene != 0)
        (void) fprintf(file,"  Scene: %lu\n",image->scene);
    (void) fprintf(file,"  Compression: %s\n",
                   CompressionTypeToString(image->compression));
    /*
      Display formatted image attributes. This must happen before we access
      any pseudo attributes like EXIF since doing so causes real attributes
      to be created and we would get duplicates in the output.
    */
    attribute=GetImageAttribute(image,(char *) NULL);
    {
        for ( ; attribute != (const ImageAttribute *) NULL; attribute=attribute->next)
        {
            if (LocaleNCompare("EXIF",attribute->key,4) != 0)
            {
                (void) fprintf(file,"  %c", toupper((int)attribute->key[0]));
                if (strlen(attribute->key) > 1)
                    (void) fprintf(file,"%.1024s",attribute->key+1);

                (void) fprintf(file,": ");
                (void) fprintf(file,"%s\n",attribute->value);
            }
        }
    }
    if((profile=GetImageProfile(image,"ICM",&profile_length)) != 0)
        (void) fprintf(file,"  Profile-color: %lu bytes\n",(unsigned long)
                       profile_length);
    if((profile=GetImageProfile(image,"IPTC",&profile_length)) != 0)
    {
        char
        *tag,
        *text;

        size_t
        length;

        /*
          Describe IPTC data.
        */
        (void) fprintf(file,"  Profile-iptc: %lu bytes\n",(unsigned long)
                       profile_length);
        for (i=0; i < (long) profile_length; )
        {
            if (profile[i] != 0x1c)
            {
                i++;
                continue;
            }
            i++;  /* skip file separator */
            i++;  /* skip record number */
            switch (profile[i])
            {
            case 5:
                tag=(char *) "Image Name";
                break;
            case 7:
                tag=(char *) "Edit Status";
                break;
            case 10:
                tag=(char *) "Priority";
                break;
            case 15:
                tag=(char *) "Category";
                break;
            case 20:
                tag=(char *) "Supplemental Category";
                break;
            case 22:
                tag=(char *) "Fixture Identifier";
                break;
            case 25:
                tag=(char *) "Keyword";
                break;
            case 30:
                tag=(char *) "Release Date";
                break;
            case 35:
                tag=(char *) "Release Time";
                break;
            case 40:
                tag=(char *) "Special Instructions";
                break;
            case 45:
                tag=(char *) "Reference Service";
                break;
            case 47:
                tag=(char *) "Reference Date";
                break;
            case 50:
                tag=(char *) "Reference Number";
                break;
            case 55:
                tag=(char *) "Created Date";
                break;
            case 60:
                tag=(char *) "Created Time";
                break;
            case 65:
                tag=(char *) "Originating Program";
                break;
            case 70:
                tag=(char *) "Program Version";
                break;
            case 75:
                tag=(char *) "Object Cycle";
                break;
            case 80:
                tag=(char *) "Byline";
                break;
            case 85:
                tag=(char *) "Byline Title";
                break;
            case 90:
                tag=(char *) "City";
                break;
            case 95:
                tag=(char *) "Province State";
                break;
            case 100:
                tag=(char *) "Country Code";
                break;
            case 101:
                tag=(char *) "Country";
                break;
            case 103:
                tag=(char *) "Original Transmission Reference";
                break;
            case 105:
                tag=(char *) "Headline";
                break;
            case 110:
                tag=(char *) "Credit";
                break;
            case 115:
                tag=(char *) "Source";
                break;
            case 116:
                tag=(char *) "Copyright String";
                break;
            case 120:
                tag=(char *) "Caption";
                break;
            case 121:
                tag=(char *) "Local Caption";
                break;
            case 122:
                tag=(char *) "Caption Writer";
                break;
            case 200:
                tag=(char *) "Custom Field 1";
                break;
            case 201:
                tag=(char *) "Custom Field 2";
                break;
            case 202:
                tag=(char *) "Custom Field 3";
                break;
            case 203:
                tag=(char *) "Custom Field 4";
                break;
            case 204:
                tag=(char *) "Custom Field 5";
                break;
            case 205:
                tag=(char *) "Custom Field 6";
                break;
            case 206:
                tag=(char *) "Custom Field 7";
                break;
            case 207:
                tag=(char *) "Custom Field 8";
                break;
            case 208:
                tag=(char *) "Custom Field 9";
                break;
            case 209:
                tag=(char *) "Custom Field 10";
                break;
            case 210:
                tag=(char *) "Custom Field 11";
                break;
            case 211:
                tag=(char *) "Custom Field 12";
                break;
            case 212:
                tag=(char *) "Custom Field 13";
                break;
            case 213:
                tag=(char *) "Custom Field 14";
                break;
            case 214:
                tag=(char *) "Custom Field 15";
                break;
            case 215:
                tag=(char *) "Custom Field 16";
                break;
            case 216:
                tag=(char *) "Custom Field 17";
                break;
            case 217:
                tag=(char *) "Custom Field 18";
                break;
            case 218:
                tag=(char *) "Custom Field 19";
                break;
            case 219:
                tag=(char *) "Custom Field 20";
                break;
            default:
                tag=(char *) "unknown";
                break;
            }
            i++;
            (void) fprintf(file,"    %.1024s:\n",tag);
            length=profile[i++] << 8;
            length|=profile[i++];
            text=MagickAllocateMemory(char *,length+1);
            if (text != (char *) NULL)
            {
                char
                **textlist;

                register long
                j;

                (void) strncpy(text,(char *) profile+i,length);
                text[length]='\0';
                textlist=StringToList(text);
                if (textlist != (char **) NULL)
                {
                    for (j=0; textlist[j] != (char *) NULL; j++)
                    {
                        (void) fprintf(file,"  %s\n",textlist[j]);
                        MagickFreeMemory(textlist[j]);
                    }
                    MagickFreeMemory(textlist);
                }
                MagickFreeMemory(text);
            }
            i+=length;
        }
    }