forked from tTh/FloatImg
322 lines
6.7 KiB
C
322 lines
6.7 KiB
C
/*
|
|
* fimg-pnm.c
|
|
*
|
|
* crude version who make HUGE ascii files !
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <stdint.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include "../floatimg.h"
|
|
|
|
extern int verbosity; /* must be declared around main() */
|
|
|
|
/* ---------------------------------------------------------------- */
|
|
/* nouveau juin 2019, pendant la Ravebish */
|
|
|
|
int fimg_load_from_pnm(char *fname, FloatImg *head, int notused)
|
|
{
|
|
FILE *fp;
|
|
int width, height, maxval;
|
|
int foo, line, column;
|
|
unsigned char *buffline, *idxrd, dummychar;
|
|
float *Rptr, *Gptr, *Bptr;
|
|
|
|
if (NULL==head) {
|
|
fprintf(stderr, "%s : head ptr is %p\n", __func__, head);
|
|
return -8;
|
|
}
|
|
|
|
if (NULL==(fp=fopen(fname, "r"))) {
|
|
perror(fname);
|
|
exit(1);
|
|
}
|
|
|
|
foo = fscanf(fp, "P6 %d %d %d", &width, &height, &maxval);
|
|
if (3 != foo) {
|
|
fprintf(stderr, "%s : fscanf -> %d\n", __func__, foo);
|
|
return -1;
|
|
}
|
|
|
|
if (verbosity) {
|
|
fprintf(stderr, "%s is %dx%d , max=%d\n",fname, width, height, maxval);
|
|
}
|
|
|
|
if (NULL==(buffline=calloc(3, width))) {
|
|
fprintf(stderr, "%s on %s : memory error\n", __func__, fname);
|
|
return -2;
|
|
}
|
|
|
|
foo = fimg_create(head, width, height, 3);
|
|
if (foo) {
|
|
fprintf(stderr, "%s : create floatimg -> %d\n", __func__, foo);
|
|
exit(1);
|
|
}
|
|
|
|
#if DEBUG_LEVEL
|
|
fread(&dummychar, 1, 1, fp);
|
|
fprintf(stderr, "%s : dummychar %xx\n", __func__, dummychar);
|
|
#else
|
|
fseek(fp, 1L, SEEK_CUR); /* black magic */
|
|
#endif
|
|
|
|
Rptr = head->R; Gptr = head->G; Bptr = head->B;
|
|
for (line=0; line<height; line++) {
|
|
foo = fread(buffline, 3, width, fp);
|
|
// fprintf(stderr, "line %d read %d\n", line, width);
|
|
idxrd = buffline;
|
|
for (column=0; column<width; column++)
|
|
{
|
|
*Rptr++ = (float)*idxrd++;
|
|
*Gptr++ = (float)*idxrd++;
|
|
*Bptr++ = (float)*idxrd++;
|
|
}
|
|
}
|
|
|
|
fclose(fp);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* ---------------------------------------------------------------- */
|
|
/*
|
|
* this func write the content of the R channel, the
|
|
* only one used by graylevel images
|
|
*/
|
|
static void dump_gray_values(FILE *fp, FloatImg *picz, float fk)
|
|
{
|
|
int cnt, sz, value;
|
|
int idx;
|
|
|
|
cnt = 0;
|
|
sz = picz->width * picz->height;
|
|
for (idx=0; idx<sz; idx++) {
|
|
if (fk > 0) value = (int)(picz->R[idx] / fk);
|
|
else value = 0;
|
|
cnt += fprintf(fp, "%d", value);
|
|
if (cnt > 70) {
|
|
fputs("\n", fp); cnt = 0;
|
|
}
|
|
else {
|
|
fputs(" ", fp); cnt++;
|
|
}
|
|
}
|
|
fputs("\n", fp);
|
|
}
|
|
/* ---------------------------------------------------------------- */
|
|
static void dump_rgb_values(FILE *fp, FloatImg *picz, float fk)
|
|
{
|
|
int cnt, sz, idx;
|
|
int Rv, Gv, Bv;
|
|
|
|
cnt = 0;
|
|
sz = picz->width * picz->height;
|
|
for (idx=0; idx<sz; idx++) {
|
|
if (fk > 0) { /* why ? */
|
|
Rv = (int)(picz->R[idx] / fk);
|
|
Gv = (int)(picz->G[idx] / fk);
|
|
Bv = (int)(picz->B[idx] / fk);
|
|
}
|
|
else {
|
|
Rv = Gv = Bv = 0;
|
|
}
|
|
cnt += fprintf(fp, "%d %d %d", Rv, Gv, Bv);
|
|
if (cnt > 60) {
|
|
fputs("\n", fp); cnt = 0;
|
|
}
|
|
else {
|
|
fputs(" ", fp); cnt++;
|
|
}
|
|
}
|
|
fputs("\n", fp);
|
|
}
|
|
/* ---------------------------------------------------------------- */
|
|
/*
|
|
* bit 0 of flags : use fvalue/count
|
|
*/
|
|
int fimg_save_as_pnm(FloatImg *head, char *fname, int flags)
|
|
{
|
|
FILE *fp;
|
|
float maximum, fk;
|
|
char *code;
|
|
|
|
#if DEBUG_LEVEL
|
|
fprintf(stderr, ">>> %-25s ( %p '%s' 0x%04x )\n", __func__, head,
|
|
fname, flags);
|
|
#endif
|
|
|
|
if ( head->type != FIMG_TYPE_RGB && head->type != FIMG_TYPE_GRAY) {
|
|
#if DEBUG_LEVEL
|
|
fprintf(stderr, "%s : type %d is bad.\n", __func__, head->type);
|
|
#endif
|
|
return -1;
|
|
}
|
|
|
|
if (NULL==(fp=fopen(fname, "w"))) {
|
|
perror(fname);
|
|
return -2;
|
|
}
|
|
|
|
switch(head->type) {
|
|
case FIMG_TYPE_GRAY: code = "P2"; break;
|
|
case FIMG_TYPE_RGB: code = "P3"; break;
|
|
}
|
|
|
|
fprintf(fp, "%s\n%d %d\n", code, head->width, head->height);
|
|
|
|
if ( flags & 1 ) {
|
|
fk = (head->fval * head->count) / 65535.0;
|
|
if (verbosity > 1) {
|
|
fprintf(stderr, "%s using fval/count %f %d -> %f\n",
|
|
__func__,
|
|
head->fval, head->count, fk);
|
|
}
|
|
fprintf(fp, "# fval/count %f %d\n", head->fval, head->count);
|
|
}
|
|
else {
|
|
maximum = fimg_get_maxvalue(head);
|
|
fk = maximum / 65535.0;
|
|
fprintf(fp, "# maxval %15f\n# divisor %15f\n", maximum, fk);
|
|
}
|
|
|
|
fprintf(fp, "65535\n");
|
|
fflush(fp);
|
|
|
|
switch(head->type) {
|
|
case FIMG_TYPE_GRAY:
|
|
dump_gray_values(fp, head, fk);
|
|
break;
|
|
case FIMG_TYPE_RGB:
|
|
dump_rgb_values(fp, head, fk);
|
|
break;
|
|
}
|
|
|
|
fputs("\n", fp); fclose(fp);
|
|
|
|
return 0;
|
|
}
|
|
/* ---------------------------------------------------------------- */
|
|
/* nouveau 27 fevrier 2022 */
|
|
/* WARNING ! UGLY CODE INSIDE */
|
|
int fimg_save_plane_as_pgm(FloatImg *psrc, char *fname, char plane)
|
|
{
|
|
FILE *fp;
|
|
float maxval, fk, *ptrplane;
|
|
int area, idx, printed;
|
|
|
|
|
|
#if DEBUG_LEVEL
|
|
fprintf(stderr, ">>> %s ( %p %s '%c' )\n", __func__, psrc, fname, plane);
|
|
#endif
|
|
|
|
switch (plane) {
|
|
case 'r': case 'R':
|
|
ptrplane = psrc->R; break;
|
|
case 'g': case 'G':
|
|
ptrplane = psrc->G; break;
|
|
case 'b': case 'B':
|
|
ptrplane = psrc->B; break;
|
|
case 'a': case 'A':
|
|
ptrplane = psrc->A; break;
|
|
default:
|
|
fprintf(stderr, "%s: bad plane '%c'\n", __func__, plane);
|
|
abort(); break;
|
|
}
|
|
|
|
if (NULL == ptrplane) { /* mmmm... */
|
|
fprintf(stderr, "%s: mmmm...\n", __func__);
|
|
return -3;
|
|
}
|
|
|
|
if (NULL==(fp=fopen(fname, "w"))) {
|
|
perror(fname);
|
|
return -2;
|
|
}
|
|
|
|
/* WARNING !
|
|
* some software (yes, povray, I look at you) doesn't like
|
|
* width and height on two separate lines.
|
|
*/
|
|
fprintf(fp, "P2\n%d %d\n65535\n\n", psrc->width, psrc->height);
|
|
|
|
area = psrc->width * psrc->height;
|
|
maxval = fimg_get_plane_maxvalue(psrc, plane);
|
|
fk = maxval / 65535.0;
|
|
|
|
if (verbosity) {
|
|
fprintf(stderr, "%s: maxval of plane '%c' = %f\n", __func__,
|
|
plane, maxval);
|
|
}
|
|
|
|
printed = 0;
|
|
for (idx=0; idx<area; idx++) {
|
|
printed += fprintf(fp, "%d ", (int)(ptrplane[idx]/fk));
|
|
if (printed > 72) {
|
|
fputs("\n", fp);
|
|
printed = 0;
|
|
}
|
|
}
|
|
|
|
fclose(fp);
|
|
|
|
return 0;
|
|
}
|
|
/* ---------------------------------------------------------------- */
|
|
/* nouveau 10 fevrier 2022 */
|
|
int fimg_save_as_pgm(FloatImg *src, char *fname, int flags)
|
|
{
|
|
FILE *fp;
|
|
float maximum, fk;
|
|
int area, idx, printed;
|
|
float accu;
|
|
|
|
#if DEBUG_LEVEL
|
|
fprintf(stderr, ">>> %s ( %p %s %d )\n", __func__, src, fname, flags);
|
|
#endif
|
|
|
|
if (flags) {
|
|
fprintf(stderr, "%s: flags must be 0\n", __func__);
|
|
}
|
|
|
|
if ( src->type != FIMG_TYPE_RGB ) {
|
|
#if DEBUG_LEVEL
|
|
fprintf(stderr, "%s : type %d is bad.\n", __func__, src->type);
|
|
#endif
|
|
return -1;
|
|
}
|
|
|
|
if (NULL==(fp=fopen(fname, "w"))) {
|
|
perror(fname);
|
|
return -2;
|
|
}
|
|
|
|
/* WARNING !
|
|
* some software (yes, povray, I look at you) doesn't like
|
|
* width and height on two separate lines.
|
|
*/
|
|
fprintf(fp, "P2\n%d %d\n65535\n\n", src->width, src->height);
|
|
|
|
area = src->width * src->height;
|
|
maximum = fimg_get_maxvalue(src);
|
|
fk = maximum / 65535.0;
|
|
|
|
printed = 0;
|
|
for (idx=0; idx<area; idx++) {
|
|
accu = (src->R[idx] + src->G[idx] + src->B[idx]) / 3.0;
|
|
printed += fprintf(fp, "%d ", (int)(accu/fk));
|
|
if (printed > 72) {
|
|
fputs("\n", fp);
|
|
printed = 0;
|
|
}
|
|
}
|
|
|
|
fclose(fp);
|
|
|
|
return 0;
|
|
}
|
|
|