⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bitmap.c

📁 关于rcp2c_v3.rar协议在LINUX下的实现程序
💻 C
📖 第 1 页 / 共 5 页
字号:
    // try and get the width and height
    result[0] = sscanf((const char *)data + i,
                       "#define %79s %d", name_and_type, &value);
    if (result[0] == 2)
    {

      type = strrchr(name_and_type, '_');
      type = (type == NULL) ? name_and_type : type + 1;
      if (strcmp(type, "width") == 0)
        rcbmp->cx = value;
      else if (strcmp(type, "height") == 0)
        rcbmp->cy = value;
    }
    // look for the data token (is there data)?
    result[0] = sscanf((const char *)data + i,
                       "static unsigned char %s = {", name_and_type);
    result[1] = sscanf((const char *)data + i,
                       "static char %s = {", name_and_type);
    if (result[0] || result[1])
    {

      type = strrchr(name_and_type, '_');
      type = (type == NULL) ? name_and_type : type + 1;
      if (strcmp(type, "bits[]") == 0 && rcbmp->cx > 0 && rcbmp->cy > 0)
      {
        rcbmp->cbRow = ((rcbmp->cx + 15) & ~15) / 8;
        rcbmp->cbDst = rcbmp->cbRow * rcbmp->cy;
        rcbmp->pbBits = malloc(rcbmp->cbDst);

        break;                                   // get out of the loop
      }
    }
  }

  if (rcbmp->pbBits == NULL)
    ErrorLine("Invalid X11 bitmap");

  // read the X11 bitmap data
  memset(rcbmp->pbBits, 0, rcbmp->cbDst);
  value = 0;
  pos = 0;
  for (i = BMP_SkipNewLine(data, size, i); i < size; i++)
  {

    PILRC_BYTE c = tolower(data[i]);

    // termination of a byte?
    if ((c == ',') || (c == '}'))
    {
      if (pos < rcbmp->cbDst)
      {
        rcbmp->pbBits[pos++] = (unsigned char)value;
        if (((rcbmp->cx % 16) > 0) && ((rcbmp->cx % 16) < 9) &&
            ((pos % rcbmp->cbRow) == (rcbmp->cbRow - 1)))
          pos++;
      }
      value = 0;
    }
    else
      // numerical data? - process accordingly (hexagonal)
    if ((c >= '0') && (c <= '9'))
      value = (value >> 4) + (rev[c - '0'] << 4);
    else if ((c >= 'a') && (c <= 'f'))
      value = (value >> 4) + (rev[c - 'a' + 10] << 4);
  }
}

struct rgb
{
  int r, g, b;
};

struct foreign_reader
{
  void (*start_row) (struct foreign_reader * self,
                     int y);
  void (*read_pixel) (struct foreign_reader * self,
                      struct rgb * color);
  int maxval;
  PILRC_BYTE *pb, *pblim;
  void *userdata;
};

static void
default_start_row(struct foreign_reader *self,
                  int y)
{
}

static void
WriteGreyTbmp(RCBITMAP * rcbmp,
              struct foreign_reader *reader)
{
  BOOL warnColorLost = fFalse;
  int depth = rcbmp->pixelsize;
  unsigned long outmaxval = (1UL << depth) - 1;
  unsigned char *outp = rcbmp->pbBits;
  int *index = malloc((reader->maxval + 1) * sizeof(int));
  int i, x, y, ningreys;

  for (i = 0; i <= reader->maxval; i++)
    index[i] = -1;

  for (y = 0; y < rcbmp->cy; y++)
  {
    unsigned int outword = 0;
    int outlen = 0;

    reader->start_row(reader, y);

    for (x = 0; x < rcbmp->cx; x++)
    {
      struct rgb c;
      unsigned long grey;

      reader->read_pixel(reader, &c);
      if (c.r == c.g && c.g == c.b)
        grey = c.r;
      else
      {
        warnColorLost = fTrue;
        /*
         * From the colorspace-FAQ.  There's _some_ chance I'm
         * applying the right formula.  It's been a long time
         * since graphics class...  
         */
        grey = (299L * c.r + 587L * c.g + 114L * c.b) / 1000L;
      }

      if ((int)grey > reader->maxval)
        grey = reader->maxval;

      if (index[grey] == -1)
      {
        unsigned long outgrey;

        outgrey = (grey * outmaxval + reader->maxval / 2) / reader->maxval;
        index[grey] = (outgrey <= outmaxval) ? outmaxval - outgrey : 0;
      }

      outword <<= depth;
      outword |= index[grey];
      outlen += depth;
      if (outlen >= 16)
      {
        *outp++ = outword >> 8;
        *outp++ = outword & 0xff;
        outword = 0;
        outlen = 0;
      }
    }

    if (outlen > 0)
    {
      outword <<= 16 - outlen;
      *outp++ = outword >> 8;
      *outp++ = outword & 0xff;
    }
  }

  if (warnColorLost)
    WarningLine("Some colors saturated in index converted to grey");

  ningreys = 0;
  for (i = 0; i <= reader->maxval; i++)
    if (index[i] != -1)
      ningreys++;

  free(index);

  if (ningreys > (int)outmaxval + 1)
  {
    char buffer[120];

    sprintf(buffer, "%d input grey levels converted to only %ld",
            ningreys, outmaxval + 1);
    WarningLine(buffer);
  }
}

static int
WriteIndexedColorTbmp(RCBITMAP * rcbmp,
                      struct foreign_reader *reader,
                      struct rgb *colortable)
{
#define N 937
  struct hash_entry
  {
    struct rgb key;
    unsigned char index;
  }
  table[N];

  unsigned char *outp = rcbmp->pbBits;
  int x, y, h, nentries, ninputcolors, noutputcolors;

  nentries = 0;
  for (h = 0; h < N; h++)
    table[h].key.r = -1;

  ninputcolors = 0;

  for (y = 0; y < rcbmp->cy; y++)
  {
    reader->start_row(reader, y);

    for (x = 0; x < rcbmp->cx; x++)
    {
      struct rgb c;
      unsigned char index;

      reader->read_pixel(reader, &c);

      /*
       * This hash function has no basis in theory...  
       */
      for (h = (((c.r + 37) ^ (c.g << 2)) + c.b) % N;; h = (h + 1) % N)
        if (table[h].key.r == -1)
        {
          struct rgb cs;

          cs.r = (c.r * 255UL) / reader->maxval;
          cs.g = (c.g * 255UL) / reader->maxval;
          cs.b = (c.b * 255UL) / reader->maxval;

          if (colortable)
          {
            if (ninputcolors < 256)
            {
              colortable[ninputcolors] = cs;
              index = ninputcolors;
            }
            else
              index = 0;                         /* FIXME!!!! */
          }
          else
            index = BMP_RGBToColorIndex(cs.r, cs.g, cs.b,
                                        PalmPalette8bpp, 256);

          ninputcolors++;

          /*
           * Only add the new color if the table isn't already
           * over full. This'll slow down for input images with
           * lots of distinct colors, but it won't be infinitely 
           * slow as it would be if we let the table get
           * completely full.  
           */
          if (nentries < N / 2)
          {
            nentries++;
            table[h].key.r = c.r;
            table[h].key.g = c.g;
            table[h].key.b = c.b;
            table[h].index = index;
          }
          break;
        }
        else if (table[h].key.r == c.r && table[h].key.g == c.g
                 && table[h].key.b == c.b)
        {
          index = table[h].index;
          break;
        }

      *outp++ = index;
    }

    if (rcbmp->cbRow > rcbmp->cx)
      *outp++ = 0;
  }

  noutputcolors = (colortable) ? ninputcolors : 0;

  if (ninputcolors > 256)
  {
    char buffer[120];

    sprintf(buffer, "%d input colors converted to only 256", ninputcolors);
    WarningLine(buffer);
    ninputcolors = 256;
  }

  return ninputcolors;
}

/**
 * Write the body of a Palm Computing bitmap resource data (family member).
 *
 * @param rcbmp      a reference to the Palm Computing resource data.
 * @param width      width of the bitmap
 * @param height     height of the bitmap
 * @param bitmaptype the type of bitmap (B+W, Grey, Grey16 or Color)?
 * @param colortable does a color table need to be generated?
 * @param reader     callbacks and state variables to read the input file
 */
static void
WriteTbmp(RCBITMAP * rcbmp,
          int width,
          int height,
          int bitmaptype,
          BOOL colortable,
          struct foreign_reader *reader)
{
  int depth = 0;

  switch (bitmaptype)
  {
    case rwBitmap:
      depth = 1;
      break;

    case rwBitmapGrey:
      depth = 2;
      break;

    case rwBitmapGrey16:
      depth = 4;
      break;

    case rwBitmapColor256:
      depth = 8;
      break;

    case rwBitmapColor16k:
    case rwBitmapColor24k:
    case rwBitmapColor32k:

      // 
      // UNSUPPORTED RIGHT NOW
      // 

      break;

    default:
      Assert(fFalse);
      break;
  }

  rcbmp->cx = width;
  rcbmp->cy = height;
  rcbmp->pixelsize = depth;
  rcbmp->cbRow = ((width * depth + 15) & ~15) >> 3;
  rcbmp->cbDst = rcbmp->cbRow * height;
  rcbmp->pbBits = malloc(rcbmp->cbDst);
  rcbmp->version = (depth >= 8) ? 2 : 1;

  /*
   * The iterate-over-the-pixels code of these two ought to be unified
   * into one function, but because the color conversions inside the
   * loops are so different, it seems easier to duplicate the loops.  
   */

  if (rcbmp->pixelsize < 8)
    WriteGreyTbmp(rcbmp, reader);
  else
  {
    if (colortable)
    {
      struct rgb table[256];
      int nentries = WriteIndexedColorTbmp(rcbmp, reader, table);

      /*
       * Now bolt the color table onto the front of the output bits. 
       */

      unsigned char *newBits = malloc(2 + 4 * nentries + rcbmp->cbDst);

      if (newBits)
      {
        unsigned char *bits = newBits;
        int i;

        *bits++ = (nentries & 0xff00) >> 8;
        *bits++ = nentries & 0x00ff;

        for (i = 0; i < nentries; i++)
        {
          *bits++ = i;
          *bits++ = table[i].r;
          *bits++ = table[i].g;
          *bits++ = table[i].b;
        }

        memcpy(bits, rcbmp->pbBits, rcbmp->cbDst);
        free(rcbmp->pbBits);

        // rcbmp->ff |= 0x4000;
        rcbmp->flags.hasColorTable = fTrue;

        rcbmp->pbBits = newBits;
        rcbmp->cbDst += 2 + 4 * nentries;
      }
    }
    else
      (void)WriteIndexedColorTbmp(rcbmp, reader, NULL);
  }
}

static void
SkipPNMWhitespace(struct foreign_reader *r)
{
  while (r->pb < r->pblim)
    if (isspace(*r->pb))
      r->pb++;
    else if (*r->pb == '#')
      while (r->pb < r->pblim && *r->pb != '\n' && *r->pb != '\r')
        r->pb++;
    else
      break;
}

static int
ReadPNMInt(struct foreign_reader *r)
{
  int n = 0;

  SkipPNMWhitespace(r);
  for (; r->pb < r->pblim && isdigit(*r->pb); r->pb++)
    n = 10 * n + *r->pb - '0';

  return n;
}

/*
 * A lot of these depend on PILRC_BYTE being unsigned.  Further, if we run
 * out of input (i.e., pb >= pblim) these won't infinite loop or anything,
 * but they probably will return random colors.  But running out of input
 * indicates that the input is corrupted, so this doesn't really matter.  
 */

static void
ReadP1(struct foreign_reader *r,
       struct rgb *c)
{
  SkipPNMWhitespace(r);
  while (r->pb < r->pblim)
    switch (*r->pb++)
    {
      case '0':
        /*
         * Yes, PBM color levels really are reversed compared to PGMs! 
         */
        c->r = c->g = c->b = 1;
        return;

      case '1':
        c->r = c->g = c->b = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -