Ir ao conteúdo

C como compilar um C com libmbp.h e imghelpers.h


Ir à solução Resolvido por arfneto,

Posts recomendados

Postado

A biblioteca não é o tal .h. 

 

O header só tem as definições. Ou você tem a fonte para compilar a biblioteca, ou tem um arquivo .o dela compilada, ou tem uma DLL com o código ou um arquivo .a ou .so ou .lib dependendo de sua plataforma.

 

Não poste links. poste o código aqui.

 

Se tem um arquivo lib é so acrescentar na linha de comando, tipo gcc -o programa x.c coisa.lib

 

 

 

  • Obrigado 1
Postado

@arfneto claro amigo eu posto o codigo sim, mais e meio grande.


main.c
<code>

 

#include <dirent.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include "libbmp.h"

#include "imghelpers.h"

 

#define MYERR(...) do { \

    printf ("ERROR @ %s %s (%d): ", __FILE__,__func__,__LINE__); \

    printf (__VA_ARGS__); \

} while (0)

 

int main() {

  DIR *dp;

  struct dirent *ep;

  char filename[300];

  int firstFile = 0;                

  const char directory[] = "uploads/";

  dp = opendir(directory);

  if (dp != NULL) {

    while ((ep = readdir(dp))) {

      if (ep->d_type == DT_REG && !firstFile) {

        snprintf(filename, sizeof(filename), "%s%s", directory, ep->d_name);

        firstFile = 1;

        printf("sucesso arquivo encontrado");

      }

    }

    (void)closedir(dp);

  } else {

    perror("Não foi possível abrir o diretório 'uploads'");

    return 1;

  }

 

  printf("\n");

  printf("%s",filename);

  IMG_TAM t = pegarTamanho(filename);

  int l = t.qtdLinhas, c = t.qtdColunas;

  int R[l][c];

  int G[l][c];

  int B[l][c];

  carregaImagem(t, R, G, B, filename);

  for (int i = 0; i < l; i++) {

    for (int j = 0; j < c; j++) {

      R[i][j] = G[i][j];

      B[i][j] = R[i][j];

      G[i][j] = B[i][j];

    }

   printf("%d",i);

  }

  salvaImagem(t, R, G, B, filename);

  mostrarNoReplit(filename);

  printf("img editada");

  return 0;

}

<code>
agora eu possu duas pasta de codigo diferente uma .h e outra .c 

libbmp.h e libbmp.c
<code>

#ifndef __LIBBMP_H__

#define __LIBBMP_H__

 

#include <stdio.h>

 

#define BMP_MAGIC 19778

 

#define BMP_GET_PADDING(a) ((a) % 4)

 

enum bmp_error {

  BMP_FILE_NOT_OPENED = -4,

  BMP_HEADER_NOT_INITIALIZED,

  BMP_INVALID_FILE,

  BMP_ERROR,

  BMP_OK = 0

};

 

typedef struct _bmp_header {

  unsigned int bfSize;

  unsigned int bfReserved;

  unsigned int bfOffBits;

 

  unsigned int biSize;

  int biWidth;

  int biHeight;

  unsigned short biPlanes;

  unsigned short biBitCount;

  unsigned int biCompression;

  unsigned int biSizeImage;

  int biXPelsPerMeter;

  int biYPelsPerMeter;

  unsigned int biClrUsed;

  unsigned int biClrImportant;

} bmp_header;

 

typedef struct _bmp_pixel {

  unsigned char blue;

  unsigned char green;

  unsigned char red;

} bmp_pixel;

 

#define BMP_PIXEL(r, g, b) ((bmp_pixel){(b), (g), (r)})

 

typedef struct _bmp_img {

  bmp_header img_header;

  bmp_pixel **img_pixels;

} bmp_img;

 

void bmp_header_init_df(bmp_header *, const int, const int);

enum bmp_error bmp_header_write(const bmp_header *, FILE *);

enum bmp_error bmp_header_read(bmp_header *, FILE *);

void bmp_pixel_init(bmp_pixel *, const unsigned char, const unsigned char, const unsigned char);

void bmp_img_alloc(bmp_img *);

void bmp_img_init_df(bmp_img *, const int, const int);

void bmp_img_free(bmp_img *);

enum bmp_error bmp_img_write(const bmp_img *, const char *);

enum bmp_error bmp_img_read(bmp_img *, const char *);

 

#endif /* __LIBBMP_H__ */

<code>
//fim----------------
<code>

#include <stdio.h>

#include <stdlib.h>

#include "libbmp.h"

 

void bmp_header_init_df(bmp_header *header, const int width, const int height) {

  header->bfSize =

      (sizeof(bmp_pixel) * width + BMP_GET_PADDING(width)) * abs(height);

  header->bfReserved = 0;

  header->bfOffBits = 54;

  header->biSize = 40;

  header->biWidth = width;

  header->biHeight = height;

  header->biPlanes = 1;

  header->biBitCount = 24;

  header->biCompression = 0;

  header->biSizeImage = 0;

  header->biXPelsPerMeter = 0;

  header->biYPelsPerMeter = 0;

  header->biClrUsed = 0;

  header->biClrImportant = 0;

}

 

enum bmp_error bmp_header_write(const bmp_header *header, FILE *img_file) {

  if (header == NULL) {

    return BMP_HEADER_NOT_INITIALIZED;

  } else if (img_file == NULL) {

    return BMP_FILE_NOT_OPENED;

  }

 

  const unsigned short magic = BMP_MAGIC;

  fwrite(&magic, sizeof(magic), 1, img_file);

  fwrite(header, sizeof(bmp_header), 1, img_file);

  return BMP_OK;

}

 

enum bmp_error bmp_header_read(bmp_header *header, FILE *img_file) {

  if (img_file == NULL) {

    return BMP_FILE_NOT_OPENED;

  }

 

  unsigned short magic;

 

  if (fread(&magic, sizeof(magic), 1, img_file) != 1 || magic != BMP_MAGIC) {

    return BMP_INVALID_FILE;

  }

 

  if (fread(header, sizeof(bmp_header), 1, img_file) != 1) {

    return BMP_ERROR;

  }

 

  return BMP_OK;

}

 

void bmp_pixel_init(bmp_pixel *pxl, const unsigned char red,

                    const unsigned char green, const unsigned char blue) {

  pxl->red = red;

  pxl->green = green;

  pxl->blue = blue;

}

 

void bmp_img_alloc(bmp_img *img) {

  const size_t h = abs(img->img_header.biHeight);

 

  img->img_pixels = malloc(sizeof(bmp_pixel *) * h);

 

  for (size_t y = 0; y < h; y++) {

    img->img_pixels[y] = malloc(sizeof(bmp_pixel) * img->img_header.biWidth);

  }

}

 

void bmp_img_init_df(bmp_img *img, const int width, const int height) {

  bmp_header_init_df(&img->img_header, width, height);

  bmp_img_alloc(img);

}

 

void bmp_img_free(bmp_img *img) {

  const size_t h = abs(img->img_header.biHeight);

 

  for (size_t y = 0; y < h; y++) {

    free(img->img_pixels[y]);

  }

  free(img->img_pixels);

}

 

enum bmp_error bmp_img_write(const bmp_img *img, const char *filename) {

  FILE *img_file = fopen(filename, "wb");

 

  if (img_file == NULL) {

    return BMP_FILE_NOT_OPENED;

  }

 

  const enum bmp_error err = bmp_header_write(&img->img_header, img_file);

 

  if (err != BMP_OK) {

    fclose(img_file);

    return err;

  }

 

  const size_t h = abs(img->img_header.biHeight);

  const size_t offset = (img->img_header.biHeight > 0 ? h - 1 : 0);

  const unsigned char padding[3] = {'\0', '\0', '\0'};

 

  for (size_t y = 0; y < h; y++) {

    fwrite(img->img_pixels[offset - y], sizeof(bmp_pixel),

           img->img_header.biWidth, img_file);

    fwrite(padding, sizeof(unsigned char),

           BMP_GET_PADDING(img->img_header.biWidth), img_file);

  }

 

  fclose(img_file);

  return BMP_OK;

}

 

enum bmp_error bmp_img_read(bmp_img *img, const char *filename) {

  FILE *img_file = fopen(filename, "rb");

 

  if (img_file == NULL) {

    return BMP_FILE_NOT_OPENED;

  }

 

  const enum bmp_error err = bmp_header_read(&img->img_header, img_file);

 

  if (err != BMP_OK) {

    fclose(img_file);

    return err;

  }

 

  bmp_img_alloc(img);

 

  const size_t h = abs(img->img_header.biHeight);

  const size_t offset = (img->img_header.biHeight > 0 ? h - 1 : 0);

  const size_t padding = BMP_GET_PADDING(img->img_header.biWidth);

  const size_t items = img->img_header.biWidth;

 

  for (size_t y = 0; y < h; y++) {

    if (fread(img->img_pixels[offset - y], sizeof(bmp_pixel), items,

              img_file) != items) {

      fclose(img_file);

      return BMP_ERROR;

    }

 

    fseek(img_file, padding, SEEK_CUR);

  }

 

  fclose(img_file);

  return BMP_OK;

}

<code>

agora a mesma coisa com o imghelpers.h e .c
<code>
 

#ifndef IMGPHELPERS_H

#define IMGPHELPERS_H

 

#include <stdio.h>

 

struct IMG_TAM {

    int qtdLinhas;

    int qtdColunas;

};

typedef struct IMG_TAM IMG_TAM;

 

IMG_TAM pegarTamanho(const char *filename);

 

void carregaImagem(

  IMG_TAM t,

  int R[t.qtdLinhas][t.qtdColunas],

  int G[t.qtdLinhas][t.qtdColunas],

  int B[t.qtdLinhas][t.qtdColunas],

  const char *filename);

 

void salvaImagem(IMG_TAM t,

  int R[t.qtdLinhas][t.qtdColunas],

  int G[t.qtdLinhas][t.qtdColunas],

  int B[t.qtdLinhas][t.qtdColunas],

  const char *filename);

 

void zerarPixels(IMG_TAM t,

  unsigned char PIX[t.qtdLinhas][t.qtdColunas]);

 

void mostrarNoReplit(const char *filename);

 

#endif

 


<code>
//fim -----------
<code>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include "libbmp.h"

#include "imghelpers.h"



 

int limit(int x) {

    if (x > 255)

        return 255;

    else if (x < 0)

        return 0;

    else

        return x;

}

 

IMG_TAM pegarTamanho(const char *filename) {

    FILE *f = fopen(filename, "rb");

    if (f == NULL) {

        printf("arquivo %s não existe!\n", filename);

        exit(1);

    }

    fclose(f);

 

    IMG_TAM t;

    bmp_img img;

    bmp_img_read(&img, filename);

    t.qtdColunas = img.img_header.biWidth;

    t.qtdLinhas = img.img_header.biHeight;

    bmp_img_free(&img);

    return t;

}

 

void carregaImagem(

    IMG_TAM t,

    int R[t.qtdLinhas][t.qtdColunas],

    int G[t.qtdLinhas][t.qtdColunas],

    int B[t.qtdLinhas][t.qtdColunas],

    const char *filename) {

    bmp_img img;

    bmp_img_read(&img, filename);

 

    int width = t.qtdColunas;

    int height = t.qtdLinhas;

 

    for (int y = 0; y < height; y++) {

        for (int x = 0; x < width; x++) {

            R[y][x] = img.img_pixels[y][x].red;

            G[y][x] = img.img_pixels[y][x].green;

            B[y][x] = img.img_pixels[y][x].blue;

        }

    }

    printf("- - Imagem %s carregada com %dx%d px - -\n", filename, width, height);

}

 

void salvaImagem(

    IMG_TAM t,

    int R[t.qtdLinhas][t.qtdColunas],

    int G[t.qtdLinhas][t.qtdColunas],

    int B[t.qtdLinhas][t.qtdColunas],

    const char *filename) {

    bmp_img img;

    int width = t.qtdColunas;

    int height = t.qtdLinhas;

    bmp_img_init_df(&img, width, height);

 

    for (int y = 0; y < height; y++) {

        for (int x = 0; x < width; x++) {

            bmp_pixel_init(&img.img_pixels[y][x], limit(R[y][x]), limit(G[y][x]), limit(B[y][x]));

        }

    }

    bmp_img_write(&img, filename);

    bmp_img_free(&img);

    printf("- - Imagem salva no caminho %s - -\n", filename);

}

 

void zerarPixels(

    IMG_TAM t,

    unsigned char PIX[t.qtdLinhas][t.qtdColunas]) {

    for (int y = 0; y < t.qtdColunas; y++) {

        for (int x = 0; x < t.qtdLinhas; x++) {

            PIX[x][y] = 0;

        }

    }

}

 

void mostrarNoReplit(const char *filename) {

    int buffsize = 256;

    char buf[buffsize];

    char fehString[] = "feh --full-screen --auto-zoom %s > /dev/null 2>&1";

    int filename_length = strlen(filename);

    int fehString_length = strlen(fehString);

    if (filename_length + fehString_length > buffsize) {

       

        return;

    }

    printf("Exibindo imagem: %s", filename);

    fflush(stdout);

    snprintf(buf, sizeof buf, fehString, filename);

    system(buf);

}
<code>

o codigo deve pegar a primeira imagem da pasta uploads e editala deixando em preto e branco

o codigo encontra a imagem so que na hora que vai usar a biblioteca o codigo morre n e faz nada

usei o seguinte codigo para compilar 
gcc main.c libbmp.c imghelpers.c -o main.exe

  • Obrigado 1
Postado
3 horas atrás, matheus.Matta disse:

o codigo encontra a imagem so que na hora que vai usar a biblioteca o codigo morre n e faz nada

O erro deve ser por causa do formato da imagem que tem que ser bmp.

  • Obrigado 1
Postado

Use o botão code, como explicado no primeiro post do forum. 

 


#include "imghelpers.h"
 

 

Esse include está errado...

 

#ifndef IMGPHELPERS_H
#define IMGPHELPERS_H

 

Ou isso está errado.

Em C isso não está definido no padrão

 

struct IMG_TAM
{
    int qtdLinhas;
    int qtdColunas;
};
typedef struct IMG_TAM IMG_TAM;

IMG_TAM pegarTamanho(const char* filename);

void carregaImagem(
    IMG_TAM t, int R[t.qtdLinhas][t.qtdColunas],
    int G[t.qtdLinhas][t.qtdColunas],
    int B[t.qtdLinhas][t.qtdColunas], const char* filename);

 

Use o simples e passe os endereços. 

 

A dimensão do vetor deve ser conhecida em tempo de compilação. Até tem desde sempre uma extensão, os VLA, que admitem isso. Mas trazem mais problema que solução e em geral só vemos em programas de estudantes.

  • Curtir 1
  • Obrigado 1
Postado

@arfneto não acredito que o erro seja de sintaxe ja que o codigo roda prefeitamente no replit, o problema e quando eu passo o codigo para outro programa tipo vscode 

a libs n fui eu que crie apenas uso para editar as imagens que tem que ser em formato bmp

 

 

  • Curtir 1
Postado
39 minutos atrás, matheus.Matta disse:

não acredito que o erro seja de sintaxe ja que o codigo roda prefeitamente no replit

 

   Isso também não existe na linguagem oficialmente. Como eu disse, o tamanho do vetor deve ser conhecido em tempo de compilação. Existem os VLA mas são tratados como extensão apenas e por alguns compiladores. E nunca é visto em produção, só em programas de estudantes.

 

Em C use endereços. Ou constantes.

 

 int l = t.qtdLinhas, c = t.qtdColunas;
    int R[l][c];
    int G[l][c];
    int B[l][c];


São dezenas de erros como esses: 

 

\imghelpers.h(16,12): error C2057: expected constant expression
\imghelpers.h(16,22): error C2466: cannot allocate an array of constant size 0
\imghelpers.h(16,25): error C2057: expected constant expression
\imghelpers.h(16,36): error C2466: cannot allocate an array of constant size 0
\imghelpers.h(16,36): error C2087: 'R': missing subscript
imghelpers.h(17,12): error C2057: expected constant expression
imghelpers.h(17,22): error C2466: cannot allocate an array of constant size 0

 

1 hora atrás, matheus.Matta disse:

programa tipo vscode

 

VS Code é um IDE. Pode ser usado em vários ambientes e com vários compiladores. Que está usando?

Que sistema? Que compilador? Que versão de C?

  • Curtir 1
Postado

Seu programa rodou corretamente aqui, deixando a imagem em preto e branco.

 

Caso o problema não seja o formato da imagem você podia dar mais informações do erro.

  • Curtir 1
Postado
9 horas atrás, matheus.Matta disse:

não acredito que o erro seja de sintaxe ja que o codigo roda prefeitamente no replit

 

Errado está. Isso não está no padrão. VLA não faz parte da linguagem e o compilador deve ter te dito isso também.

 

Pode ser que tenha dificuldade em compilar por não ter usado a opção que habilita o uso de VLA em seu compilador. 

 

De todo modo acho que podia reescrever essa parte. O código da biblioteca nem está assim muito bom. E tem exemplos aqui nesse forum.

 

 

  • Curtir 1
Postado

@arfneto você conhece alguma biblioteca parecida com essa que funcione ? pelo visto o problema esta sendo ela então e melhor troca-la.
eu criei outro topico com uma explicação melhor se você puder olhar la e me ajuda kkk, você esta sendo minha unica esperança de terminar esse projeto. alias se eu habilitar o uso de VLA funcionaria de alguma forma ?

 

  • Curtir 1
Postado

Achei esse projeto interessante e mudei um pouco a forma de preparar a imagem e converter. Tentei deixar mais simples e com alocação dinâmica para os arrays RGB e talvez tenha algum detalhe tecnicamente, ou do ponto de vista da boa prática de programação, incorreto nessa abordagem, mas para os testes rodou corretamente. Removi o imghelpers.c e o header e coloquei as funções "auxiliares" no mesmo source de main (chamei de imagebmp.c). No libbmp.c e o header não mudei nada.

 

Para quem quiser testar tem que passar o nome da imagem como primeiro argumento e a saída para o segundo:

 

imagebmp.exe input.bmp output.bmp

 

#include <stdio.h>
#include <stdlib.h>
#include "libbmp.h"

typedef struct {
    int width;
    int height;
}Size;

typedef struct {
    int** red;
    int** green;
    int** blue;
}RGB;

void alloc_rgb(RGB* RGB, int height, int width);
void free_rgb(RGB* RGB, int width);
Size* get_size(const char* filename);
int limit(int x);
void load_image(Size* img_size, RGB* RGB, const char* filename);
void save_image(Size* img_size, RGB* RGB, const char* filename);

int main(int argc, char* argv[]) {
    const char* input_filename = argv[1];
    const char* output_filename = argv[2];
    Size*		img_size;
    RGB			RGB;

    if (argc == 3) {
        FILE* file = fopen(input_filename, "r");
        if (file == NULL) {
            fprintf(stderr, "Failed to open file: %s\n", input_filename);
            exit(1);
        }
        fclose(file);
    } else {
        fprintf(stderr, "Error: argc[%d]. Usage: imagebmp.exe input.bmp output.bmp", argc);
        exit(1);
    }

    img_size = get_size(input_filename);
    alloc_rgb(&RGB, img_size->height, img_size->width);
    if (img_size == NULL) {
        fprintf(stderr, "Can't read or open file: %s\n", input_filename);
        exit(1);
    }

    load_image(img_size, &RGB, input_filename);

    for (int y = 0; y < img_size->height; y += 1) {
        for (int x = 0; x < img_size->width; x += 1) {
            RGB.red[y][x] = RGB.green[y][x];
            RGB.green[y][x] = RGB.red[y][x];
            RGB.blue[y][x] = RGB.blue[y][x];
        }
    }
    save_image(img_size, &RGB, output_filename);
    free_rgb(&RGB, img_size->height);
    return 0;
}

void alloc_rgb(RGB* RGB, int height, int width) {
    RGB->red = (int**)malloc(sizeof(int*) * height);
    RGB->green = (int**)malloc(sizeof(int*) * height);
    RGB->blue = (int**)malloc(sizeof(int*) * height);

    for (int i = 0; i < height; i += 1) {
        RGB->red[i] = (int*)malloc(sizeof(int) * width);
        RGB->green[i] = (int*)malloc(sizeof(int) * width);
        RGB->blue[i] = (int*)malloc(sizeof(int) * width);
    }
}

void free_rgb(RGB* RGB, int width) {
    for (int i = 0; i < width; i += 1) {
        free(RGB->red[i]);
        free(RGB->green[i]);
        free(RGB->blue[i]);
    }
    free(RGB->red);
    free(RGB->green);
    free(RGB->blue);
}

Size* get_size(const char* filename) {
    FILE* file = fopen(filename, "rb");
    Size* img_size = NULL;
    bmp_img	image;

    if (file != NULL) {
        img_size = (Size*)malloc(sizeof(Size));
        bmp_img_read(&image, filename);
        img_size->height = image.img_header.biHeight;
        img_size->width = image.img_header.biWidth;
        bmp_img_free(&image);
        fclose(file);
    }
    return img_size;
}

int limit(int x) {
    if (x > 255) {
        return 255;
    } else if (x < 0) {
        return 0;
    }
    return x;
}

void load_image(Size* img_size, RGB* RGB, const char* filename) {
    bmp_img	image;
    bmp_img_read(&image, filename);
    for (int y = 0; y < img_size->height; y += 1) {
        for (int x = 0; x < img_size->width; x += 1) {
            RGB->red[y][x] = image.img_pixels[y][x].red;
            RGB->green[y][x] = image.img_pixels[y][x].green;
            RGB->blue[y][x] = image.img_pixels[y][x].blue;
        }
    }
}

void save_image(Size* img_size, RGB* RGB, const char* filename) {
    bmp_img	image;
    bmp_img_init_df(&image, img_size->width, img_size->height);
	
    for (int y = 0; y < img_size->height; y += 1) {
        for (int x = 0; x < img_size->width; x += 1) {
            bmp_pixel_init(
                &image.img_pixels[y][x],
                limit(RGB->red[y][x]),
                limit(RGB->green[y][x]),
                limit(RGB->blue[y][x])
            );
        }
    }
    bmp_img_write(&image, filename);
    bmp_img_free(&image);
}

 

Obs: Por algum motivo o fórum deixou o nome do parâmetro RGB maiúsculo. Então para testar tem que corrigir isso.

 

  • Amei 1
Postado
15 minutos atrás, Midori disse:
for (int y = 0; y < img_size->height; y += 1) {
        for (int x = 0; x < img_size->width; x += 1) {
            RGB.red[y][x] = RGB.green[y][x];
            RGB.green[y][x] = RGB.red[y][x];
            RGB.blue[y][x] = RGB.blue[y][x];
        }
    }

 

Considere a segunda linha do loop interno... Se red = green então não há propósito em escrever green = red logo a seguir. Já é igual. E blue = blue é a função identidade. f(x) = x para todo x. Ou perdi algo?

 

 

  • Obrigado 1
Postado

@arfneto Cheguei a pensar nisso, mas como acabei não usando o retorno e só foquei em resolver a questão da conversão ficou void mesmo. Considero uma boa prática retornar algo. Por que é mais rápido?

  • Curtir 1
Postado

Porque tem um parâmetro a menos para empilhar e desempilhar e na hora de montar em geral o código é mais simples... menos instruções.

 

28 minutos atrás, Midori disse:
void load_image(Size* img_size, RGB* RGB, const char* filename);

 

Está claro que quer carregar a imagem em um bitmap na memória. 

 

E considerando

 

29 minutos atrás, Midori disse:
typedef struct {
    int width;
    int height;
}Size;

typedef struct {
    int** red;
    int** green;
    int** blue;
}RGB;

 

int** é muito inseguro. Não se expõe essas coisas em uma API. E está claro que falta algo. Considere main que é a mesma coisa

 

	int main(int argc, char**argv);

 

Por alguma razão existe argc....

 

Porque não tem isso em RGB? Porque estão em Size. Não bom. Isso só dá problema. Encapsulamento é sempre vantagem.

 

Entenda: esses valores inclusive já estão encapsulados no bitmap, padrão da Microsoft...

 

typedef struct _bmp_header
{
  unsigned int bfSize;
  unsigned int bfReserved;
  unsigned int bfOffBits; 
  unsigned int biSize;
  int biWidth;
  int biHeight;
  unsigned short biPlanes;
  unsigned short biBitCount;
  unsigned int biCompression;
  unsigned int biSizeImage;
  int biXPelsPerMeter;
  int biYPelsPerMeter;
  unsigned int biClrUsed;
  unsigned int biClrImportant;
} bmp_header;

 

Se vai ler já estão no arquivo. Se vai criar já sabe que alguma forma ou não vai mesmo conseguir criar. Isso quer dizer que não precisa e não deve ter isso.

 

Escreva o simples:

 

	BITMAP* load_image(const char* filename);
	int     save_image(BITMAP*,const char* filename); 

 

E aí pode escrever

 

	const char* um = "um.bmp");
	const char* copia = "copia.bmp");
	BITMAP* bmp = load_image(um);
	int res = save_image( bmp, outro);
	if ( res == 0 ) printf("\"%s\" copiado para \"%s\"\n", um, outro);
	bmp = delete_image(bmp);

 

 por exemplo, para copiar um bitmap

existe argc porque quando declara argv como char** precisa saber o tamanho. E isso falta na sua estrutura RGB. E isso já está lá. Não precisa recriar Size

  • Obrigado 1
Postado
3 horas atrás, arfneto disse:

int** é muito inseguro. Não se expõe essas coisas em uma API.

Essa estutura não era realmente necessaria. Dessa vez so peguei os valores de img_pixels. Para facilitar fiz uma estrutura para armazenar os tamanhos usados nos loops.

 

#include <stdio.h>
#include <stdlib.h>
#include "libbmp.h"

typedef struct{
    bmp_pixel**	img_pixels;
    int width;
    int height;
}WHPixels;

WHPixels* load_image(const char* filename);
int save_image(WHPixels* whpix, const char* filename);
int limit(int x);

int main(int argc, char* argv[]) {
    const char* input_filename = argv[1];
    const char* output_filename = argv[2];
    WHPixels*   whpix;

    if(argc != 3){
        fprintf(stderr,
            "Error: argc[%d]. Usage: imagebmp input.bmp output.bmp\n", argc);
        exit(1);
    }
	
    whpix = load_image(input_filename);
	
    if(whpix == NULL){
        fprintf(stderr, "Can't read or open file: %s\n", input_filename);
        exit(1);
    }

    for(int y = 0; y < whpix->height; y += 1){
        for(int x = 0; x < whpix->width; x += 1){
            unsigned char red = whpix->img_pixels[y][x].red;
            whpix->img_pixels[y][x].red = whpix->img_pixels[y][x].green;
            whpix->img_pixels[y][x].green = red;
        }
    }	

    if(save_image(whpix, output_filename)){
        fprintf(stderr, "Failed to save file: %s\n", output_filename);
        exit(1);
    }

    return 0;
}

WHPixels* load_image(const char* filename){
    FILE*       file = fopen(filename, "rb");
    WHPixels*   whpix = NULL;
    bmp_img     image;
    
    if(file == NULL){
        return NULL;
    }

    whpix = (WHPixels*)malloc(sizeof(WHPixels));
	
    bmp_img_read(&image, filename);
	
    whpix->width = image.img_header.biWidth;
    whpix->height = image.img_header.biHeight;	
    whpix->img_pixels = image.img_pixels;

    fclose(file);
    return whpix;
}

int save_image(WHPixels* whpix, const char* filename){
    bmp_img		image;
    bmp_img_init_df(&image, whpix->width, whpix->height);
	
    for(int y = 0; y < whpix->height; y += 1){
        for(int x = 0; x < whpix->width; x += 1){
            bmp_pixel_init(
                &image.img_pixels[y][x],
                limit(whpix->img_pixels[y][x].red),
                limit(whpix->img_pixels[y][x].green),
                limit(whpix->img_pixels[y][x].blue)
            );
        }
    }
    if(bmp_img_write(&image, filename) != BMP_OK){
        return 1;
    }
    bmp_img_free(&image);
    return 0;
}

int limit(int x){
    if(x > 255){
        return 255;
    }else if (x < 0){
        return 0;
    }
    return x;
}

 

Mas codigo tem um problema. Em vez de ficar preto e branco so troca as cores e deixa uma parte desenquadrada,

 

screen.png.cb8fbfb1b73bdabcca4d32c8ce5e0cec.png

 

 

  • Curtir 1
Postado
38 minutos atrás, Midori disse:

Essa estutura não era realmente necessaria. Dessa vez so peguei os valores de img_pixels. Para facilitar fiz uma estrutura para armazenar os tamanhos usados nos loops.

 

acho que não me expliquei bem: esses valores já fazem parte da estrutura. Não deve replicar isso de novo e de novo

  • Curtir 1
Postado

a discusão aqui esta muito elevada para meu nivel KKKK, MAS Continuem esta me fazendo entender

so estou confuso em uma coisa, no replit site que eu uso para estudo na faculdade esse mesmo codigo funciona sem problemas, vou deixar um Vídeo:

 

EXPLICAÇÃO DO CODIGO: pegar uma imagem da pasta uploads e deixa em preto e branco obivo a img tem que estar em .bmp
em um ambiente tipo esse do replit onde n gera um executavel funciona prefeitamente unico problema e que eu preciso de um executavel para continuar meu projeto onde eu vou criar uma especie de aplicador de filtros. tipo o que o instagram tem 

@Midori isso se ajeita no for onde eu declaro R[i][j] = G[i][j]; o filtro n e tão importante, isso e so um teste para tentar gerar um executavel.

 

  • Curtir 1
Postado
1 hora atrás, matheus.Matta disse:

so estou confuso em uma coisa, no replit site que eu uso para estudo na faculdade esse mesmo codigo funciona sem problemas

 

Você entendeu quando eu disse 2X que isso não existe a menos que tenha habilitado uma extensão da linguagem?  É só uma opção para o compilador. 

 

Em 19/10/2023 às 12:06, matheus.Matta disse:

você conhece alguma biblioteca parecida com essa que funcione ? pelo visto o problema esta sendo ela então e melhor troca-la.
eu criei outro topico com uma explicação melhor se você puder olhar la e me ajuda kkk, você esta sendo minha unica esperança de terminar esse projeto. alias se eu habilitar o uso de VLA funcionaria de alguma forma ?

 

Acho que já disse que eu não usaria isso. Mas deve sim funcionar.

 

Eu também disse que o código não é assim bom (o dessa biblioteca).

 

Eu já postei programas aqui que geram bitmaps em C e C++. Procure no perfil do usuário. Claro, não vou dizer que o que eu escrevi é bom. 😄  

 

1 hora atrás, matheus.Matta disse:

em um ambiente tipo esse do replit onde n gera um executavel funciona prefeitamente unico problema e que eu preciso de um executavel para continuar meu projeto onde eu vou criar uma especie de aplicador de filtros

 

Vai ter esse problema outras vezes com VLA. E pode acabar com uma escola projeto ou emprego que nem aceita falar nisso. Use C, padrão. Mesmo dirent.h é um pesadelo porque oficialmente não existe para Windows. E a solução do Windows não existe para Unix / Linux / Android

 

E acho que não precisa de dirent.h e essa coisa toda só para abrir 1 arquivo. E devia pegar o nome da linha de comando como @Midori mostrou.

 

Quando o cara vai rodar seu programa já sabe o que vai fazer, então é um porre ficar esperando um prompt para digitar o nome e teclar ENTER de novo...

 

1 hora atrás, matheus.Matta disse:

isso se ajeita no for onde eu declaro R[i][j] = G[i][j]; o filtro n e tão importante, isso e so um teste para tentar gerar um executavel.

 

É muito chato usar esses índices todos para um bitmap. Entenda que os pixels vem todos arrumadinhos, um depois do outro. Quantos? Tá escrito lá. Que largura? está escrito lá. Que altura? Está escrito lá.

 

Isso é um bitmap, segundo quem criou: a Microsoft.

 

    typedef struct
    {
        BitmapFileHeader h_bmp;
        BitmapInfoHeader h_info;
        uint8_t*         pixel;
    } Bitmap;

 

E esses são os headers:

 


    typedef struct
    {
        char    header[2];
        int32_t fileSize;
        int32_t reserved;
        int32_t dataOffset;
    } BitmapFileHeader;

    typedef struct
    {
        int32_t headerSize;
        int32_t width;
        int32_t height;
        int16_t planes;
        int16_t bitsPerPixel;
        int32_t compression;
        int32_t dataSize;
        int32_t horizontalResolution;
        int32_t verticalResolution;
        int32_t colors;
        int32_t importantColors;
    } BitmapInfoHeader;

 

Pra que inventar tudo de novo?

 

considerem

 

uint8_t é padrão, não é ideia minha. É um unsigned char*, o popular byte sem sinal

 

  • Curtir 1
Postado

@arfneto agora entendi, parece que me falta conhecimento sobre o assunto. tem algum lugar que eu possa me aprofundar? melhor forma de enteder isso e eu criando a minha propria para manipular e n usar a que o proff disponibilizou.

Na verdade ela foi criada para assinar matrix para os estudantes eu que estava querendo levar a um nivel diferente sem nescessidade, mas quando me vem a ideia n consigo parar ate fazer kkk

  • Curtir 1
Postado

@arfneto @Midori
GRAÇAS A AJUDA DE vocês EU FINALMENTE CONSEGUI, PROCUREI ENTENDER COMO MANIPULAR O BMP, CRIEI MINHA PROPRIA LIB PARA MANIPULAR ( vou deixa o codigo abaixo ) E FUNCIONOU PREFEITAMENTE.

Vídeo do resultado:

#include "myBmp.h"
#include <stdio.h>
#include <stdlib.h>

int main() {
    const char* filename = "lenna.bmp";

    IMG_TAM t = pegarTamanho(filename);
    int l = t.qtdLinhas;
    int c = t.qtdColunas;

    //alocação de imagem
    int** R = (int**)malloc(sizeof(int*) * l);
    int** G = (int**)malloc(sizeof(int*) * l);
    int** B = (int**)malloc(sizeof(int*) * l);
    for (int i = 0; i < l; i++) {
        R[i] = (int*)malloc(sizeof(int) * c);
        G[i] = (int*)malloc(sizeof(int) * c);
        B[i] = (int*)malloc(sizeof(int) * c);
    }

    carregaImagem(filename, R, G, B, c, l);

    for (int i = 0; i < l; i++) {
        for (int j = 0; j < c; j++) {
            // Calcule a média dos componentes de cor R, G e B
            int grayValue = (R[i][j] + G[i][j] + B[i][j]) / 3;
  
            // Atribua o valor médio a cada componente de cor
            R[i][j] = grayValue;
            G[i][j] = grayValue;
            B[i][j] = grayValue;
        }
    }

    salvaImagem("saida.bmp", R, G, B, c, l);

    // liberar o espaço da memória 
    for (int i = 0; i < l; i++) {
        free(R[i]);
        free(G[i]);
        free(B[i]);
    }
    free(R);
    free(G);
    free(B);

    return 0;
}


//myBmp.c-----------------------------------------------
#include "myBmp.h"
#include <stdio.h>
#include <stdlib.h>



// Implementação da função para carregar uma imagem BMP
void carregaImagem(const char* filename, int** R, int** G, int** B, int width, int height) {
    FILE* file = fopen(filename, "rb");

    if (file == NULL) {
        printf("Erro ao abrir o arquivo BMP.\n");
        return;
    }

    BMPFileHeader fileHeader;
    BMPInfoHeader infoHeader;

    fread(&fileHeader, sizeof(BMPFileHeader), 1, file);
    fread(&infoHeader, sizeof(BMPInfoHeader), 1, file);

    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            fread(&B[i][j], 1, 1, file);
            fread(&G[i][j], 1, 1, file);
            fread(&R[i][j], 1, 1, file);
        }
    }

    fclose(file);
}

// Implementação da função para salvar uma imagem BMP
void salvaImagem(const char* filename, int** R, int** G, int** B, int width, int height) {
    FILE* file = fopen(filename, "wb");

    if (file == NULL) {
        printf("Erro ao criar o arquivo BMP de saída.\n");
        return;
    }

    BMPFileHeader fileHeader;
    BMPInfoHeader infoHeader;

    // Preencha os campos de fileHeader e infoHeader com os valores apropriados
    // Certifique-se de que esses valores correspondam às dimensões e ao formato da imagem BMP que você está criando

    fwrite(&fileHeader, sizeof(BMPFileHeader), 1, file);
    fwrite(&infoHeader, sizeof(BMPInfoHeader), 1, file);

    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            fwrite(&B[i][j], 1, 1, file);
            fwrite(&G[i][j], 1, 1, file);
            fwrite(&R[i][j], 1, 1, file);
        }
    }

    fclose(file);
}

IMG_TAM pegarTamanho(const char* filename) {
    FILE* file = fopen(filename, "rb");

    if (file == NULL) {
        printf("Erro ao abrir o arquivo BMP.\n");
        exit(1);
    }

    // Leitura do cabeçalho BMP para obter as dimensões da imagem
    BMPFileHeader fileHeader;
    BMPInfoHeader infoHeader;

    fread(&fileHeader, sizeof(BMPFileHeader), 1, file);
    fread(&infoHeader, sizeof(BMPInfoHeader), 1, file);

    IMG_TAM tamanho;
    tamanho.qtdLinhas = infoHeader.imageHeight;
    tamanho.qtdColunas = infoHeader.imageWidth;

    fclose(file);

    return tamanho;
}
//myBmp.h-----------------------------------------------------
#ifndef MYBMP_H
#define MYBMP_H
#pragma pack(1)


typedef struct {
    int qtdLinhas;
    int qtdColunas;
} IMG_TAM;

typedef struct {
    char signature[2];
    int fileSize;
    int reserved;
    int dataOffset;
} BMPFileHeader;

typedef struct {
    int headerSize;
    int imageWidth;
    int imageHeight;
    short planes;
    short bitsPerPixel;
    int compression;
    int imageSize;
    int xPixelsPerMeter;
    int yPixelsPerMeter;
    int colorsUsed;
    int importantColors;
} BMPInfoHeader;

// Declaração das funções
IMG_TAM pegarTamanho(const char* filename);
void carregaImagem(const char* filename, int** R, int** G, int** B, int width, int height);
void salvaImagem(const char* filename, int** R, int** G, int** B, int width, int height);
#endif

 

  • Curtir 3
Postado
2 horas atrás, matheus.Matta disse:

vocês EU FINALMENTE CONSEGUI, PROCUREI ENTENDER COMO MANIPULAR O BMP, CRIEI MINHA PROPRIA LIB PARA MANIPULAR ( vou deixa o codigo abaixo ) E FUNCIONOU PREFEITAMENTE.

 

Bom que desistiu daquele código. E de dirent.h. E dos VLA.

 

Sobre o código:

 

Tem agora seu código original, tem o seu código revisado, tem a versão que @Midori sugeriu. 

 

Sobre a conversão para preto e branco

 

É muito comum usar a média das cores e pronto, como fez

 

		int grayValue = (R[i][j] + G[i][j] + B[i][j]) / 3;

 

mas essa abaixo é a fórmula clássica que se vê sempre. Não sei a origem para poder creditar o autor, mas essa parece dar resultado mais expressivo na imagem

 

        double value = (*p * 0.114) + *(p + 1) * 0.587 +
                     *(p + 2) * 0.299;  // isso e antigo

 e claro as cores estão na ordem RGB 

 

Sobre a versão revisada

 

// Implementação da função para carregar uma imagem BMP
void carregaImagem(const char* filename, int** R, int** G, int** B, int width, int height) {
    FILE* file = fopen(filename, "rb");

    if (file == NULL) {
        printf("Erro ao abrir o arquivo BMP.\n");
        return;
    }

    BMPFileHeader fileHeader;
    BMPInfoHeader infoHeader;

    fread(&fileHeader, sizeof(BMPFileHeader), 1, file);
    fread(&infoHeader, sizeof(BMPInfoHeader), 1, file);

    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            fread(&B[i][j], 1, 1, file);
            fread(&G[i][j], 1, 1, file);
            fread(&R[i][j], 1, 1, file);
        }
    }

    fclose(file);
}

 

Entenda que o comentário no início é um pouco folclórico. Dá pra imaginar que a função com aquele nome faça isso. E que seja a implementação. Não use acentos em comentários. Podem nem sair na tela ou na impressão.

 

Agora imagine um bitmap de 1024x768, pequeno. Sua função vai chamar duas vezes fread para ler os headers em separado. Para que?

 

E depois vai chamar fread mais de 2.3 milhões de vezes para ler o bitmap. Acha certo? Não é certo. Se fosse um FHD comum 1920x1080 seriam 6.2 milhões de chamadas. E mais duas,

 

    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            fread(&B[i][j], 1, 1, file);
            fread(&G[i][j], 1, 1, file);
            fread(&R[i][j], 1, 1, file);
        }
    }

 

E para cada pixel vai calcular o endereço 3 vezes a partir de i e j. Claro que vai dar o mesmo resultado nas 3 vezes. 

 

	void carregaImagem(const char* filename,
                       int** R, int** G, int** B, int width, int height);

 

E está usando nada menos que SEIS parâmetros.

 

Pense nisso.

 

  • Obrigado 1

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

Ebook grátis: Aprenda a ler resistores e capacitores!

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!