JWS C Library
C language utility library
jiff.c
Go to the documentation of this file.
00001 /*
00002  * This work is licensed under a Creative Commons 
00003  * Attribution-Noncommercial-Share Alike 3.0 United States License.
00004  * 
00005  *    http://creativecommons.org/licenses/by-nc-sa/3.0/us/
00006  * 
00007  * You are free:
00008  * 
00009  *    to Share - to copy, distribute, display, and perform the work
00010  *    to Remix - to make derivative works
00011  * 
00012  * Under the following conditions:
00013  * 
00014  *    Attribution. You must attribute the work in the manner specified by the
00015  *    author or licensor (but not in any way that suggests that they endorse you
00016  *    or your use of the work).
00017  * 
00018  *    Noncommercial. You may not use this work for commercial purposes.
00019  * 
00020  *    Share Alike. If you alter, transform, or build upon this work, you may
00021  *    distribute the resulting work only under the same or similar license to
00022  *    this one.
00023  * 
00024  * For any reuse or distribution, you must make clear to others the license
00025  * terms of this work. The best way to do this is by including this header.
00026  * 
00027  * Any of the above conditions can be waived if you get permission from the
00028  * copyright holder.
00029  * 
00030  * Apart from the remix rights granted under this license, nothing in this
00031  * license impairs or restricts the author's moral rights.
00032  */
00033 
00034 
00049 #include <jwsc/config.h>
00050 
00051 #include <stdlib.h>
00052 #include <stdio.h>
00053 #include <assert.h>
00054 #include <inttypes.h>
00055 
00056 #include "jwsc/base/bits.h"
00057 #include "jwsc/image/jiff.h"
00058 
00059 #ifdef JWSC_HAVE_DMALLOC
00060 #include <dmalloc.h>
00061 #endif
00062 
00063 
00065 #define  HEADER_SIZE              64
00066 
00068 #define  DEFAULT_JIFF_COLORSPACE  JIFF_RGB
00069 
00071 #define  DEFAULT_JIFF_DEPTH       JIFF_8_BIT
00072 
00074 #define  DEFAULT_JIFF_TYPE        JIFF_INTEGER
00075 
00077 #define  DEFAULT_JIFF_RED_W       0.3f
00078 
00080 #define  DEFAULT_JIFF_GREEN_W     0.59f
00081 
00083 #define  DEFAULT_JIFF_BLUE_W      0.11f
00084 
00085 
00087 void init_jiff_attributes(JIFF_attributes* attrs)
00088 {
00089     attrs->colorspace = DEFAULT_JIFF_COLORSPACE;
00090     attrs->depth      = DEFAULT_JIFF_DEPTH;
00091     attrs->type       = DEFAULT_JIFF_TYPE;
00092     attrs->red_w      = DEFAULT_JIFF_RED_W;
00093     attrs->green_w    = DEFAULT_JIFF_GREEN_W;
00094     attrs->blue_w     = DEFAULT_JIFF_BLUE_W;
00095 }
00096 
00097 
00098 
00099 
00117 Error* read_image_as_jiff_f(Image_f** img_out, const char* fname)
00118 {
00119     FILE* fp;
00120 
00121     uint32_t header[HEADER_SIZE];
00122 #ifndef JWSC_BIGENDIAN
00123     uint32_t i;
00124 #endif
00125 
00126     uint32_t num_rows;
00127     uint32_t num_cols;
00128 
00129     uint32_t num_channels;
00130     uint32_t channel_bytes;
00131 
00132     void*     data;
00133     float*    elts;
00134     uint32_t  num_elts;
00135     uint32_t  elt;
00136     Pixel_f*  pxls;
00137 
00138     JIFF_attributes attrs;
00139 
00140 
00141     if (!(fp = fopen(fname, "r")))
00142     {
00143         free_image_f(*img_out); *img_out = NULL;
00144         return JWSC_EIO("Could not open jiff file");
00145     }
00146 
00147     if (fread(header, 4, HEADER_SIZE, fp) != HEADER_SIZE)
00148     {
00149         fclose(fp);
00150         free_image_f(*img_out); *img_out = NULL;
00151         return JWSC_EIO("Could not read jiff header");
00152     }
00153 
00154 #ifndef JWSC_BIGENDIAN
00155     for (i = 0; i < HEADER_SIZE; i++)
00156     {
00157         bswap_u32(&(header[ i ]));
00158     }
00159 #endif
00160 
00161     num_rows = header[0];
00162     num_cols = header[1];
00163 
00164     /* Colorspace */
00165     switch (header[2])
00166     {
00167         case JIFF_RGB:
00168             attrs.colorspace = JIFF_RGB;
00169             num_channels = 3;
00170             break;
00171         case JIFF_GRAY:
00172             attrs.colorspace = JIFF_GRAY;
00173             num_channels = 1;
00174             break;
00175         default:
00176             fclose(fp);
00177             free_image_f(*img_out); *img_out = NULL;
00178             return JWSC_EIO("Unknown JIFF colorspace");
00179     }
00180 
00181     /* Depth */
00182     switch (header[3])
00183     {
00184         case JIFF_8_BIT:
00185             attrs.depth = JIFF_8_BIT;
00186             channel_bytes = 1;
00187             break;
00188         case JIFF_16_BIT:
00189             attrs.depth = JIFF_16_BIT;
00190             channel_bytes = 2;
00191             break;
00192         case JIFF_32_BIT:
00193             attrs.depth = JIFF_32_BIT;
00194             channel_bytes = 4;
00195             break;
00196         default:
00197             fclose(fp);
00198             free_image_f(*img_out); *img_out = NULL;
00199             return JWSC_EIO("Unknown JIFF channel depth");
00200     }
00201 
00202     /* Type */
00203     switch (header[4])
00204     {
00205         case JIFF_INTEGER:
00206             attrs.type = JIFF_INTEGER;
00207             break;
00208         case JIFF_FLOAT:
00209             if (attrs.depth != JIFF_32_BIT)
00210             {
00211                 fclose(fp);
00212                 free_image_f(*img_out); *img_out = NULL;
00213                 return JWSC_EIO("Invalid JIFF channel type for depth");
00214             }
00215             attrs.type = JIFF_FLOAT;
00216             break;
00217         default:
00218             fclose(fp);
00219             free_image_f(*img_out); *img_out = NULL;
00220             return JWSC_EIO("Unknown JIFF channel type");
00221     }
00222 
00223     num_elts = num_rows*num_cols*num_channels;
00224     assert(data = malloc(channel_bytes*num_elts));
00225 
00226     if (fread(data, channel_bytes, num_elts, fp) != num_elts)
00227     {
00228         free(data);
00229         fclose(fp);
00230         free_image_f(*img_out); *img_out = NULL;
00231         return JWSC_EIO("Could not read jiff data");
00232     }
00233 
00234 #ifndef JWSC_BIGENDIAN
00235     if (attrs.depth != JIFF_8_BIT)
00236     {
00237         for (elt = 0; elt < num_elts; elt++)
00238         {
00239             switch(attrs.depth)
00240             {
00241                 case JIFF_16_BIT:
00242                     bswap_u16(&(((uint16_t*)data)[ elt ]));
00243                     break;
00244                 case JIFF_32_BIT:
00245                     bswap_u32(&(((uint32_t*)data)[ elt ]));
00246                     break;
00247                 default:
00248                     abort();
00249             }
00250         }
00251     }
00252 #endif
00253 
00254     create_image_f(img_out, num_rows, num_cols);
00255     elts = (float*)*((*img_out)->pxls);
00256     pxls = *((*img_out)->pxls);
00257 
00258     if (attrs.colorspace == JIFF_RGB)
00259     {
00260         for (elt = 0; elt < num_elts; elt += 3)
00261         {
00262             if (attrs.type == JIFF_FLOAT)
00263             {
00264                 elts[ elt+0 ] = ((float*)data)[ elt+0 ];
00265                 elts[ elt+1 ] = ((float*)data)[ elt+1 ];
00266                 elts[ elt+2 ] = ((float*)data)[ elt+2 ];
00267             }
00268             else if (attrs.depth == JIFF_8_BIT)
00269             {
00270                 elts[ elt+0 ] = (float)((uint8_t*)data)[ elt+0 ] / 0xFF;
00271                 elts[ elt+1 ] = (float)((uint8_t*)data)[ elt+1 ] / 0xFF;
00272                 elts[ elt+2 ] = (float)((uint8_t*)data)[ elt+2 ] / 0xFF;
00273             }
00274             else if (attrs.depth == JIFF_16_BIT)
00275             {
00276                 elts[ elt+0 ] = (float)((uint16_t*)data)[ elt+0 ] / 0xFFFF;
00277                 elts[ elt+1 ] = (float)((uint16_t*)data)[ elt+1 ] / 0xFFFF;
00278                 elts[ elt+2 ] = (float)((uint16_t*)data)[ elt+2 ] / 0xFFFF;
00279             }
00280             else if (attrs.depth == JIFF_32_BIT)
00281             {
00282                 elts[ elt+0 ] = (float)((uint32_t*)data)[ elt+0 ] / 0xFFFFFFFF;
00283                 elts[ elt+1 ] = (float)((uint32_t*)data)[ elt+1 ] / 0xFFFFFFFF;
00284                 elts[ elt+2 ] = (float)((uint32_t*)data)[ elt+2 ] / 0xFFFFFFFF;
00285             }
00286             else
00287             {
00288                 abort();
00289             }
00290         }
00291     }
00292     else if (attrs.colorspace == JIFF_GRAY)
00293     {
00294         for (elt = 0; elt < num_elts; elt++)
00295         {
00296             if (attrs.type == JIFF_FLOAT)
00297             {
00298                 pxls[ elt ].r = ((float*)data)[ elt ];
00299                 pxls[ elt ].g = ((float*)data)[ elt ];
00300                 pxls[ elt ].b = ((float*)data)[ elt ];
00301             }
00302             else if (attrs.depth == JIFF_8_BIT)
00303             {
00304                 pxls[ elt ].r = (float)((uint8_t*)data)[ elt ] / 0xFF;
00305                 pxls[ elt ].g = (float)((uint8_t*)data)[ elt ] / 0xFF;
00306                 pxls[ elt ].b = (float)((uint8_t*)data)[ elt ] / 0xFF;
00307             }
00308             else if (attrs.depth == JIFF_16_BIT)
00309             {
00310                 pxls[ elt ].r = (float)((uint16_t*)data)[ elt ] / 0xFFFF;
00311                 pxls[ elt ].g = (float)((uint16_t*)data)[ elt ] / 0xFFFF;
00312                 pxls[ elt ].b = (float)((uint16_t*)data)[ elt ] / 0xFFFF;
00313             }
00314             else if (attrs.depth == JIFF_32_BIT)
00315             {
00316                 pxls[ elt ].r = (float)((uint32_t*)data)[ elt ] / 0xFFFFFFFF;
00317                 pxls[ elt ].g = (float)((uint32_t*)data)[ elt ] / 0xFFFFFFFF;
00318                 pxls[ elt ].b = (float)((uint32_t*)data)[ elt ] / 0xFFFFFFFF;
00319             }
00320             else
00321             {
00322                 abort();
00323             }
00324         }
00325     }
00326     else
00327     {
00328         abort();
00329     }
00330 
00331     free(data);
00332     fclose(fp);
00333 
00334     return NULL;
00335 }
00336 
00358 Error* write_image_as_jiff_f
00359 (
00360     const Image_f*         img, 
00361     const char*            fname, 
00362     const JIFF_attributes* attrs
00363 )
00364 {
00365     FILE* fp;
00366 
00367     uint32_t header[HEADER_SIZE] = {0};
00368     uint32_t num_elts;
00369     uint32_t elt;
00370     uint32_t num_channels;
00371     uint32_t channel_bytes;
00372 #ifndef JWSC_BIGENDIAN
00373     uint32_t i;
00374 #endif
00375 
00376     float gray;
00377     float red, green, blue;
00378 
00379     void*     data;
00380     float*    elts;
00381     Pixel_f*  pxls;
00382 
00383 
00384     if (attrs->type == JIFF_FLOAT && attrs->depth != JIFF_32_BIT)
00385     {
00386         return JWSC_EIO("Invalid JIFF channel type for depth");
00387     }
00388 
00389 
00390     /* Prepare the header. */
00391     header[0] = img->num_rows;
00392     header[1] = img->num_cols;
00393     header[2] = attrs->colorspace;
00394     header[3] = attrs->depth;
00395     header[4] = attrs->type;
00396 
00397 #ifndef JWSC_BIGENDIAN
00398     for (i = 0; i < HEADER_SIZE; i++)
00399     {
00400         bswap_u32(&(header[ i ]));
00401     }
00402 #endif
00403 
00404     /* Prepare the data. */
00405     switch (attrs->colorspace)
00406     {
00407         case JIFF_RGB:
00408             num_channels = 3;
00409             break;
00410         case JIFF_GRAY:
00411             num_channels = 1;
00412             break;
00413         default:
00414             abort();
00415     }
00416 
00417     switch (attrs->depth)
00418     {
00419         case JIFF_8_BIT:
00420             channel_bytes = 1;
00421             break;
00422         case JIFF_16_BIT:
00423             channel_bytes = 2;
00424             break;
00425         case JIFF_32_BIT:
00426             channel_bytes = 4;
00427             break;
00428         default:
00429             abort();
00430     }
00431     
00432     num_elts = img->num_rows*img->num_cols*num_channels;
00433     assert(data = malloc(channel_bytes*num_elts));
00434 
00435     elts = (float*)*(img->pxls);
00436     pxls = *(img->pxls);
00437 
00438     if (attrs->colorspace == JIFF_RGB)
00439     {
00440         for (elt = 0; elt < num_elts; elt += 3)
00441         {
00442             red   = elts[ elt+0 ];
00443             green = elts[ elt+1 ];
00444             blue  = elts[ elt+2 ];
00445 
00446             if (attrs->type == JIFF_FLOAT)
00447             {
00448                 ((float*)data)[ elt+0 ] = red;
00449                 ((float*)data)[ elt+1 ] = green;
00450                 ((float*)data)[ elt+2 ] = blue;
00451             }
00452             else if (attrs->depth == JIFF_8_BIT)
00453             {
00454                 ((uint8_t*)data)[ elt+0 ] = (uint8_t)(red * 0xFF);
00455                 ((uint8_t*)data)[ elt+1 ] = (uint8_t)(green * 0xFF);
00456                 ((uint8_t*)data)[ elt+2 ] = (uint8_t)(blue * 0xFF);
00457             }
00458             else if (attrs->depth == JIFF_16_BIT)
00459             {
00460                 ((uint16_t*)data)[ elt+0 ] = (uint16_t)(red * 0xFFFF);
00461                 ((uint16_t*)data)[ elt+1 ] = (uint16_t)(green * 0xFFFF);
00462                 ((uint16_t*)data)[ elt+2 ] = (uint16_t)(blue * 0xFFFF);
00463             }
00464             else if (attrs->depth == JIFF_32_BIT)
00465             {
00466                 ((uint32_t*)data)[ elt+0 ] = (uint32_t)(red * 0xFFFFFFFF);
00467                 ((uint32_t*)data)[ elt+1 ] = (uint32_t)(green * 0xFFFFFFFF);
00468                 ((uint32_t*)data)[ elt+2 ] = (uint32_t)(blue * 0xFFFFFFFF);
00469             }
00470             else
00471             {
00472                 abort();
00473             }
00474         }
00475     }
00476     else if (attrs->colorspace == JIFF_GRAY)
00477     {
00478         for (elt = 0; elt < num_elts; elt++)
00479         {
00480             gray = attrs->red_w   * pxls[ elt ].r + 
00481                    attrs->green_w * pxls[ elt ].g + 
00482                    attrs->blue_w  * pxls[ elt ].b;
00483 
00484             if (attrs->type == JIFF_FLOAT)
00485             {
00486                 ((float*)data)[ elt ]  = gray;
00487             }
00488             else if (attrs->depth == JIFF_8_BIT)
00489             {
00490                 ((uint8_t*)data)[ elt ]  = (uint8_t)(gray * 0xFF);
00491             }
00492             else if (attrs->depth == JIFF_16_BIT)
00493             {
00494                 ((uint16_t*)data)[ elt ]  = (uint16_t)(gray * 0xFFFF);
00495             }
00496             else if (attrs->depth == JIFF_32_BIT)
00497             {
00498                 ((uint32_t*)data)[ elt ]  = (uint32_t)(gray * 0xFFFFFFFF);
00499             }
00500             else
00501             {
00502                 abort();
00503             }
00504         }
00505     }
00506     else
00507     {
00508         abort();
00509     }
00510 
00511 #ifndef JWSC_BIGENDIAN
00512     if (attrs->depth != JIFF_8_BIT)
00513     {
00514         for (elt = 0; elt < num_elts; elt++)
00515         {
00516             switch(attrs->depth)
00517             {
00518                 case JIFF_16_BIT:
00519                     bswap_u16(&(((uint16_t*)data)[ elt ]));
00520                     break;
00521                 case JIFF_32_BIT:
00522                     bswap_u32(&(((uint32_t*)data)[ elt ]));
00523                     break;
00524                 default:
00525                     abort();
00526             }
00527         }
00528     }
00529 #endif
00530 
00531 
00532     if (!(fp = fopen(fname, "w")))
00533     {
00534         free(data);
00535         return JWSC_EIO("Could not open jiff file");
00536     }
00537 
00538     if (fwrite(header, 4, HEADER_SIZE, fp) != HEADER_SIZE)
00539     {
00540         free(data);
00541         fclose(fp);
00542         return JWSC_EIO("Could not write jiff header");
00543     }
00544 
00545     if (fwrite(data, channel_bytes, num_elts, fp) != num_elts)
00546     {
00547         free(data);
00548         fclose(fp);
00549         return JWSC_EIO("Could not write jiff data");
00550     }
00551 
00552     free(data);
00553     fclose(fp);
00554 
00555     return NULL;
00556 }