Сохранение выходных данных ASCII в переменной

#c #image-processing #character

Вопрос:

Этот код C преобразует BMP-изображение в формат ASCII. Результат отображается в терминале.

Однако я хочу изменить программу и сохранить выведенные символы в строковой переменной. Проблема в том, img что выводимые символы являются указателем на изображение.

 #define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

char * scale = "8Xoi?;`. "; 
int numScale;

typedef struct
{
    size_t width;
    size_t height;
    unsigned char * data;
} image;


unsigned char luminanceFromRGB(unsigned char r, unsigned char g, unsigned char b)
{
  return (unsigned char) (0.2126 * r   0.7152 * g   0.0722 * b);
}

//Loads image and saves it to img as an image pointer.
long loadImage(image ** img, char * location)
{
  FILE *f = fopen(location, "rb");

  if (f == NULL)
  {
    puts("Opening failed...");
    return 0;
  }

  unsigned char * resu<
  fseek(f, 0, SEEK_END);
  long size = ftell(f);


  fseek(f, 0, SEEK_SET);
  result = (unsigned char *) malloc((size_t) size);

  if (size != fread(result, sizeof(unsigned char), (size_t) size, f))
  {
    free(result);
    puts("Reading failed...");
    fclose(f);
    return 0;
  }

  fclose (f);

  if (size < 54)
  {
    free(result);
    puts("Invalid file...");
    return 0;
  }



  size_t pdOffset = result[10] | result[11] << 8 | result[12] << 16   | result[13] << 24;

  unsigned long width = result[18] | result[19] << 8 | result[20] << 16   | result[21] << 24;
  unsigned long height = result[22] | result[23] << 8 | result[24] << 16 | result[25] << 24;

  unsigned long bpp = result[28] | result[29] << 8;
  int noCompression = result[30] == 0 amp;amp; result[31] == 0 amp;amp; result[32] == 0   amp;amp; result[33] == 0;

  if (bpp != 24 || !noCompression || width < 1 || height < 1 || width > 64000 || height > 64000)
  {
    free(result);
    puts("Unsupported BMP format, only 24 bits per pixel are supported...");
    return 0;
  }
 
  int bytesPerPixel = (int) (bpp / 8);

  size_t rowBytes = (width * bytesPerPixel   3) / 4 * 4;

  printf("Bytes per row: %zun", rowBytes);

  size_t usedRowBytes = width * bytesPerPixel;
  size_t imageBytes = rowBytes * height;

  *img = malloc(sizeof(image));
  (*img)->height = height;
  (*img)->width = width;

  size_t imgSize = width * height;

  (*img)->data = (unsigned char *) malloc(imgSize);

  printf("Offset: %zun", pdOffset);

  unsigned char * ptr = (*img)->data;
  unsigned char * srcPtr = amp;result[pdOffset];

  for (size_t i = 0; i < imgSize;   i)
  {
    unsigned char r = *srcPtr;
    unsigned char g = *(srcPtr   1);
    unsigned char b = *(srcPtr   2);

    *ptr = luminanceFromRGB(r, g, b);
    ptr  ;
    srcPtr  = bytesPerPixel;

    if (i % width == 0)
    {
      srcPtr  = rowBytes - usedRowBytes;
    }
  }

  free(result);
  
  return size;
}


//Assigns a ASCII character (scale) depending on the images brightness
void printchar(image * img)
{
  for (size_t y = img->height - 1; y > 0; --y)
  {
    for (size_t x = 0; x < img->width;   x)
    {
      unsigned char c = *(img->data   x   img->width * y);
      int rescaled = c * numScale / 256;
      putchar(scale[numScale - rescaled]);
    }
    
    putchar('n');
  }
}



void release(image * img)
{
  if (img)
  {
    if (img->data)
      free(img->data);

    free(img);
  }
}



int main(int argc, char ** argv)
{
  if (argc != 2)
  {
    puts("Argument needed: filename.");
    return 1;
  }

  puts(argv[1]);

  setbuf(stdout, 0);

  numScale = strlen(scale) - 1;
  printf("ASCII Brightness Scale: %dn", numScale);

  image *img = NULL;

  if (loadImage(amp;img, argv[1]))
  {
    printf("Image dimensions: %zux%zun", img->width, img->height);

    //Prints ASCII characters in terminal
    printchar(img);

    release(img);
  }

return 0;
}
 

Комментарии:

1. Изображение bmp-это просто заголовок, за которым следуют значения RGB. Здесь нет никакой строки. Просто прочитайте значения изображения в a uint8_t rgb[3] — это ваши значения пикселей. Затем вы можете обрабатывать их по своему усмотрению.

2. ЭМАРО, в чем вопрос? Почтовый индекс здесь .

3. Мои извинения, программа выводит символы ASCII с помощью img, который является указателем на изображение. Однако я хочу сохранить выведенные символы в качестве строковой переменной.

Ответ №1:

Измените main() на

 //printchar(img);
char buf[1000000]; // 1M should be enough
sprintchar(buf, img);
printf("%s", buf); // or whatever
 

и измените/скопируйте printchar() на

 void sprintchar(char *dst, image *img) {
    for (size_t y = img->height - 1; y > 0; --y) {
        for (size_t x = 0; x < img->width;   x) {
            unsigned char c = *(img->data   x   img->width * y);
            int rescaled = c * numScale / 256;
            *dst   = scale[numScale - rescaled];
        }
        *dst   = 'n';
    }
    *dst = 0;
}
 

Комментарии:

1. Абсолютно идеально, большое спасибо!

2. Вместо 1000000 использования img->height * (img->width 1) 1 , возможно, с malloc()