#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()