Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow images to be piped in via stdin #27

Merged
merged 1 commit into from Jul 27, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/catimg.c
Expand Up @@ -108,7 +108,12 @@ int main(int argc, char *argv[])

if (cols < 1) // if precision is 2 we can use the terminal full width. Otherwise we can only use half
cols = terminal_columns() / (2 / precision);
img_load_from_file(&img, file);

if (strcmp(file, "-") == 0) {
img_load_from_stdin(&img);
} else {
img_load_from_file(&img, file);
}
if (cols < img.width) {
float sc = cols/(float)img.width;
img_resize(&img, sc, sc);
Expand Down
78 changes: 57 additions & 21 deletions src/sh_image.c
@@ -1,4 +1,5 @@
#include "sh_image.h"
#include "sh_utils.h"
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#include <stdlib.h>
Expand All @@ -10,20 +11,10 @@ typedef struct gif_result_t {
struct gif_result_t *next;
} gif_result;

// stbi_xload was written by urraka and slighty modified by me (posva) to make
// it have a channels argument. Thanks to urraka for his help with this :)
STBIDEF unsigned char *stbi_xload(char const *filename, int *x, int *y, int *frames, int *channels)
STBIDEF unsigned char *stbi__xload_main(stbi__context *s, int *x, int *y, int *frames, int *channels)
{
FILE *f;
stbi__context s;
unsigned char *result = 0;

if (!(f = stbi__fopen(filename, "rb")))
return stbi__errpuc("can't fopen", "Unable to open file");

stbi__start_file(&s, f);

if (stbi__gif_test(&s)) {
if (stbi__gif_test(s)) {
stbi__gif g;
gif_result head;
gif_result *prev = 0, *gr = &head;
Expand All @@ -33,8 +24,8 @@ STBIDEF unsigned char *stbi_xload(char const *filename, int *x, int *y, int *fra

*frames = 0;

while ((gr->data = stbi__gif_load_next(&s, &g, channels, 4))) {
if (gr->data == (unsigned char*)&s) {
while ((gr->data = stbi__gif_load_next(s, &g, channels, 4))) {
if (gr->data == (unsigned char*)s) {
gr->data = 0;
break;
}
Expand Down Expand Up @@ -78,14 +69,42 @@ STBIDEF unsigned char *stbi_xload(char const *filename, int *x, int *y, int *fra
}
}
} else {
result = stbi__load_main(&s, x, y, channels, 0);
result = stbi__load_main(s, x, y, channels, 0);
*frames = !!result;
}

return result;
}

// stbi_xload was written by urraka and slighty modified by me (posva) to make
// it have a channels argument. Thanks to urraka for his help with this :)
STBIDEF unsigned char *stbi_xload(char const *filename, int *x, int *y, int *frames, int *channels)
{
FILE *f;
stbi__context s;
unsigned char *result = 0;

if (!(f = stbi__fopen(filename, "rb")))
return stbi__errpuc("can't fopen", "Unable to open file");

stbi__start_file(&s, f);

result = stbi__xload_main(&s, x, y, frames, channels);

fclose(f);

return result;
}

STBIDEF unsigned char *stbi_xload_from_memory(stbi_uc *buffer, int len, int *x, int *y, int *frames, int *channels)
{
stbi__context s;

stbi__start_mem(&s, buffer, len);

return stbi__xload_main(&s, x, y, frames, channels);
}

void setPixelGray(color_t *pixel, unsigned char* ptr) {
pixel->r = pixel->g = pixel->b = ptr[0];
pixel->a = 255;
Expand All @@ -110,12 +129,7 @@ void setPixelRGBAlpha(color_t *pixel, unsigned char* ptr) {
pixel->a = ptr[3];
}

void img_load_from_file(image_t *img, const char* file)
{
int channels, w, h, frames;
/*unsigned char* ptr = stbi_load(file, &w, &h, &channels, 0);*/
unsigned char* ptr = stbi_xload(file, &w, &h, &frames, &channels);

void img_load_from_data(image_t *img, stbi_uc* ptr, int w, int h, int frames, int channels) {
if (ptr && w && h) {
img->width = w;
/*h *= 3;*/
Expand Down Expand Up @@ -168,6 +182,28 @@ void img_load_from_file(image_t *img, const char* file)
}
}

void img_load_from_file(image_t *img, const char* file)
{
int channels, w, h, frames;
unsigned char* ptr = stbi_xload(file, &w, &h, &frames, &channels);

img_load_from_data(img, ptr, w, h, frames, channels);
}

void img_load_from_stdin(image_t *img)
{
int channels, w, h, frames;
unsigned char *mem;

uint32_t len = read_stdin(&mem);

unsigned char* ptr = stbi_xload_from_memory(mem, len, &w, &h, &frames, &channels);

free(mem);

img_load_from_data(img, ptr, w, h, frames, channels);
}

void img_create(image_t *img, uint32_t width, uint32_t height)
{
if (!(img->pixels = malloc(sizeof(color_t)*width*height))) {
Expand Down
7 changes: 7 additions & 0 deletions src/sh_image.h
Expand Up @@ -57,6 +57,13 @@ typedef struct {
*/
void img_load_from_file(image_t *img, const char* file);

/**
* @brief Load an image from stdin
*
* @param img instance
*/
void img_load_from_stdin(image_t *img);

/**
* @brief Init a transparent picture
*
Expand Down
50 changes: 49 additions & 1 deletion src/sh_utils.c
Expand Up @@ -2,10 +2,19 @@

#ifdef WINDOWS
#include <windows.h>
#include <io.h>
#include <fcntl.h>
#define fileno _fileno
#define read _read
#else
#include <sys/ioctl.h>
#include <unistd.h>
#endif

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

uint32_t terminal_columns()
{
#ifdef WINDOWS
Expand All @@ -15,8 +24,47 @@ uint32_t terminal_columns()
return ret?csbi.dwSize.X:0;
#else
struct winsize win;
ioctl(0, TIOCGWINSZ, &win);
ioctl(1, TIOCGWINSZ, &win);
return win.ws_col;
#endif
}

#define READ_BUF_SIZE 4096
uint32_t read_stdin(unsigned char **ptr) {
#ifdef WINDOWS
_setmode(_fileno(stdin), _O_BINARY);
#endif
size_t size = 0;
ssize_t count = 0;

size_t cur_size = READ_BUF_SIZE;
unsigned char* data = malloc(cur_size);

unsigned char buf[READ_BUF_SIZE];

int fd = fileno(stdin);

while((count = read(fd, buf, READ_BUF_SIZE)) > 0) {
size += count;
if (size > cur_size) {
cur_size *= 2;
data = realloc(data, cur_size);
if (!data) {
printf("Error: Could not allocate memory\n");
exit(1);
}
}
memcpy(data+size-count, buf, count);
}

// If count is not zero, some error occured
if (count < 0) {
perror("read_stdin");
exit(1);
}

*ptr = data;

return size;
}

8 changes: 8 additions & 0 deletions src/sh_utils.h
Expand Up @@ -31,5 +31,13 @@
* @return the number of columns
*/
uint32_t terminal_columns();

/**
* @brief Read binary data from stdin
* @param ptr Address to the ptr which will be filled with the data
* @return number of bytes read
*/
uint32_t read_stdin(unsigned char **ptr);

///@}
#endif
2 changes: 1 addition & 1 deletion src/stb_image.h
Expand Up @@ -4525,7 +4525,7 @@ static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp)

// Microsoft/Windows BMP image

#ifndef STBI_NO_BMP && STBI_NO_ICO
#if !defined(STBI_NO_BMP) && !defined(STBI_NO_ICO)
static int stbi__bmp_test_raw(stbi__context *s)
{
int r;
Expand Down