00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifdef HAVE_CONFIG_H
00027 # include <config.h>
00028 #endif
00029
00030 #ifdef HAVE_PNG_H
00031
00032 #include <png.h>
00033 #include <setjmp.h>
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 int Import_png8
00044 (
00045 const char *pngname,
00046 int transp_index,
00047
00048 int& width, int& height,
00049 int& rowbytes,
00050
00051 int& xoff, int& yoff,
00052
00053
00054 unsigned char *& pixels,
00055 unsigned char *& palette,
00056
00057 int& pal_size
00058 )
00059 {
00060 pixels = 0;
00061
00062 FILE *fp = fopen(pngname, "rb");
00063 if (!fp)
00064 return (0);
00065 unsigned char sigbuf[4];
00066 if (fread(sigbuf, 1, sizeof(sigbuf), fp) != sizeof(sigbuf) ||
00067 png_sig_cmp(sigbuf, 0, sizeof(sigbuf)))
00068 {
00069 fclose(fp);
00070 return (0);
00071 }
00072
00073 png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING,
00074 0, 0, 0);
00075 if (!png)
00076 {
00077 fclose(fp);
00078 return (0);
00079 }
00080
00081 png_infop info = png_create_info_struct(png);
00082 if (setjmp(png->jmpbuf))
00083 {
00084 png_destroy_read_struct(&png, &info, 0);
00085 fclose(fp);
00086 return (0);
00087 }
00088 png_init_io(png, fp);
00089
00090 png_set_sig_bytes(png, sizeof(sigbuf));
00091 png_read_info(png, info);
00092 unsigned long w, h;
00093 int depth, color, interlace;
00094 png_get_IHDR(png, info, &w, &h, &depth, &color,
00095 &interlace, 0, 0);
00096 width = (int) w;
00097 height = (int) h;
00098 if (color != PNG_COLOR_TYPE_PALETTE)
00099 {
00100 png_destroy_read_struct(&png, &info, 0);
00101 fclose(fp);
00102 return (0);
00103 }
00104 if (depth < 8)
00105 png_set_packing(png);
00106 png_colorp pngpal;
00107 if (png_get_PLTE(png, info, &pngpal, &pal_size) != 0)
00108 palette = new unsigned char[3*pal_size];
00109 else
00110 {
00111 pal_size = 0;
00112 palette = 0;
00113 }
00114 int i;
00115 for (i = 0; i < pal_size; i++)
00116 {
00117 palette[3*i] = pngpal[i].red;
00118 palette[3*i + 1] = pngpal[i].green;
00119 palette[3*i + 2] = pngpal[i].blue;
00120 }
00121 png_int_32 pngxoff, pngyoff;
00122 int utype;
00123 if (png_get_oFFs(png, info, &pngxoff, &pngyoff, &utype) &&
00124 utype == PNG_OFFSET_PIXEL)
00125 {
00126 xoff = pngxoff;
00127 yoff = pngyoff;
00128 }
00129 else
00130 xoff = yoff = 0;
00131 png_bytep trans;
00132 int num_trans;
00133 png_color_16p trans_values;
00134 if (transp_index < 0 || transp_index > 255 || pal_size == 0 ||
00135 !png_get_tRNS(png, info, &trans, &num_trans, &trans_values))
00136 num_trans = 0;
00137
00138 png_read_update_info(png, info);
00139
00140 rowbytes = png_get_rowbytes(png, info);
00141 png_bytep image = new png_byte[height*rowbytes];
00142 pixels = image;
00143 png_bytep rowptr;
00144 int r;
00145 for (r = 0, rowptr = image; r < height; r++, rowptr += rowbytes)
00146 png_read_rows(png, &rowptr, 0, 1);
00147 png_read_end(png, info);
00148
00149 unsigned char *endptr = pixels + height*rowbytes;
00150 for (i = 0; i < num_trans; i++)
00151 {
00152 if (trans[i] != 0)
00153 continue;
00154
00155 for (unsigned char *ptr = pixels; ptr != endptr; ptr++)
00156 if (*ptr == i)
00157 *ptr = transp_index;
00158
00159 else if (*ptr > i)
00160 *ptr = *ptr - 1;
00161 if (i < pal_size - 1)
00162 memmove(palette + 3*i, palette + 3*(i + 1),
00163 3*pal_size - 3*(i + 1));
00164 pal_size--;
00165 }
00166
00167 png_destroy_read_struct(&png, &info, 0);
00168 fclose(fp);
00169 return (1);
00170 }
00171
00172
00173
00174
00175
00176
00177
00178
00179 int Export_png8
00180 (
00181 const char *pngname,
00182 int transp_index,
00183 int width, int height,
00184 int rowbytes,
00185
00186 int xoff, int yoff,
00187
00188 unsigned char *pixels,
00189 unsigned char *palette,
00190
00191 int pal_size,
00192 bool transp_to_0
00193
00194
00195 )
00196 {
00197
00198 FILE *fp = fopen(pngname, "wb");
00199 if (!fp)
00200 return (0);
00201
00202 png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING,
00203 0, 0, 0);
00204 if (!png)
00205 {
00206 fclose(fp);
00207 return (0);
00208 }
00209
00210 png_infop info = png_create_info_struct(png);
00211 if (setjmp(png->jmpbuf))
00212 {
00213 png_destroy_write_struct(&png, &info);
00214 fclose(fp);
00215 return (0);
00216 }
00217 png_init_io(png, fp);
00218 png_set_IHDR(png, info, width, height, 8, PNG_COLOR_TYPE_PALETTE,
00219 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
00220 PNG_FILTER_TYPE_DEFAULT);
00221 if (transp_index == 0)
00222 transp_to_0 = false;
00223 png_color pngpal[256];
00224 int rot = transp_to_0 ? (pal_size - transp_index) : 0;
00225 for (int i = 0; i < pal_size; i++)
00226 {
00227 int desti = (i + rot)%pal_size;
00228 pngpal[desti].red = palette[3*i];
00229 pngpal[desti].green = palette[3*i + 1];
00230 pngpal[desti].blue = palette[3*i + 2];
00231 }
00232 png_set_PLTE(png, info, &pngpal[0], pal_size);
00233 png_set_oFFs(png, info, xoff, yoff, PNG_OFFSET_PIXEL);
00234 if (transp_index >= 0 && transp_index < 256)
00235 {
00236 int tindex = transp_to_0 ? 0 : transp_index;
00237 png_byte trans[256];
00238 memset(&trans[0], 255, tindex);
00239 trans[(png_byte) tindex] = 0;
00240 png_set_tRNS(png, info, &trans[0], tindex + 1, 0);
00241 }
00242
00243 png_write_info(png, info);
00244 png_bytep rowptr;
00245 int r;
00246 for (r = 0, rowptr = pixels; r < height; r++, rowptr += rowbytes)
00247 {
00248 if (!transp_to_0)
00249 png_write_row(png, rowptr);
00250 else
00251 {
00252 unsigned char *tbuf = new unsigned char[rowbytes];
00253 for (int i = 0; i < rowbytes; i++)
00254 tbuf[i] = (rowptr[i] + rot)%pal_size;
00255 png_write_row(png, &tbuf[0]);
00256 delete [] tbuf;
00257 }
00258 }
00259 png_write_end(png, 0);
00260
00261 png_destroy_write_struct(&png, &info);
00262 fclose(fp);
00263 return (1);
00264 }
00265
00266
00267
00268
00269
00270
00271
00272
00273 int Import_png32
00274 (
00275 const char *pngname,
00276 int& width, int& height,
00277 int& rowbytes,
00278
00279 int& xoff, int& yoff,
00280
00281
00282 unsigned char *& pixels,
00283 bool bottom_first
00284
00285 )
00286 {
00287 pixels = 0;
00288
00289 FILE *fp = fopen(pngname, "rb");
00290 if (!fp)
00291 return (0);
00292 unsigned char sigbuf[4];
00293 if (fread(sigbuf, 1, sizeof(sigbuf), fp) != sizeof(sigbuf) ||
00294 png_sig_cmp(sigbuf, 0, sizeof(sigbuf)))
00295 {
00296 fclose(fp);
00297 return (0);
00298 }
00299
00300 png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING,
00301 0, 0, 0);
00302 if (!png)
00303 {
00304 fclose(fp);
00305 return (0);
00306 }
00307
00308 png_infop info = png_create_info_struct(png);
00309 if (setjmp(png->jmpbuf))
00310 {
00311 png_destroy_read_struct(&png, &info, 0);
00312 fclose(fp);
00313 return (0);
00314 }
00315 png_init_io(png, fp);
00316
00317 png_set_sig_bytes(png, sizeof(sigbuf));
00318 png_read_info(png, info);
00319 unsigned long w, h;
00320 int depth, color, interlace;
00321 png_get_IHDR(png, info, &w, &h, &depth, &color,
00322 &interlace, 0, 0);
00323 width = (int) w;
00324 height = (int) h;
00325 png_int_32 pngxoff, pngyoff;
00326 int utype;
00327 if (png_get_oFFs(png, info, &pngxoff, &pngyoff, &utype) &&
00328 utype == PNG_OFFSET_PIXEL)
00329 {
00330 xoff = pngxoff;
00331 yoff = pngyoff;
00332 }
00333 else
00334 xoff = yoff = 0;
00335 png_set_strip_16(png);
00336 if (color == PNG_COLOR_TYPE_PALETTE)
00337 png_set_expand(png);
00338 if (png_get_valid(png, info, PNG_INFO_tRNS))
00339 png_set_expand(png);
00340 else if (depth == 8 && color == PNG_COLOR_TYPE_RGB)
00341 png_set_filler(png, 0xff, PNG_FILLER_AFTER);
00342
00343 png_read_update_info(png, info);
00344
00345 rowbytes = png_get_rowbytes(png, info);
00346 png_bytep image = new png_byte[height*rowbytes];
00347 pixels = image;
00348 png_bytep rowptr = image;
00349 int r;
00350 int stride;
00351 if (bottom_first)
00352 {
00353 stride = -rowbytes;
00354 rowptr += (height - 1)*rowbytes;
00355 }
00356 else
00357 stride = rowbytes;
00358 for (int r = 0; r < height; r++, rowptr += stride)
00359 png_read_row(png, rowptr, 0);
00360 png_read_end(png, info);
00361
00362 png_destroy_read_struct(&png, &info, 0);
00363 fclose(fp);
00364 return (1);
00365 }
00366
00367 #endif
00368