JWS C Library
C language utility library
|
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 }