00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <stdio.h>
00013 #include <malloc.h>
00014 #include "pngu.h"
00015 #include "png.h"
00016
00017
00018
00019 #define PNGU_SOURCE_BUFFER 1
00020 #define PNGU_SOURCE_DEVICE 2
00021
00022
00023
00024 int pngu_info (IMGCTX ctx);
00025 int pngu_decode (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, PNGU_u32 stripAlpha);
00026 void pngu_free_info (IMGCTX ctx);
00027 void pngu_read_data_from_buffer (png_structp png_ptr, png_bytep data, png_size_t length);
00028 void pngu_write_data_to_buffer (png_structp png_ptr, png_bytep data, png_size_t length);
00029 void pngu_flush_data_to_buffer (png_structp png_ptr);
00030 int pngu_clamp (int value, int min, int max);
00031
00032
00033
00034 struct _IMGCTX
00035 {
00036 int source;
00037 void *buffer;
00038 char *filename;
00039 PNGU_u32 cursor;
00040
00041 PNGU_u32 propRead;
00042 PNGUPROP prop;
00043
00044 PNGU_u32 infoRead;
00045 png_structp png_ptr;
00046 png_infop info_ptr;
00047 FILE *fd;
00048
00049 png_bytep *row_pointers;
00050 png_bytep img_data;
00051 };
00052
00053
00054
00055
00056 IMGCTX PNGU_SelectImageFromBuffer (const void *buffer)
00057 {
00058 IMGCTX ctx = NULL;
00059
00060 if (!buffer)
00061 return NULL;
00062
00063 ctx = malloc (sizeof (struct _IMGCTX));
00064 if (!ctx)
00065 return NULL;
00066
00067 ctx->buffer = (void *) buffer;
00068 ctx->source = PNGU_SOURCE_BUFFER;
00069 ctx->cursor = 0;
00070 ctx->filename = NULL;
00071 ctx->propRead = 0;
00072 ctx->infoRead = 0;
00073
00074 return ctx;
00075 }
00076
00077
00078 IMGCTX PNGU_SelectImageFromDevice (const char *filename)
00079 {
00080 IMGCTX ctx = NULL;
00081
00082 if (!filename)
00083 return NULL;
00084
00085 ctx = malloc (sizeof (struct _IMGCTX));
00086 if (!ctx)
00087 return NULL;
00088
00089 ctx->buffer = NULL;
00090 ctx->source = PNGU_SOURCE_DEVICE;
00091 ctx->cursor = 0;
00092
00093 ctx->filename = malloc (strlen (filename) + 1);
00094 if (!ctx->filename)
00095 {
00096 free (ctx);
00097 return NULL;
00098 }
00099 strcpy(ctx->filename, filename);
00100
00101 ctx->propRead = 0;
00102 ctx->infoRead = 0;
00103
00104 return ctx;
00105 }
00106
00107
00108 void PNGU_ReleaseImageContext (IMGCTX ctx)
00109 {
00110 if (!ctx)
00111 return;
00112
00113 if (ctx->filename)
00114 free (ctx->filename);
00115
00116 if ((ctx->propRead) && (ctx->prop.trans))
00117 free (ctx->prop.trans);
00118
00119 pngu_free_info (ctx);
00120
00121 free (ctx);
00122 }
00123
00124
00125 int PNGU_GetImageProperties (IMGCTX ctx, PNGUPROP *imgprop)
00126 {
00127 int res;
00128
00129 if (!ctx->propRead)
00130 {
00131 res = pngu_info (ctx);
00132 if (res != PNGU_OK)
00133 return res;
00134 }
00135
00136 *imgprop = ctx->prop;
00137
00138 return PNGU_OK;
00139 }
00140
00141
00142 int PNGU_DecodeToYCbYCr (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride)
00143 {
00144 int result;
00145 PNGU_u32 x, y, buffWidth;
00146
00147
00148 if (width % 2)
00149 return PNGU_ODD_WIDTH;
00150
00151
00152 if (stride % 2)
00153 return PNGU_ODD_STRIDE;
00154
00155 result = pngu_decode (ctx, width, height, 1);
00156 if (result != PNGU_OK)
00157 return result;
00158
00159
00160 buffWidth = (width + stride) / 2;
00161 for (y = 0; y < height; y++)
00162 for (x = 0; x < (width / 2); x++)
00163 ((PNGU_u32 *)buffer)[y*buffWidth+x] = PNGU_RGB8_TO_YCbYCr (*(ctx->row_pointers[y]+x*6), *(ctx->row_pointers[y]+x*6+1), *(ctx->row_pointers[y]+x*6+2),
00164 *(ctx->row_pointers[y]+x*6+3), *(ctx->row_pointers[y]+x*6+4), *(ctx->row_pointers[y]+x*6+5));
00165
00166
00167 free (ctx->img_data);
00168 free (ctx->row_pointers);
00169
00170
00171 return PNGU_OK;
00172 }
00173
00174
00175 int PNGU_DecodeToRGB565 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride)
00176 {
00177 int result;
00178 PNGU_u32 x, y, buffWidth;
00179
00180 result = pngu_decode (ctx, width, height, 1);
00181 if (result != PNGU_OK)
00182 return result;
00183
00184 buffWidth = width + stride;
00185
00186
00187 for (y = 0; y < height; y++)
00188 for (x = 0; x < width; x++)
00189 ((PNGU_u16 *)buffer)[y*buffWidth+x] =
00190 (((PNGU_u16) (ctx->row_pointers[y][x*3] & 0xF8)) << 8) |
00191 (((PNGU_u16) (ctx->row_pointers[y][x*3+1] & 0xFC)) << 3) |
00192 (((PNGU_u16) (ctx->row_pointers[y][x*3+2] & 0xF8)) >> 3);
00193
00194
00195 free (ctx->img_data);
00196 free (ctx->row_pointers);
00197
00198
00199 return PNGU_OK;
00200 }
00201
00202
00203 int PNGU_DecodeToRGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride, PNGU_u8 default_alpha)
00204 {
00205 int result;
00206 PNGU_u32 x, y, buffWidth;
00207
00208 result = pngu_decode (ctx, width, height, 0);
00209 if (result != PNGU_OK)
00210 return result;
00211
00212 buffWidth = width + stride;
00213
00214
00215 if ( (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB_ALPHA) )
00216 {
00217
00218 for (y = 0; y < height; y++)
00219 memcpy (buffer + (y * buffWidth * 4), ctx->row_pointers[y], width * 4);
00220 }
00221 else
00222 {
00223
00224 for (y = 0; y < height; y++)
00225 for (x = 0; x < width; x++)
00226 ((PNGU_u32 *)buffer)[y*buffWidth+x] =
00227 (((PNGU_u32) ctx->row_pointers[y][x*3]) << 24) |
00228 (((PNGU_u32) ctx->row_pointers[y][x*3+1]) << 16) |
00229 (((PNGU_u32) ctx->row_pointers[y][x*3+2]) << 8) |
00230 ((PNGU_u32) default_alpha);
00231 }
00232
00233
00234 free (ctx->img_data);
00235 free (ctx->row_pointers);
00236
00237
00238 return PNGU_OK;
00239 }
00240
00241
00242 int PNGU_DecodeTo4x4RGB565 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer)
00243 {
00244 int result;
00245 PNGU_u32 x, y, qwidth, qheight;
00246
00247
00248 if ((width % 4) || (height % 4))
00249 return PNGU_INVALID_WIDTH_OR_HEIGHT;
00250
00251 result = pngu_decode (ctx, width, height, 1);
00252 if (result != PNGU_OK)
00253 return result;
00254
00255
00256 qwidth = width / 4;
00257 qheight = height / 4;
00258
00259 for (y = 0; y < qheight; y++)
00260 for (x = 0; x < qwidth; x++)
00261 {
00262 int blockbase = (y * qwidth + x) * 4;
00263
00264 PNGU_u64 field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4]+x*12));
00265 PNGU_u64 field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4]+x*12+8));
00266 ((PNGU_u64 *) buffer)[blockbase] =
00267 (((field64 & 0xF800000000000000ULL) | ((field64 & 0xFC000000000000ULL) << 3) | ((field64 & 0xF80000000000ULL) << 5)) |
00268 (((field64 & 0xF800000000ULL) << 8) | ((field64 & 0xFC000000ULL) << 11) | ((field64 & 0xF80000ULL) << 13)) |
00269 (((field64 & 0xF800ULL) << 16) | ((field64 & 0xFCULL) << 19) | ((field32 & 0xF8000000ULL) >> 11)) |
00270 (((field32 & 0xF80000ULL) >> 8) | ((field32 & 0xFC00ULL) >> 5) | ((field32 & 0xF8ULL) >> 3)));
00271
00272 field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4+1]+x*12));
00273 field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4+1]+x*12+8));
00274 ((PNGU_u64 *) buffer)[blockbase+1] =
00275 (((field64 & 0xF800000000000000ULL) | ((field64 & 0xFC000000000000ULL) << 3) | ((field64 & 0xF80000000000ULL) << 5)) |
00276 (((field64 & 0xF800000000ULL) << 8) | ((field64 & 0xFC000000ULL) << 11) | ((field64 & 0xF80000ULL) << 13)) |
00277 (((field64 & 0xF800ULL) << 16) | ((field64 & 0xFCULL) << 19) | ((field32 & 0xF8000000ULL) >> 11)) |
00278 (((field32 & 0xF80000ULL) >> 8) | ((field32 & 0xFC00ULL) >> 5) | ((field32 & 0xF8ULL) >> 3)));
00279
00280 field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4+2]+x*12));
00281 field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4+2]+x*12+8));
00282 ((PNGU_u64 *) buffer)[blockbase+2] =
00283 (((field64 & 0xF800000000000000ULL) | ((field64 & 0xFC000000000000ULL) << 3) | ((field64 & 0xF80000000000ULL) << 5)) |
00284 (((field64 & 0xF800000000ULL) << 8) | ((field64 & 0xFC000000ULL) << 11) | ((field64 & 0xF80000ULL) << 13)) |
00285 (((field64 & 0xF800ULL) << 16) | ((field64 & 0xFCULL) << 19) | ((field32 & 0xF8000000ULL) >> 11)) |
00286 (((field32 & 0xF80000ULL) >> 8) | ((field32 & 0xFC00ULL) >> 5) | ((field32 & 0xF8ULL) >> 3)));
00287
00288 field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4+3]+x*12));
00289 field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4+3]+x*12+8));
00290 ((PNGU_u64 *) buffer)[blockbase+3] =
00291 (((field64 & 0xF800000000000000ULL) | ((field64 & 0xFC000000000000ULL) << 3) | ((field64 & 0xF80000000000ULL) << 5)) |
00292 (((field64 & 0xF800000000ULL) << 8) | ((field64 & 0xFC000000ULL) << 11) | ((field64 & 0xF80000ULL) << 13)) |
00293 (((field64 & 0xF800ULL) << 16) | ((field64 & 0xFCULL) << 19) | ((field32 & 0xF8000000ULL) >> 11)) |
00294 (((field32 & 0xF80000ULL) >> 8) | ((field32 & 0xFC00ULL) >> 5) | ((field32 & 0xF8ULL) >> 3)));
00295 }
00296
00297
00298 free (ctx->img_data);
00299 free (ctx->row_pointers);
00300
00301
00302 return PNGU_OK;
00303 }
00304
00305
00306 int PNGU_DecodeTo4x4RGB5A3 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u8 default_alpha)
00307 {
00308 int result;
00309 PNGU_u32 x, y, qwidth, qheight;
00310 PNGU_u64 alphaMask;
00311
00312
00313 if ((width % 4) || (height % 4))
00314 return PNGU_INVALID_WIDTH_OR_HEIGHT;
00315
00316 result = pngu_decode (ctx, width, height, 0);
00317 if (result != PNGU_OK)
00318 return result;
00319
00320
00321 qwidth = width / 4;
00322 qheight = height / 4;
00323
00324
00325 if ( (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB_ALPHA) )
00326 {
00327
00328 for (y = 0; y < qheight; y++)
00329 for (x = 0; x < qwidth; x++)
00330 {
00331 int blockbase = (y * qwidth + x) * 4;
00332 PNGU_u64 tmp;
00333
00334 PNGU_u64 fieldA = *((PNGU_u64 *)(ctx->row_pointers[y*4]+x*16));
00335 PNGU_u64 fieldB = *((PNGU_u64 *)(ctx->row_pointers[y*4]+x*16+8));
00336
00337 if ((fieldA & 0xE000000000ULL) == 0xE000000000ULL)
00338 tmp = 0x8000000000000000ULL | ((fieldA & 0xF800000000000000ULL) >> 1) | ((fieldA & 0xF8000000000000ULL) << 2) | ((fieldA & 0xF80000000000ULL) << 5);
00339 else
00340 tmp = ((fieldA & 0xE000000000ULL) << 23) | ((fieldA & 0xF000000000000000ULL) >> 4) | (fieldA & 0xF0000000000000ULL) | ((fieldA & 0xF00000000000ULL) << 4);
00341
00342
00343 if ((fieldA & 0xE0ULL) == 0xE0ULL)
00344 tmp = tmp | 0x800000000000ULL | ((fieldA & 0xF8000000ULL) << 15) | ((fieldA & 0xF80000ULL) << 18) | ((fieldA & 0xF800ULL) << 21);
00345 else
00346 tmp = tmp | ((fieldA & 0xE0ULL) << 39) | ((fieldA & 0xF0000000ULL) << 12) | ((fieldA & 0xF00000ULL) << 16) | ((fieldA & 0xF000ULL) << 20);
00347
00348
00349 if ((fieldB & 0xE000000000ULL) == 0xE000000000ULL)
00350 tmp = tmp | 0x80000000ULL | ((fieldB & 0xF800000000000000ULL) >> 33) | ((fieldB & 0xF8000000000000ULL) >> 30) | ((fieldB & 0xF80000000000ULL) >> 27);
00351 else
00352 tmp = tmp | ((fieldB & 0xE000000000ULL) >> 9) | ((fieldB & 0xF000000000000000ULL) >> 36) | ((fieldB & 0xF0000000000000ULL) >> 32) | ((fieldB & 0xF00000000000ULL) >> 28);
00353
00354
00355 if ((fieldB & 0xE0ULL) == 0xE0ULL)
00356 tmp = tmp | 0x8000ULL | ((fieldB & 0xF8000000ULL) >> 17) | ((fieldB & 0xF80000ULL) >> 14) | ((fieldB & 0xF800ULL) >> 11);
00357 else
00358 tmp = tmp | ((fieldB & 0xE0ULL) << 7) | ((fieldB & 0xF0000000ULL) >> 20) | ((fieldB & 0xF00000ULL) >> 16) | ((fieldB & 0xF000ULL) >> 12);
00359 ((PNGU_u64 *) buffer)[blockbase] = tmp;
00360
00361 fieldA = *((PNGU_u64 *)(ctx->row_pointers[y*4+1]+x*16));
00362 fieldB = *((PNGU_u64 *)(ctx->row_pointers[y*4+1]+x*16+8));
00363 if ((fieldA & 0xE000000000ULL) == 0xE000000000ULL)
00364
00365 tmp = 0x8000000000000000ULL | ((fieldA & 0xF800000000000000ULL) >> 1) | ((fieldA & 0xF8000000000000ULL) << 2) | ((fieldA & 0xF80000000000ULL) << 5);
00366 else
00367
00368 tmp = ((fieldA & 0xE000000000ULL) << 23) | ((fieldA & 0xF000000000000000ULL) >> 4) | (fieldA & 0xF0000000000000ULL) | ((fieldA & 0xF00000000000ULL) << 4);
00369
00370 if ((fieldA & 0xE0ULL) == 0xE0ULL)
00371
00372 tmp = tmp | 0x800000000000ULL | ((fieldA & 0xF8000000ULL) << 15) | ((fieldA & 0xF80000ULL) << 18) | ((fieldA & 0xF800ULL) << 21);
00373 else
00374
00375 tmp = tmp | ((fieldA & 0xE0ULL) << 39) | ((fieldA & 0xF0000000ULL) << 12) | ((fieldA & 0xF00000ULL) << 16) | ((fieldA & 0xF000ULL) << 20);
00376
00377 if ((fieldB & 0xE000000000ULL) == 0xE000000000ULL)
00378
00379 tmp = tmp | 0x80000000ULL | ((fieldB & 0xF800000000000000ULL) >> 33) | ((fieldB & 0xF8000000000000ULL) >> 30) | ((fieldB & 0xF80000000000ULL) >> 27);
00380 else
00381
00382 tmp = tmp | ((fieldB & 0xE000000000ULL) >> 9) | ((fieldB & 0xF000000000000000ULL) >> 36) | ((fieldB & 0xF0000000000000ULL) >> 32) | ((fieldB & 0xF00000000000ULL) >> 28);
00383
00384 if ((fieldB & 0xE0ULL) == 0xE0ULL)
00385
00386 tmp = tmp | 0x8000ULL | ((fieldB & 0xF8000000ULL) >> 17) | ((fieldB & 0xF80000ULL) >> 14) | ((fieldB & 0xF800ULL) >> 11);
00387 else
00388
00389 tmp = tmp | ((fieldB & 0xE0ULL) << 7) | ((fieldB & 0xF0000000ULL) >> 20) | ((fieldB & 0xF00000ULL) >> 16) | ((fieldB & 0xF000ULL) >> 12);
00390 ((PNGU_u64 *) buffer)[blockbase+1] = tmp;
00391
00392 fieldA = *((PNGU_u64 *)(ctx->row_pointers[y*4+2]+x*16));
00393 fieldB = *((PNGU_u64 *)(ctx->row_pointers[y*4+2]+x*16+8));
00394 if ((fieldA & 0xE000000000ULL) == 0xE000000000ULL)
00395
00396 tmp = 0x8000000000000000ULL | ((fieldA & 0xF800000000000000ULL) >> 1) | ((fieldA & 0xF8000000000000ULL) << 2) | ((fieldA & 0xF80000000000ULL) << 5);
00397 else
00398
00399 tmp = ((fieldA & 0xE000000000ULL) << 23) | ((fieldA & 0xF000000000000000ULL) >> 4) | (fieldA & 0xF0000000000000ULL) | ((fieldA & 0xF00000000000ULL) << 4);
00400
00401 if ((fieldA & 0xE0ULL) == 0xE0ULL)
00402
00403 tmp = tmp | 0x800000000000ULL | ((fieldA & 0xF8000000ULL) << 15) | ((fieldA & 0xF80000ULL) << 18) | ((fieldA & 0xF800ULL) << 21);
00404 else
00405
00406 tmp = tmp | ((fieldA & 0xE0ULL) << 39) | ((fieldA & 0xF0000000ULL) << 12) | ((fieldA & 0xF00000ULL) << 16) | ((fieldA & 0xF000ULL) << 20);
00407
00408 if ((fieldB & 0xE000000000ULL) == 0xE000000000ULL)
00409
00410 tmp = tmp | 0x80000000ULL | ((fieldB & 0xF800000000000000ULL) >> 33) | ((fieldB & 0xF8000000000000ULL) >> 30) | ((fieldB & 0xF80000000000ULL) >> 27);
00411 else
00412
00413 tmp = tmp | ((fieldB & 0xE000000000ULL) >> 9) | ((fieldB & 0xF000000000000000ULL) >> 36) | ((fieldB & 0xF0000000000000ULL) >> 32) | ((fieldB & 0xF00000000000ULL) >> 28);
00414
00415 if ((fieldB & 0xE0ULL) == 0xE0ULL)
00416
00417 tmp = tmp | 0x8000ULL | ((fieldB & 0xF8000000ULL) >> 17) | ((fieldB & 0xF80000ULL) >> 14) | ((fieldB & 0xF800ULL) >> 11);
00418 else
00419
00420 tmp = tmp | ((fieldB & 0xE0ULL) << 7) | ((fieldB & 0xF0000000ULL) >> 20) | ((fieldB & 0xF00000ULL) >> 16) | ((fieldB & 0xF000ULL) >> 12);
00421 ((PNGU_u64 *) buffer)[blockbase+2] = tmp;
00422
00423 fieldA = *((PNGU_u64 *)(ctx->row_pointers[y*4+3]+x*16));
00424 fieldB = *((PNGU_u64 *)(ctx->row_pointers[y*4+3]+x*16+8));
00425 if ((fieldA & 0xE000000000ULL) == 0xE000000000ULL)
00426
00427 tmp = 0x8000000000000000ULL | ((fieldA & 0xF800000000000000ULL) >> 1) | ((fieldA & 0xF8000000000000ULL) << 2) | ((fieldA & 0xF80000000000ULL) << 5);
00428 else
00429
00430 tmp = ((fieldA & 0xE000000000ULL) << 23) | ((fieldA & 0xF000000000000000ULL) >> 4) | (fieldA & 0xF0000000000000ULL) | ((fieldA & 0xF00000000000ULL) << 4);
00431
00432 if ((fieldA & 0xE0ULL) == 0xE0ULL)
00433
00434 tmp = tmp | 0x800000000000ULL | ((fieldA & 0xF8000000ULL) << 15) | ((fieldA & 0xF80000ULL) << 18) | ((fieldA & 0xF800ULL) << 21);
00435 else
00436
00437 tmp = tmp | ((fieldA & 0xE0ULL) << 39) | ((fieldA & 0xF0000000ULL) << 12) | ((fieldA & 0xF00000ULL) << 16) | ((fieldA & 0xF000ULL) << 20);
00438
00439 if ((fieldB & 0xE000000000ULL) == 0xE000000000ULL)
00440
00441 tmp = tmp | 0x80000000ULL | ((fieldB & 0xF800000000000000ULL) >> 33) | ((fieldB & 0xF8000000000000ULL) >> 30) | ((fieldB & 0xF80000000000ULL) >> 27);
00442 else
00443
00444 tmp = tmp | ((fieldB & 0xE000000000ULL) >> 9) | ((fieldB & 0xF000000000000000ULL) >> 36) | ((fieldB & 0xF0000000000000ULL) >> 32) | ((fieldB & 0xF00000000000ULL) >> 28);
00445
00446 if ((fieldB & 0xE0ULL) == 0xE0ULL)
00447
00448 tmp = tmp | 0x8000ULL | ((fieldB & 0xF8000000ULL) >> 17) | ((fieldB & 0xF80000ULL) >> 14) | ((fieldB & 0xF800ULL) >> 11);
00449 else
00450
00451 tmp = tmp | ((fieldB & 0xE0ULL) << 7) | ((fieldB & 0xF0000000ULL) >> 20) | ((fieldB & 0xF00000ULL) >> 16) | ((fieldB & 0xF000ULL) >> 12);
00452 ((PNGU_u64 *) buffer)[blockbase+3] = tmp;
00453 }
00454 }
00455 else
00456 {
00457
00458 default_alpha = (default_alpha >> 5);
00459 if (default_alpha == 7)
00460 {
00461
00462 alphaMask = 0x8000800080008000ULL;
00463
00464 for (y = 0; y < qheight; y++)
00465 for (x = 0; x < qwidth; x++)
00466 {
00467 int blockbase = (y * qwidth + x) * 4;
00468
00469 PNGU_u64 field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4]+x*12));
00470 PNGU_u64 field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4]+x*12+8));
00471 ((PNGU_u64 *) buffer)[blockbase] =
00472 alphaMask | ((field64 & 0xF800000000000000ULL) >> 1) | ((field64 & 0xF8000000000000ULL) << 2) |
00473 ((field64 & 0xF80000000000ULL) << 5) | ((field64 & 0xF800000000ULL) << 7) | ((field64 & 0xF8000000ULL) << 10) |
00474 ((field64 & 0xF80000ULL) << 13) | ((field64 & 0xF800ULL) << 15) | ((field64 & 0xF8ULL) << 18) |
00475 ((field32 & 0xF8000000ULL) >> 11) | ((field32 & 0xF80000ULL) >> 9) | ((field32 & 0xF800ULL) >> 6) | ((field32 & 0xF8ULL) >> 3);
00476
00477 field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4+1]+x*12));
00478 field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4+1]+x*12+8));
00479 ((PNGU_u64 *) buffer)[blockbase+1] =
00480 alphaMask | ((field64 & 0xF800000000000000ULL) >> 1) | ((field64 & 0xF8000000000000ULL) << 2) |
00481 ((field64 & 0xF80000000000ULL) << 5) | ((field64 & 0xF800000000ULL) << 7) | ((field64 & 0xF8000000ULL) << 10) |
00482 ((field64 & 0xF80000ULL) << 13) | ((field64 & 0xF800ULL) << 15) | ((field64 & 0xF8ULL) << 18) |
00483 ((field32 & 0xF8000000ULL) >> 11) | ((field32 & 0xF80000ULL) >> 9) | ((field32 & 0xF800ULL) >> 6) | ((field32 & 0xF8ULL) >> 3);
00484
00485 field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4+2]+x*12));
00486 field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4+2]+x*12+8));
00487 ((PNGU_u64 *) buffer)[blockbase+2] =
00488 alphaMask | ((field64 & 0xF800000000000000ULL) >> 1) | ((field64 & 0xF8000000000000ULL) << 2) |
00489 ((field64 & 0xF80000000000ULL) << 5) | ((field64 & 0xF800000000ULL) << 7) | ((field64 & 0xF8000000ULL) << 10) |
00490 ((field64 & 0xF80000ULL) << 13) | ((field64 & 0xF800ULL) << 15) | ((field64 & 0xF8ULL) << 18) |
00491 ((field32 & 0xF8000000ULL) >> 11) | ((field32 & 0xF80000ULL) >> 9) | ((field32 & 0xF800ULL) >> 6) | ((field32 & 0xF8ULL) >> 3);
00492
00493 field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4+3]+x*12));
00494 field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4+3]+x*12+8));
00495 ((PNGU_u64 *) buffer)[blockbase+3] =
00496 alphaMask | ((field64 & 0xF800000000000000ULL) >> 1) | ((field64 & 0xF8000000000000ULL) << 2) |
00497 ((field64 & 0xF80000000000ULL) << 5) | ((field64 & 0xF800000000ULL) << 7) | ((field64 & 0xF8000000ULL) << 10) |
00498 ((field64 & 0xF80000ULL) << 13) | ((field64 & 0xF800ULL) << 15) | ((field64 & 0xF8ULL) << 18) |
00499 ((field32 & 0xF8000000ULL) >> 11) | ((field32 & 0xF80000ULL) >> 9) | ((field32 & 0xF800ULL) >> 6) | ((field32 & 0xF8ULL) >> 3);
00500 }
00501 }
00502 else
00503 {
00504
00505 default_alpha = (default_alpha << 4);
00506 alphaMask = (((PNGU_u64) default_alpha) << 56) | (((PNGU_u64) default_alpha) << 40) |
00507 (((PNGU_u64) default_alpha) << 24) | (((PNGU_u64) default_alpha) << 8);
00508
00509 for (y = 0; y < qheight; y++)
00510 for (x = 0; x < qwidth; x++)
00511 {
00512 int blockbase = (y * qwidth + x) * 4;
00513
00514 PNGU_u64 field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4]+x*12));
00515 PNGU_u64 field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4]+x*12+8));
00516 ((PNGU_u64 *) buffer)[blockbase] =
00517 alphaMask | ((field64 & 0xF000000000000000ULL) >> 4) | (field64 & 0xF0000000000000ULL) | ((field64 & 0xF00000000000ULL) << 4) |
00518 ((field64 & 0xF000000000ULL) << 4) | ((field64 & 0xF0000000ULL) << 8) | ((field64 & 0xF00000ULL) << 12) |
00519 ((field64 & 0xF000ULL) << 12) | ((field64 & 0xF0ULL) << 16) | ((field32 & 0xF0000000ULL) >> 12) |
00520 ((field32 & 0xF00000ULL) >> 12) | ((field32 & 0xF000ULL) >> 8) | ((field32 & 0xF0ULL) >> 4);
00521
00522 field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4+1]+x*12));
00523 field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4+1]+x*12+8));
00524 ((PNGU_u64 *) buffer)[blockbase+1] =
00525 alphaMask | ((field64 & 0xF000000000000000ULL) >> 4) | (field64 & 0xF0000000000000ULL) | ((field64 & 0xF00000000000ULL) << 4) |
00526 ((field64 & 0xF000000000ULL) << 4) | ((field64 & 0xF0000000ULL) << 8) | ((field64 & 0xF00000ULL) << 12) |
00527 ((field64 & 0xF000ULL) << 12) | ((field64 & 0xF0ULL) << 16) | ((field32 & 0xF0000000ULL) >> 12) |
00528 ((field32 & 0xF00000ULL) >> 12) | ((field32 & 0xF000ULL) >> 8) | ((field32 & 0xF0ULL) >> 4);
00529
00530 field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4+2]+x*12));
00531 field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4+2]+x*12+8));
00532 ((PNGU_u64 *) buffer)[blockbase+2] =
00533 alphaMask | ((field64 & 0xF000000000000000ULL) >> 4) | (field64 & 0xF0000000000000ULL) | ((field64 & 0xF00000000000ULL) << 4) |
00534 ((field64 & 0xF000000000ULL) << 4) | ((field64 & 0xF0000000ULL) << 8) | ((field64 & 0xF00000ULL) << 12) |
00535 ((field64 & 0xF000ULL) << 12) | ((field64 & 0xF0ULL) << 16) | ((field32 & 0xF0000000ULL) >> 12) |
00536 ((field32 & 0xF00000ULL) >> 12) | ((field32 & 0xF000ULL) >> 8) | ((field32 & 0xF0ULL) >> 4);
00537
00538 field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4+3]+x*12));
00539 field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4+3]+x*12+8));
00540 ((PNGU_u64 *) buffer)[blockbase+3] =
00541 alphaMask | ((field64 & 0xF000000000000000ULL) >> 4) | (field64 & 0xF0000000000000ULL) | ((field64 & 0xF00000000000ULL) << 4) |
00542 ((field64 & 0xF000000000ULL) << 4) | ((field64 & 0xF0000000ULL) << 8) | ((field64 & 0xF00000ULL) << 12) |
00543 ((field64 & 0xF000ULL) << 12) | ((field64 & 0xF0ULL) << 16) | ((field32 & 0xF0000000ULL) >> 12) |
00544 ((field32 & 0xF00000ULL) >> 12) | ((field32 & 0xF000ULL) >> 8) | ((field32 & 0xF0ULL) >> 4);
00545 }
00546 }
00547 }
00548
00549
00550 free (ctx->img_data);
00551 free (ctx->row_pointers);
00552
00553
00554 return PNGU_OK;
00555 }
00556
00557
00558 int PNGU_DecodeTo4x4RGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u8 default_alpha)
00559 {
00560 int result;
00561 PNGU_u32 x, y, qwidth, qheight;
00562 PNGU_u64 alphaMask;
00563
00564
00565 if ((width % 4) || (height % 4))
00566 return PNGU_INVALID_WIDTH_OR_HEIGHT;
00567
00568 result = pngu_decode (ctx, width, height, 0);
00569 if (result != PNGU_OK)
00570 return result;
00571
00572
00573 qwidth = width / 4;
00574 qheight = height / 4;
00575
00576
00577 if ( (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB_ALPHA) )
00578 {
00579
00580 for (y = 0; y < qheight; y++)
00581 for (x = 0; x < qwidth; x++)
00582 {
00583 int blockbase = (y * qwidth + x) * 8;
00584
00585 PNGU_u64 fieldA = *((PNGU_u64 *)(ctx->row_pointers[y*4]+x*16));
00586 PNGU_u64 fieldB = *((PNGU_u64 *)(ctx->row_pointers[y*4]+x*16+8));
00587 ((PNGU_u64 *) buffer)[blockbase] =
00588 ((fieldA & 0xFF00000000ULL) << 24) | ((fieldA & 0xFF00000000000000ULL) >> 8) |
00589 ((fieldA & 0xFFULL) << 40) | ((fieldA & 0xFF000000ULL) << 8) |
00590 ((fieldB & 0xFF00000000ULL) >> 8) | ((fieldB & 0xFF00000000000000ULL) >> 40) |
00591 ((fieldB & 0xFFULL) << 8) | ((fieldB & 0xFF000000ULL) >> 24);
00592 ((PNGU_u64 *) buffer)[blockbase+4] =
00593 ((fieldA & 0xFFFF0000000000ULL) << 8) | ((fieldA & 0xFFFF00ULL) << 24) |
00594 ((fieldB & 0xFFFF0000000000ULL) >> 24) | ((fieldB & 0xFFFF00ULL) >> 8);
00595
00596 fieldA = *((PNGU_u64 *)(ctx->row_pointers[y*4+1]+x*16));
00597 fieldB = *((PNGU_u64 *)(ctx->row_pointers[y*4+1]+x*16+8));
00598 ((PNGU_u64 *) buffer)[blockbase+1] =
00599 ((fieldA & 0xFF00000000ULL) << 24) | ((fieldA & 0xFF00000000000000ULL) >> 8) |
00600 ((fieldA & 0xFFULL) << 40) | ((fieldA & 0xFF000000ULL) << 8) |
00601 ((fieldB & 0xFF00000000ULL) >> 8) | ((fieldB & 0xFF00000000000000ULL) >> 40) |
00602 ((fieldB & 0xFFULL) << 8) | ((fieldB & 0xFF000000ULL) >> 24);
00603 ((PNGU_u64 *) buffer)[blockbase+5] =
00604 ((fieldA & 0xFFFF0000000000ULL) << 8) | ((fieldA & 0xFFFF00ULL) << 24) |
00605 ((fieldB & 0xFFFF0000000000ULL) >> 24) | ((fieldB & 0xFFFF00ULL) >> 8);
00606
00607 fieldA = *((PNGU_u64 *)(ctx->row_pointers[y*4+2]+x*16));
00608 fieldB = *((PNGU_u64 *)(ctx->row_pointers[y*4+2]+x*16+8));
00609 ((PNGU_u64 *) buffer)[blockbase+2] =
00610 ((fieldA & 0xFF00000000ULL) << 24) | ((fieldA & 0xFF00000000000000ULL) >> 8) |
00611 ((fieldA & 0xFFULL) << 40) | ((fieldA & 0xFF000000ULL) << 8) |
00612 ((fieldB & 0xFF00000000ULL) >> 8) | ((fieldB & 0xFF00000000000000ULL) >> 40) |
00613 ((fieldB & 0xFFULL) << 8) | ((fieldB & 0xFF000000ULL) >> 24);
00614 ((PNGU_u64 *) buffer)[blockbase+6] =
00615 ((fieldA & 0xFFFF0000000000ULL) << 8) | ((fieldA & 0xFFFF00ULL) << 24) |
00616 ((fieldB & 0xFFFF0000000000ULL) >> 24) | ((fieldB & 0xFFFF00ULL) >> 8);
00617
00618 fieldA = *((PNGU_u64 *)(ctx->row_pointers[y*4+3]+x*16));
00619 fieldB = *((PNGU_u64 *)(ctx->row_pointers[y*4+3]+x*16+8));
00620 ((PNGU_u64 *) buffer)[blockbase+3] =
00621 ((fieldA & 0xFF00000000ULL) << 24) | ((fieldA & 0xFF00000000000000ULL) >> 8) |
00622 ((fieldA & 0xFFULL) << 40) | ((fieldA & 0xFF000000ULL) << 8) |
00623 ((fieldB & 0xFF00000000ULL) >> 8) | ((fieldB & 0xFF00000000000000ULL) >> 40) |
00624 ((fieldB & 0xFFULL) << 8) | ((fieldB & 0xFF000000ULL) >> 24);
00625 ((PNGU_u64 *) buffer)[blockbase+7] =
00626 ((fieldA & 0xFFFF0000000000ULL) << 8) | ((fieldA & 0xFFFF00ULL) << 24) |
00627 ((fieldB & 0xFFFF0000000000ULL) >> 24) | ((fieldB & 0xFFFF00ULL) >> 8);
00628 }
00629 }
00630 else
00631 {
00632
00633 alphaMask = (((PNGU_u64)default_alpha) << 56) | (((PNGU_u64)default_alpha) << 40) |
00634 (((PNGU_u64)default_alpha) << 24) | (((PNGU_u64)default_alpha) << 8);
00635
00636 for (y = 0; y < qheight; y++)
00637 for (x = 0; x < qwidth; x++)
00638 {
00639 int blockbase = (y * qwidth + x) * 8;
00640
00641 PNGU_u64 field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4]+x*12));
00642 PNGU_u64 field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4]+x*12+8));
00643 ((PNGU_u64 *) buffer)[blockbase] =
00644 (((field64 & 0xFF00000000000000ULL) >> 8) | (field64 & 0xFF00000000ULL) |
00645 ((field64 & 0xFF00ULL) << 8) | ((field32 & 0xFF0000ULL) >> 16) | alphaMask);
00646 ((PNGU_u64 *) buffer)[blockbase+4] =
00647 (((field64 & 0xFFFF0000000000ULL) << 8) | ((field64 & 0xFFFF0000ULL) << 16) |
00648 ((field64 & 0xFFULL) << 24) | ((field32 & 0xFF000000ULL) >> 8) | (field32 & 0xFFFFULL));
00649
00650 field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4+1]+x*12));
00651 field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4+1]+x*12+8));
00652 ((PNGU_u64 *) buffer)[blockbase+1] =
00653 (((field64 & 0xFF00000000000000ULL) >> 8) | (field64 & 0xFF00000000ULL) |
00654 ((field64 & 0xFF00ULL) << 8) | ((field32 & 0xFF0000ULL) >> 16) | alphaMask);
00655 ((PNGU_u64 *) buffer)[blockbase+5] =
00656 (((field64 & 0xFFFF0000000000ULL) << 8) | ((field64 & 0xFFFF0000ULL) << 16) |
00657 ((field64 & 0xFFULL) << 24) | ((field32 & 0xFF000000ULL) >> 8) | (field32 & 0xFFFFULL));
00658
00659 field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4+2]+x*12));
00660 field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4+2]+x*12+8));
00661 ((PNGU_u64 *) buffer)[blockbase+2] =
00662 (((field64 & 0xFF00000000000000ULL) >> 8) | (field64 & 0xFF00000000ULL) |
00663 ((field64 & 0xFF00ULL) << 8) | ((field32 & 0xFF0000ULL) >> 16) | alphaMask);
00664 ((PNGU_u64 *) buffer)[blockbase+6] =
00665 (((field64 & 0xFFFF0000000000ULL) << 8) | ((field64 & 0xFFFF0000ULL) << 16) |
00666 ((field64 & 0xFFULL) << 24) | ((field32 & 0xFF000000ULL) >> 8) | (field32 & 0xFFFFULL));
00667
00668 field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4+3]+x*12));
00669 field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4+3]+x*12+8));
00670 ((PNGU_u64 *) buffer)[blockbase+3] =
00671 (((field64 & 0xFF00000000000000ULL) >> 8) | (field64 & 0xFF00000000ULL) |
00672 ((field64 & 0xFF00ULL) << 8) | ((field32 & 0xFF0000ULL) >> 16) | alphaMask);
00673 ((PNGU_u64 *) buffer)[blockbase+7] =
00674 (((field64 & 0xFFFF0000000000ULL) << 8) | ((field64 & 0xFFFF0000ULL) << 16) |
00675 ((field64 & 0xFFULL) << 24) | ((field32 & 0xFF000000ULL) >> 8) | (field32 & 0xFFFFULL));
00676 }
00677 }
00678
00679
00680 free (ctx->img_data);
00681 free (ctx->row_pointers);
00682
00683
00684 return PNGU_OK;
00685 }
00686
00687
00688 int PNGU_EncodeFromYCbYCr (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride)
00689 {
00690 png_uint_32 rowbytes;
00691 PNGU_u32 x, y, buffWidth;
00692
00693
00694 pngu_free_info (ctx);
00695 ctx->propRead = 0;
00696
00697
00698 if (ctx->source == PNGU_SOURCE_BUFFER);
00699
00700 else if (ctx->source == PNGU_SOURCE_DEVICE)
00701 {
00702
00703 if (!(ctx->fd = fopen (ctx->filename, "wb")))
00704 return PNGU_CANT_OPEN_FILE;
00705 }
00706
00707 else
00708 return PNGU_NO_FILE_SELECTED;
00709
00710
00711 ctx->png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
00712 if (!(ctx->png_ptr))
00713 {
00714 if (ctx->source == PNGU_SOURCE_DEVICE)
00715 fclose (ctx->fd);
00716 return PNGU_LIB_ERROR;
00717 }
00718
00719 ctx->info_ptr = png_create_info_struct (ctx->png_ptr);
00720 if (!(ctx->info_ptr))
00721 {
00722 png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL);
00723 if (ctx->source == PNGU_SOURCE_DEVICE)
00724 fclose (ctx->fd);
00725 return PNGU_LIB_ERROR;
00726 }
00727
00728 if (ctx->source == PNGU_SOURCE_BUFFER)
00729 {
00730
00731 ctx->cursor = 0;
00732 png_set_write_fn (ctx->png_ptr, ctx, pngu_write_data_to_buffer, pngu_flush_data_to_buffer);
00733 }
00734 else if (ctx->source == PNGU_SOURCE_DEVICE)
00735 {
00736
00737 png_init_io (ctx->png_ptr, ctx->fd);
00738 }
00739
00740
00741 png_set_IHDR (ctx->png_ptr, ctx->info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB,
00742 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
00743
00744
00745 rowbytes = width * 3;
00746 if (rowbytes % 4)
00747 rowbytes = ((rowbytes / 4) + 1) * 4;
00748
00749 ctx->img_data = malloc (rowbytes * height);
00750 if (!ctx->img_data)
00751 {
00752 png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL);
00753 if (ctx->source == PNGU_SOURCE_DEVICE)
00754 fclose (ctx->fd);
00755 return PNGU_LIB_ERROR;
00756 }
00757
00758 ctx->row_pointers = malloc (sizeof (png_bytep) * height);
00759 if (!ctx->row_pointers)
00760 {
00761 png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL);
00762 if (ctx->source == PNGU_SOURCE_DEVICE)
00763 fclose (ctx->fd);
00764 return PNGU_LIB_ERROR;
00765 }
00766
00767
00768 buffWidth = (width + stride) / 2;
00769 for (y = 0; y < height; y++)
00770 {
00771 ctx->row_pointers[y] = ctx->img_data + (y * rowbytes);
00772
00773 for (x = 0; x < (width / 2); x++)
00774 PNGU_YCbYCr_TO_RGB8 ( ((PNGU_u32 *)buffer)[y*buffWidth+x],
00775 ((PNGU_u8 *) ctx->row_pointers[y]+x*6), ((PNGU_u8 *) ctx->row_pointers[y]+x*6+1),
00776 ((PNGU_u8 *) ctx->row_pointers[y]+x*6+2), ((PNGU_u8 *) ctx->row_pointers[y]+x*6+3),
00777 ((PNGU_u8 *) ctx->row_pointers[y]+x*6+4), ((PNGU_u8 *) ctx->row_pointers[y]+x*6+5) );
00778 }
00779
00780
00781 png_set_rows (ctx->png_ptr, ctx->info_ptr, ctx->row_pointers);
00782
00783
00784 png_write_png (ctx->png_ptr, ctx->info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
00785
00786
00787 png_write_end (ctx->png_ptr, (png_infop) NULL);
00788
00789
00790 free (ctx->img_data);
00791 free (ctx->row_pointers);
00792 png_destroy_write_struct (&(ctx->png_ptr), &(ctx->info_ptr));
00793 if (ctx->source == PNGU_SOURCE_DEVICE)
00794 fclose (ctx->fd);
00795
00796
00797 return PNGU_OK;
00798 }
00799
00800 int PNGU_EncodeFromRGB (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride)
00801 {
00802 png_uint_32 rowbytes;
00803 PNGU_u32 y;
00804
00805
00806 pngu_free_info (ctx);
00807 ctx->propRead = 0;
00808
00809
00810 if (ctx->source == PNGU_SOURCE_BUFFER);
00811
00812 else if (ctx->source == PNGU_SOURCE_DEVICE)
00813 {
00814
00815 if (!(ctx->fd = fopen (ctx->filename, "wb")))
00816 return PNGU_CANT_OPEN_FILE;
00817 }
00818
00819 else
00820 return PNGU_NO_FILE_SELECTED;
00821
00822
00823 ctx->png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
00824 if (!(ctx->png_ptr))
00825 {
00826 if (ctx->source == PNGU_SOURCE_DEVICE)
00827 fclose (ctx->fd);
00828 return PNGU_LIB_ERROR;
00829 }
00830
00831 ctx->info_ptr = png_create_info_struct (ctx->png_ptr);
00832 if (!(ctx->info_ptr))
00833 {
00834 png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL);
00835 if (ctx->source == PNGU_SOURCE_DEVICE)
00836 fclose (ctx->fd);
00837 return PNGU_LIB_ERROR;
00838 }
00839
00840 if (ctx->source == PNGU_SOURCE_BUFFER)
00841 {
00842
00843 ctx->cursor = 0;
00844 png_set_write_fn (ctx->png_ptr, ctx, pngu_write_data_to_buffer, pngu_flush_data_to_buffer);
00845 }
00846 else if (ctx->source == PNGU_SOURCE_DEVICE)
00847 {
00848
00849 png_init_io (ctx->png_ptr, ctx->fd);
00850 }
00851
00852
00853 png_set_IHDR (ctx->png_ptr, ctx->info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB,
00854 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
00855
00856
00857 rowbytes = width * 3;
00858 if (rowbytes % 4)
00859 rowbytes = ((rowbytes / 4) + 1) * 4;
00860
00861 ctx->img_data = malloc(rowbytes * height);
00862 memset(ctx->img_data, 0, rowbytes * height);
00863
00864 if (!ctx->img_data)
00865 {
00866 png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL);
00867 if (ctx->source == PNGU_SOURCE_DEVICE)
00868 fclose (ctx->fd);
00869 return PNGU_LIB_ERROR;
00870 }
00871
00872 ctx->row_pointers = malloc (sizeof (png_bytep) * height);
00873 memset(ctx->row_pointers, 0, sizeof (png_bytep) * height);
00874
00875 if (!ctx->row_pointers)
00876 {
00877 png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL);
00878 if (ctx->source == PNGU_SOURCE_DEVICE)
00879 fclose (ctx->fd);
00880 return PNGU_LIB_ERROR;
00881 }
00882
00883 for (y = 0; y < height; y++)
00884 {
00885 ctx->row_pointers[y] = buffer + (y * rowbytes);
00886 }
00887
00888
00889 png_set_rows (ctx->png_ptr, ctx->info_ptr, ctx->row_pointers);
00890
00891
00892 png_write_png (ctx->png_ptr, ctx->info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
00893
00894
00895 png_write_end (ctx->png_ptr, (png_infop) NULL);
00896
00897
00898 free (ctx->img_data);
00899 free (ctx->row_pointers);
00900 png_destroy_write_struct (&(ctx->png_ptr), &(ctx->info_ptr));
00901 if (ctx->source == PNGU_SOURCE_DEVICE)
00902 fclose (ctx->fd);
00903
00904
00905 return ctx->cursor;
00906 }
00907
00908 int PNGU_EncodeFromGXTexture (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride)
00909 {
00910 int x,y,res;
00911 unsigned char * ptr = (unsigned char*)buffer;
00912 unsigned char * tmpbuffer = (unsigned char *)malloc(width*height*3);
00913 memset(tmpbuffer, 0, width*height*3);
00914 png_uint_32 offset;
00915
00916 for(y=0; y < height; y++)
00917 {
00918 for(x=0; x < width; x++)
00919 {
00920 offset = (((y >> 2)<<4)*width) + ((x >> 2)<<6) + (((y%4 << 2) + x%4 ) << 1);
00921
00922 tmpbuffer[y*640*3+x*3] = ptr[offset+1];
00923 tmpbuffer[y*640*3+x*3+1] = ptr[offset+32];
00924 tmpbuffer[y*640*3+x*3+2] = ptr[offset+33];
00925 }
00926 }
00927
00928 res = PNGU_EncodeFromRGB (ctx, width, height, tmpbuffer, stride);
00929 free(tmpbuffer);
00930 return res;
00931 }
00932
00933
00934 PNGU_u32 PNGU_RGB8_TO_YCbYCr (PNGU_u8 r1, PNGU_u8 g1, PNGU_u8 b1, PNGU_u8 r2, PNGU_u8 g2, PNGU_u8 b2)
00935 {
00936 int y1, cb1, cr1, y2, cb2, cr2, cb, cr;
00937
00938 y1 = (299 * r1 + 587 * g1 + 114 * b1) / 1000;
00939 cb1 = (-16874 * r1 - 33126 * g1 + 50000 * b1 + 12800000) / 100000;
00940 cr1 = (50000 * r1 - 41869 * g1 - 8131 * b1 + 12800000) / 100000;
00941
00942 y2 = (299 * r2 + 587 * g2 + 114 * b2) / 1000;
00943 cb2 = (-16874 * r2 - 33126 * g2 + 50000 * b2 + 12800000) / 100000;
00944 cr2 = (50000 * r2 - 41869 * g2 - 8131 * b2 + 12800000) / 100000;
00945
00946 cb = (cb1 + cb2) >> 1;
00947 cr = (cr1 + cr2) >> 1;
00948
00949 return (PNGU_u32) ((y1 << 24) | (cb << 16) | (y2 << 8) | cr);
00950 }
00951
00952
00953 void PNGU_YCbYCr_TO_RGB8 (PNGU_u32 ycbycr, PNGU_u8 *r1, PNGU_u8 *g1, PNGU_u8 *b1, PNGU_u8 *r2, PNGU_u8 *g2, PNGU_u8 *b2)
00954 {
00955 PNGU_u8 *val = (PNGU_u8 *) &ycbycr;
00956 int r, g, b;
00957
00958 r = 1.371f * (val[3] - 128);
00959 g = - 0.698f * (val[3] - 128) - 0.336f * (val[1] - 128);
00960 b = 1.732f * (val[1] - 128);
00961
00962 *r1 = pngu_clamp (val[0] + r, 0, 255);
00963 *g1 = pngu_clamp (val[0] + g, 0, 255);
00964 *b1 = pngu_clamp (val[0] + b, 0, 255);
00965
00966 *r2 = pngu_clamp (val[2] + r, 0, 255);
00967 *g2 = pngu_clamp (val[2] + g, 0, 255);
00968 *b2 = pngu_clamp (val[2] + b, 0, 255);
00969 }
00970
00971
00972 int pngu_info (IMGCTX ctx)
00973 {
00974 png_byte magic[8];
00975 png_uint_32 width;
00976 png_uint_32 height;
00977 png_color_16p background;
00978 png_bytep trans;
00979 png_color_16p trans_values;
00980 int scale, i;
00981
00982
00983 if (ctx->source == PNGU_SOURCE_BUFFER)
00984 memcpy (magic, ctx->buffer, 8);
00985
00986 else if (ctx->source == PNGU_SOURCE_DEVICE)
00987 {
00988
00989 if (!(ctx->fd = fopen (ctx->filename, "rb")))
00990 return PNGU_CANT_OPEN_FILE;
00991
00992
00993 if (fread (magic, 1, 8, ctx->fd) != 8)
00994 {
00995 fclose (ctx->fd);
00996 return PNGU_CANT_READ_FILE;
00997 }
00998 }
00999
01000 else
01001 return PNGU_NO_FILE_SELECTED;;
01002
01003 if (png_sig_cmp(magic, 0, 8) != 0)
01004 {
01005 if (ctx->source == PNGU_SOURCE_DEVICE)
01006 fclose (ctx->fd);
01007 return PNGU_FILE_IS_NOT_PNG;
01008 }
01009
01010
01011 ctx->png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
01012 if (!(ctx->png_ptr))
01013 {
01014 if (ctx->source == PNGU_SOURCE_DEVICE)
01015 fclose (ctx->fd);
01016 return PNGU_LIB_ERROR;
01017 }
01018
01019 ctx->info_ptr = png_create_info_struct (ctx->png_ptr);
01020 if (!(ctx->info_ptr))
01021 {
01022 if (ctx->source == PNGU_SOURCE_DEVICE)
01023 fclose (ctx->fd);
01024 png_destroy_read_struct (&(ctx->png_ptr), (png_infopp)NULL, (png_infopp)NULL);
01025 return PNGU_LIB_ERROR;
01026 }
01027
01028 if (ctx->source == PNGU_SOURCE_BUFFER)
01029 {
01030
01031 ctx->cursor = 0;
01032 png_set_read_fn (ctx->png_ptr, ctx, pngu_read_data_from_buffer);
01033 }
01034 else if (ctx->source == PNGU_SOURCE_DEVICE)
01035 {
01036
01037 png_init_io (ctx->png_ptr, ctx->fd);
01038 png_set_sig_bytes (ctx->png_ptr, 8);
01039 }
01040
01041
01042 png_read_info (ctx->png_ptr, ctx->info_ptr);
01043
01044
01045 if (!ctx->propRead)
01046 {
01047 png_get_IHDR(ctx->png_ptr, ctx->info_ptr, &width, &height,
01048 (int *) &(ctx->prop.imgBitDepth),
01049 (int *) &(ctx->prop.imgColorType),
01050 NULL, NULL, NULL);
01051
01052 ctx->prop.imgWidth = width;
01053 ctx->prop.imgHeight = height;
01054 switch (ctx->prop.imgColorType)
01055 {
01056 case PNG_COLOR_TYPE_GRAY:
01057 ctx->prop.imgColorType = PNGU_COLOR_TYPE_GRAY;
01058 break;
01059 case PNG_COLOR_TYPE_GRAY_ALPHA:
01060 ctx->prop.imgColorType = PNGU_COLOR_TYPE_GRAY_ALPHA;
01061 break;
01062 case PNG_COLOR_TYPE_PALETTE:
01063 ctx->prop.imgColorType = PNGU_COLOR_TYPE_PALETTE;
01064 break;
01065 case PNG_COLOR_TYPE_RGB:
01066 ctx->prop.imgColorType = PNGU_COLOR_TYPE_RGB;
01067 break;
01068 case PNG_COLOR_TYPE_RGB_ALPHA:
01069 ctx->prop.imgColorType = PNGU_COLOR_TYPE_RGB_ALPHA;
01070 break;
01071 default:
01072 ctx->prop.imgColorType = PNGU_COLOR_TYPE_UNKNOWN;
01073 break;
01074 }
01075
01076
01077 scale = 1;
01078 if (ctx->prop.imgBitDepth == 16)
01079 scale = 256;
01080
01081
01082 ctx->prop.validBckgrnd = 0;
01083 if (((ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB_ALPHA)) &&
01084 (png_get_bKGD (ctx->png_ptr, ctx->info_ptr, &background)))
01085 {
01086 ctx->prop.validBckgrnd = 1;
01087 ctx->prop.bckgrnd.r = background->red / scale;
01088 ctx->prop.bckgrnd.g = background->green / scale;
01089 ctx->prop.bckgrnd.b = background->blue / scale;
01090 }
01091 else if (((ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA)) &&
01092 (png_get_bKGD (ctx->png_ptr, ctx->info_ptr, &background)))
01093 {
01094 ctx->prop.validBckgrnd = 1;
01095 ctx->prop.bckgrnd.r = ctx->prop.bckgrnd.g = ctx->prop.bckgrnd.b = background->gray / scale;
01096 }
01097
01098
01099 ctx->prop.numTrans = 0;
01100 ctx->prop.trans = NULL;
01101 if (((ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB_ALPHA)) &&
01102 (png_get_tRNS (ctx->png_ptr, ctx->info_ptr, &trans, (int *) &(ctx->prop.numTrans), &trans_values)))
01103 {
01104 if (ctx->prop.numTrans)
01105 {
01106 ctx->prop.trans = malloc (sizeof (PNGUCOLOR) * ctx->prop.numTrans);
01107 if (ctx->prop.trans)
01108 for (i = 0; i < ctx->prop.numTrans; i++)
01109 {
01110 ctx->prop.trans[i].r = trans_values[i].red / scale;
01111 ctx->prop.trans[i].g = trans_values[i].green / scale;
01112 ctx->prop.trans[i].b = trans_values[i].blue / scale;
01113 }
01114 else
01115 ctx->prop.numTrans = 0;
01116 }
01117 }
01118 else if (((ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA)) &&
01119 (png_get_tRNS (ctx->png_ptr, ctx->info_ptr, &trans, (int *) &(ctx->prop.numTrans), &trans_values)))
01120 {
01121 if (ctx->prop.numTrans)
01122 {
01123 ctx->prop.trans = malloc (sizeof (PNGUCOLOR) * ctx->prop.numTrans);
01124 if (ctx->prop.trans)
01125 for (i = 0; i < ctx->prop.numTrans; i++)
01126 ctx->prop.trans[i].r = ctx->prop.trans[i].g = ctx->prop.trans[i].b =
01127 trans_values[i].gray / scale;
01128 else
01129 ctx->prop.numTrans = 0;
01130 }
01131 }
01132
01133 ctx->propRead = 1;
01134 }
01135
01136
01137 ctx->infoRead = 1;
01138
01139 return PNGU_OK;
01140 }
01141
01142
01143 int pngu_decode (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, PNGU_u32 stripAlpha)
01144 {
01145 png_uint_32 rowbytes;
01146 int i;
01147
01148
01149 if (!ctx->infoRead)
01150 {
01151 i = pngu_info (ctx);
01152 if (i != PNGU_OK)
01153 return i;
01154 }
01155
01156
01157 if ( (ctx->prop.imgWidth != width) || (ctx->prop.imgHeight != height) )
01158 return PNGU_INVALID_WIDTH_OR_HEIGHT;
01159
01160
01161 if ( (ctx->prop.imgColorType == PNGU_COLOR_TYPE_PALETTE) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_UNKNOWN) )
01162 return PNGU_UNSUPPORTED_COLOR_TYPE;
01163
01164
01165 if (ctx->prop.imgBitDepth == 16)
01166 png_set_strip_16 (ctx->png_ptr);
01167
01168
01169 if (stripAlpha && ((ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB_ALPHA) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA)))
01170 png_set_strip_alpha (ctx->png_ptr);
01171
01172
01173 if (ctx->prop.imgBitDepth < 8)
01174 png_set_packing (ctx->png_ptr);
01175
01176
01177 if ( (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA) )
01178 png_set_gray_to_rgb (ctx->png_ptr);
01179
01180
01181 png_read_update_info (ctx->png_ptr, ctx->info_ptr);
01182
01183
01184 rowbytes = png_get_rowbytes (ctx->png_ptr, ctx->info_ptr);
01185 if (rowbytes % 4)
01186 rowbytes = ((rowbytes / 4) + 1) * 4;
01187
01188 ctx->img_data = malloc (rowbytes * ctx->prop.imgHeight);
01189 if (!ctx->img_data)
01190 {
01191 pngu_free_info (ctx);
01192 return PNGU_LIB_ERROR;
01193 }
01194
01195 ctx->row_pointers = malloc (sizeof (png_bytep) * ctx->prop.imgHeight);
01196 if (!ctx->row_pointers)
01197 {
01198 free (ctx->img_data);
01199 pngu_free_info (ctx);
01200 return PNGU_LIB_ERROR;
01201 }
01202
01203 for (i = 0; i < ctx->prop.imgHeight; i++)
01204 ctx->row_pointers[i] = ctx->img_data + (i * rowbytes);
01205
01206
01207 png_read_image (ctx->png_ptr, ctx->row_pointers);
01208
01209
01210 pngu_free_info (ctx);
01211
01212
01213 return PNGU_OK;
01214 }
01215
01216
01217 void pngu_free_info (IMGCTX ctx)
01218 {
01219 if (ctx->infoRead)
01220 {
01221 if (ctx->source == PNGU_SOURCE_DEVICE)
01222 fclose (ctx->fd);
01223
01224 png_destroy_read_struct (&(ctx->png_ptr), &(ctx->info_ptr), (png_infopp)NULL);
01225
01226 ctx->infoRead = 0;
01227 }
01228 }
01229
01230
01231
01232 void pngu_read_data_from_buffer (png_structp png_ptr, png_bytep data, png_size_t length)
01233 {
01234 IMGCTX ctx = (IMGCTX) png_get_io_ptr (png_ptr);
01235 memcpy (data, ctx->buffer + ctx->cursor, length);
01236 ctx->cursor += length;
01237 }
01238
01239
01240
01241 void pngu_write_data_to_buffer (png_structp png_ptr, png_bytep data, png_size_t length)
01242 {
01243 IMGCTX ctx = (IMGCTX) png_get_io_ptr (png_ptr);
01244 memcpy (ctx->buffer + ctx->cursor, data, length);
01245 ctx->cursor += length;
01246 }
01247
01248
01249
01250 void pngu_flush_data_to_buffer (png_structp png_ptr)
01251 {
01252
01253 }
01254
01255
01256
01257 int pngu_clamp (int value, int min, int max)
01258 {
01259 if (value < min)
01260 value = min;
01261 else if (value > max)
01262 value = max;
01263
01264 return value;
01265 }
01266