common-image.c (libcaca-0.99.beta19) | : | common-image.c (libcaca-0.99.beta20.tar.bz2) | ||
---|---|---|---|---|
/* | /* | |||
* Imaging tools for cacaview and img2irc | * Imaging tools for cacaview and img2irc | |||
* Copyright (c) 2002-2012 Sam Hocevar <sam@hocevar.net> | * Copyright © 2002—2021 Sam Hocevar <sam@hocevar.net> | |||
* All Rights Reserved | * All Rights Reserved | |||
* | * | |||
* This program is free software. It comes without any warranty, to | * This program is free software. It comes without any warranty, to | |||
* the extent permitted by applicable law. You can redistribute it | * the extent permitted by applicable law. You can redistribute it | |||
* and/or modify it under the terms of the Do What the Fuck You Want | * and/or modify it under the terms of the Do What the Fuck You Want | |||
* to Public License, Version 2, as published by Sam Hocevar. See | * to Public License, Version 2, as published by the WTFPL Task Force. | |||
* http://www.wtfpl.net/ for more details. | * See http://www.wtfpl.net/ for more details. | |||
*/ | */ | |||
#include "config.h" | #include "config.h" | |||
#if !defined(__KERNEL__) | #if !defined(__KERNEL__) | |||
# include <string.h> | # include <string.h> | |||
# include <stdlib.h> | # include <stdlib.h> | |||
#endif | #endif | |||
#if defined(USE_IMLIB2) | #if defined(USE_IMLIB2) | |||
skipping to change at line 37 | skipping to change at line 37 | |||
#if !defined(USE_IMLIB2) | #if !defined(USE_IMLIB2) | |||
static unsigned int u32fread(caca_file_t *); | static unsigned int u32fread(caca_file_t *); | |||
static unsigned int u16fread(caca_file_t *); | static unsigned int u16fread(caca_file_t *); | |||
static unsigned int u8fread(caca_file_t *); | static unsigned int u8fread(caca_file_t *); | |||
#endif | #endif | |||
struct image * load_image(char const * name) | struct image * load_image(char const * name) | |||
{ | { | |||
struct image * im = malloc(sizeof(struct image)); | struct image * im = malloc(sizeof(struct image)); | |||
unsigned int depth, bpp, rmask, gmask, bmask, amask; | unsigned int rmask, gmask, bmask, amask; | |||
#if defined(USE_IMLIB2) | #if defined(USE_IMLIB2) | |||
Imlib_Image image; | Imlib_Image image; | |||
/* Load the new image */ | /* Load the new image */ | |||
image = imlib_load_image(name); | image = imlib_load_image(name); | |||
if(!image) | if(!image) | |||
{ | { | |||
free(im); | free(im); | |||
skipping to change at line 59 | skipping to change at line 59 | |||
} | } | |||
imlib_context_set_image(image); | imlib_context_set_image(image); | |||
im->pixels = (char *)imlib_image_get_data_for_reading_only(); | im->pixels = (char *)imlib_image_get_data_for_reading_only(); | |||
im->w = imlib_image_get_width(); | im->w = imlib_image_get_width(); | |||
im->h = imlib_image_get_height(); | im->h = imlib_image_get_height(); | |||
rmask = 0x00ff0000; | rmask = 0x00ff0000; | |||
gmask = 0x0000ff00; | gmask = 0x0000ff00; | |||
bmask = 0x000000ff; | bmask = 0x000000ff; | |||
amask = 0xff000000; | amask = 0xff000000; | |||
bpp = 32; | uint32_t bpp = 32; | |||
depth = 4; | uint32_t depth = 4; | |||
/* Create the libcaca dither */ | /* Create the libcaca dither */ | |||
im->dither = caca_create_dither(bpp, im->w, im->h, depth * im->w, | im->dither = caca_create_dither(bpp, im->w, im->h, depth * im->w, | |||
rmask, gmask, bmask, amask); | rmask, gmask, bmask, amask); | |||
if(!im->dither) | if(!im->dither) | |||
{ | { | |||
imlib_free_image(); | imlib_free_image(); | |||
free(im); | free(im); | |||
return NULL; | return NULL; | |||
} | } | |||
im->priv = (void *)image; | im->priv = (void *)image; | |||
#else | #else | |||
/* Try to load a BMP file */ | /* Try to load a BMP file */ | |||
uint32_t red[256], green[256], blue[256], alpha[256]; | uint32_t red[256], green[256], blue[256], alpha[256]; | |||
unsigned int i, colors, offset, tmp, planes; | unsigned int tmp; | |||
caca_file_t *f; | ||||
f = caca_file_open(name, "rb"); | caca_file_t *f = caca_file_open(name, "rb"); | |||
if(!f) | if (!f) | |||
{ | { | |||
free(im); | free(im); | |||
return NULL; | return NULL; | |||
} | } | |||
if(u16fread(f) != 0x4d42) | if (u16fread(f) != 0x4d42) | |||
{ | { | |||
caca_file_close(f); | caca_file_close(f); | |||
free(im); | free(im); | |||
return NULL; | return NULL; | |||
} | } | |||
u32fread(f); /* size */ | u32fread(f); /* size */ | |||
u16fread(f); /* reserved 1 */ | u16fread(f); /* reserved 1 */ | |||
u16fread(f); /* reserved 2 */ | u16fread(f); /* reserved 2 */ | |||
offset = u32fread(f); | uint32_t offset = u32fread(f); | |||
uint32_t header_size = u32fread(f); /* header size */ | ||||
tmp = u32fread(f); /* header size */ | im->w = u32fread(f); | |||
if(tmp == 40) | im->h = u32fread(f); | |||
uint32_t planes = u16fread(f); | ||||
uint32_t bpp = u16fread(f); | ||||
uint32_t colors = 0; | ||||
/* Sanity check */ | ||||
if (planes != 1) | ||||
{ | { | |||
im->w = u32fread(f); | caca_file_close(f); | |||
im->h = u32fread(f); | free(im); | |||
planes = u16fread(f); | return NULL; | |||
bpp = u16fread(f); | } | |||
tmp = u32fread(f); /* compression */ | if (header_size == 40) | |||
if(tmp != 0) | { | |||
if (u32fread(f) != 0) /* compression */ | ||||
{ | { | |||
caca_file_close(f); | caca_file_close(f); | |||
free(im); | free(im); | |||
return NULL; | return NULL; | |||
} | } | |||
u32fread(f); /* sizeimage */ | u32fread(f); /* sizeimage */ | |||
u32fread(f); /* xpelspermeter */ | u32fread(f); /* xpelspermeter */ | |||
u32fread(f); /* ypelspermeter */ | u32fread(f); /* ypelspermeter */ | |||
u32fread(f); /* biclrused */ | u32fread(f); /* biclrused */ | |||
u32fread(f); /* biclrimportantn */ | u32fread(f); /* biclrimportantn */ | |||
colors = (offset - 54) / 4; | colors = (offset - 54) / 4; | |||
for(i = 0; i < colors && i < 256; i++) | for (uint32_t i = 0; i < colors && i < 256; i++) | |||
{ | { | |||
blue[i] = u8fread(f) * 16; | blue[i] = u8fread(f) * 16; | |||
green[i] = u8fread(f) * 16; | green[i] = u8fread(f) * 16; | |||
red[i] = u8fread(f) * 16; | red[i] = u8fread(f) * 16; | |||
alpha[i] = 0; | alpha[i] = 0; | |||
u8fread(f); | u8fread(f); | |||
} | } | |||
} | } | |||
else if(tmp == 12) | else if (header_size == 12) | |||
{ | { | |||
im->w = u32fread(f); | ||||
im->h = u32fread(f); | ||||
planes = u16fread(f); | ||||
bpp = u16fread(f); | ||||
colors = (offset - 26) / 3; | colors = (offset - 26) / 3; | |||
for(i = 0; i < colors && i < 256; i++) | for (uint32_t i = 0; i < colors && i < 256; i++) | |||
{ | { | |||
blue[i] = u8fread(f); | blue[i] = u8fread(f); | |||
green[i] = u8fread(f); | green[i] = u8fread(f); | |||
red[i] = u8fread(f); | red[i] = u8fread(f); | |||
alpha[i] = 0; | alpha[i] = 0; | |||
} | } | |||
} | } | |||
else | else | |||
{ | { | |||
caca_file_close(f); | caca_file_close(f); | |||
free(im); | free(im); | |||
return NULL; | return NULL; | |||
} | } | |||
/* Fill the rest of the palette */ | /* Fill the rest of the palette */ | |||
for(i = colors; i < 256; i++) | for (uint32_t i = colors; i < 256; i++) | |||
blue[i] = green[i] = red[i] = alpha[i] = 0; | blue[i] = green[i] = red[i] = alpha[i] = 0; | |||
depth = (bpp + 7) / 8; | uint32_t depth = (bpp + 7) / 8; | |||
/* Sanity check */ | ||||
if(!im->w || im->w > 0x10000 || !im->h || im->h > 0x10000 || planes != 1) | ||||
{ | ||||
caca_file_close(f); | ||||
free(im); | ||||
return NULL; | ||||
} | ||||
/* Allocate the pixel buffer */ | /* Allocate the pixel buffer */ | |||
im->pixels = malloc(im->w * im->h * depth); | im->pixels = _caca_alloc2d(im->w, im->h, depth); | |||
if(!im->pixels) | if (!im->pixels) | |||
{ | { | |||
caca_file_close(f); | caca_file_close(f); | |||
free(im); | free(im); | |||
return NULL; | return NULL; | |||
} | } | |||
memset(im->pixels, 0, im->w * im->h * depth); | memset(im->pixels, 0, im->w * im->h * depth); | |||
/* Read the bitmap data */ | /* Read the bitmap data */ | |||
for(i = im->h; i--; ) | for (size_t y = im->h; y--; ) | |||
{ | { | |||
unsigned int j, k, bits = 0; | uint32_t bits = 0; | |||
switch(bpp) | switch (bpp) | |||
{ | { | |||
case 1: | case 1: | |||
for(j = 0; j < im->w; j++) | for (size_t x = 0; x < im->w; x++) | |||
{ | { | |||
k = j % 32; | size_t k = x % 32; | |||
if(k == 0) | if (k == 0) | |||
bits = u32fread(f); | bits = u32fread(f); | |||
im->pixels[im->w * i * depth + j] = | im->pixels[im->w * y * depth + x] = | |||
(bits >> ((k & ~0xf) + 0xf - (k & 0xf))) & 0x1; | (bits >> ((k & ~0xf) + 0xf - (k & 0xf))) & 0x1; | |||
} | } | |||
break; | break; | |||
case 4: | case 4: | |||
for(j = 0; j < im->w; j++) | for (size_t x = 0; x < im->w; x++) | |||
{ | { | |||
k = j % 8; | size_t k = x % 8; | |||
if(k == 0) | if (k == 0) | |||
bits = u32fread(f); | bits = u32fread(f); | |||
im->pixels[im->w * i * depth + j] = | im->pixels[im->w * y * depth + x] = | |||
(bits >> (4 * ((k & ~0x1) + 0x1 - (k & 0x1)))) & 0xf; | (bits >> (4 * ((k & ~0x1) + 0x1 - (k & 0x1)))) & 0xf; | |||
} | } | |||
break; | break; | |||
default: | default: | |||
/* Works for 8bpp, but also for 16, 24 etc. */ | /* Works for 8bpp, but also for 16, 24 etc. */ | |||
caca_file_read(f, im->pixels + im->w * i * depth, | caca_file_read(f, im->pixels + im->w * y * depth, | |||
im->w * depth); | im->w * depth); | |||
/* Pad reads to 4 bytes */ | /* Pad reads to 4 bytes */ | |||
tmp = (im->w * depth) % 4; | tmp = (im->w * depth) % 4; | |||
tmp = (4 - tmp) % 4; | tmp = (4 - tmp) % 4; | |||
while(tmp--) | while (tmp--) | |||
u8fread(f); | u8fread(f); | |||
break; | break; | |||
} | } | |||
} | } | |||
switch(depth) | switch(depth) | |||
{ | { | |||
case 3: | case 3: | |||
rmask = 0xff0000; | rmask = 0xff0000; | |||
gmask = 0x00ff00; | gmask = 0x00ff00; | |||
skipping to change at line 245 | skipping to change at line 239 | |||
default: | default: | |||
bpp = 8; | bpp = 8; | |||
rmask = gmask = bmask = amask = 0; | rmask = gmask = bmask = amask = 0; | |||
break; | break; | |||
} | } | |||
caca_file_close(f); | caca_file_close(f); | |||
/* Create the libcaca dither */ | /* Create the libcaca dither */ | |||
im->dither = caca_create_dither(bpp, im->w, im->h, depth * im->w, | im->dither = caca_create_dither(bpp, im->w, im->h, depth * im->w, | |||
rmask, gmask, bmask, amask); | rmask, gmask, bmask, amask); | |||
if(!im->dither) | if(!im->dither) | |||
{ | { | |||
free(im->pixels); | free(im->pixels); | |||
free(im); | free(im); | |||
return NULL; | return NULL; | |||
} | } | |||
if(bpp == 8) | if (bpp == 8) | |||
caca_set_dither_palette(im->dither, red, green, blue, alpha); | caca_set_dither_palette(im->dither, red, green, blue, alpha); | |||
#endif | #endif | |||
return im; | return im; | |||
} | } | |||
void unload_image(struct image * im) | void unload_image(struct image * im) | |||
{ | { | |||
#if defined(USE_IMLIB2) | #if defined(USE_IMLIB2) | |||
/* Imlib_Image image = (Imlib_Image)im->priv; */ | /* Imlib_Image image = (Imlib_Image)im->priv; */ | |||
imlib_free_image(); | imlib_free_image(); | |||
#else | #else | |||
free(im->pixels); | free(im->pixels); | |||
#endif | #endif | |||
caca_free_dither(im->dither); | caca_free_dither(im->dither); | |||
} | } | |||
#if !defined(USE_IMLIB2) | #if !defined(USE_IMLIB2) | |||
static unsigned int u32fread(caca_file_t * f) | static unsigned int u32fread(caca_file_t * f) | |||
{ | { | |||
uint8_t buffer[4]; | uint8_t buffer[4] = { 0 }; | |||
caca_file_read(f, buffer, 4); | caca_file_read(f, buffer, 4); | |||
return ((unsigned int)buffer[3] << 24) | ((unsigned int)buffer[2] << 16) | return ((unsigned int)buffer[3] << 24) | ((unsigned int)buffer[2] << 16) | |||
| ((unsigned int)buffer[1] << 8) | ((unsigned int)buffer[0]); | | ((unsigned int)buffer[1] << 8) | ((unsigned int)buffer[0]); | |||
} | } | |||
static unsigned int u16fread(caca_file_t * f) | static unsigned int u16fread(caca_file_t * f) | |||
{ | { | |||
uint8_t buffer[2]; | uint8_t buffer[2] = { 0 }; | |||
caca_file_read(f, buffer, 2); | caca_file_read(f, buffer, 2); | |||
return ((unsigned int)buffer[1] << 8) | ((unsigned int)buffer[0]); | return ((unsigned int)buffer[1] << 8) | ((unsigned int)buffer[0]); | |||
} | } | |||
static unsigned int u8fread(caca_file_t * f) | static unsigned int u8fread(caca_file_t * f) | |||
{ | { | |||
uint8_t buffer; | uint8_t buffer[1] = { 0 }; | |||
caca_file_read(f, &buffer, 1); | caca_file_read(f, buffer, 1); | |||
return (unsigned int)buffer; | return (unsigned int)buffer[0]; | |||
} | } | |||
#endif | #endif | |||
End of changes. 35 change blocks. | ||||
63 lines changed or deleted | 57 lines changed or added |