+//---------------------------------------------------------------------------------------------
+
+#define BMP_TORASTER_OFFSET 10
+#define BMP_SIZE_OFFSET 18
+#define BMP_BPP_OFFSET 28
+#define BMP_RLE_OFFSET 30
+#define BMP_COLOR_OFFSET 54
+
+#define fill4B(a) ((4 - ((a) % 4 )) & 0x03)
+
+struct color {
+ unsigned char red;
+ unsigned char green;
+ unsigned char blue;
+};
+
+static void fetch_pallete(int fd, struct color pallete[], int count)
+{
+ unsigned char buff[4];
+ lseek(fd, BMP_COLOR_OFFSET, SEEK_SET);
+ for (int i = 0; i < count; i++)
+ {
+ read(fd, buff, 4);
+ pallete[i].red = buff[2];
+ pallete[i].green = buff[1];
+ pallete[i].blue = buff[0];
+ }
+}
+
+static unsigned char *bmp_load(const char *file, int *x, int *y)
+{
+ unsigned char buff[4];
+ struct color pallete[256];
+
+ int fd = open(file, O_RDONLY);
+ if (fd == -1) return NULL;
+ if (lseek(fd, BMP_SIZE_OFFSET, SEEK_SET) == -1) return NULL;
+ read(fd, buff, 4);
+ *x = buff[0] + (buff[1] << 8) + (buff[2] << 16) + (buff[3] << 24);
+ read(fd, buff, 4);
+ *y = buff[0] + (buff[1] << 8) + (buff[2] << 16) + (buff[3] << 24);
+ if (lseek(fd, BMP_TORASTER_OFFSET, SEEK_SET) == -1) return NULL;
+ read(fd, buff, 4);
+ int raster = buff[0] + (buff[1] << 8) + (buff[2] << 16) + (buff[3] << 24);
+ if (lseek(fd, BMP_BPP_OFFSET, SEEK_SET) == -1) return NULL;
+ read(fd, buff, 2);
+ int bpp = buff[0] + (buff[1] << 8);
+
+ unsigned char *pic_buffer = new unsigned char[(*x) * (*y) * 3];
+ unsigned char *wr_buffer = pic_buffer + (*x) * ((*y) - 1) * 3;
+
+ switch (bpp)
+ {
+ case 4:
+ {
+ int skip = fill4B((*x) / 2 + (*x) % 2);
+ fetch_pallete(fd, pallete, 16);
+ lseek(fd, raster, SEEK_SET);
+ unsigned char * tbuffer = new unsigned char[*x / 2 + 1];
+ if (tbuffer == NULL)
+ return NULL;
+ for (int i = 0; i < *y; i++)
+ {
+ read(fd, tbuffer, (*x) / 2 + *x % 2);
+ int j;
+ for (j = 0; j < (*x) / 2; j++)
+ {
+ unsigned char c1 = tbuffer[j] >> 4;
+ unsigned char c2 = tbuffer[j] & 0x0f;
+ *wr_buffer++ = pallete[c1].red;
+ *wr_buffer++ = pallete[c1].green;
+ *wr_buffer++ = pallete[c1].blue;
+ *wr_buffer++ = pallete[c2].red;
+ *wr_buffer++ = pallete[c2].green;
+ *wr_buffer++ = pallete[c2].blue;
+ }
+ if ((*x) % 2)
+ {
+ unsigned char c1 = tbuffer[j] >> 4;
+ *wr_buffer++ = pallete[c1].red;
+ *wr_buffer++ = pallete[c1].green;
+ *wr_buffer++ = pallete[c1].blue;
+ }
+ if (skip)
+ read(fd, buff, skip);
+ wr_buffer -= (*x) * 6;
+ }
+ break;
+ }
+ case 8:
+ {
+ int skip = fill4B(*x);
+ fetch_pallete(fd, pallete, 256);
+ lseek(fd, raster, SEEK_SET);
+ unsigned char * tbuffer = new unsigned char[*x];
+ if (tbuffer == NULL)
+ return NULL;
+ for (int i = 0; i < *y; i++)
+ {
+ read(fd, tbuffer, *x);
+ for (int j = 0; j < *x; j++)
+ {
+ wr_buffer[j * 3] = pallete[tbuffer[j]].red;
+ wr_buffer[j * 3 + 1] = pallete[tbuffer[j]].green;
+ wr_buffer[j * 3 + 2] = pallete[tbuffer[j]].blue;
+ }
+ if (skip)
+ read(fd, buff, skip);
+ wr_buffer -= (*x) * 3;
+ }
+ break;
+ }
+ case 24:
+ {
+ int skip = fill4B((*x) * 3);
+ lseek(fd, raster, SEEK_SET);
+ for (int i = 0; i < (*y); i++)
+ {
+ read(fd, wr_buffer, (*x) * 3);
+ for (int j = 0; j < (*x) * 3 ; j = j + 3)
+ {
+ unsigned char c = wr_buffer[j];
+ wr_buffer[j] = wr_buffer[j + 2];
+ wr_buffer[j + 2] = c;
+ }
+ if (skip)
+ read(fd, buff, skip);
+ wr_buffer -= (*x) * 3;
+ }
+ break;
+ }
+ default:
+ return NULL;
+ }
+
+ close(fd);
+ return(pic_buffer);
+}
+
+//---------------------------------------------------------------------
+
+static unsigned char *png_load(const char *file, int *ox, int *oy)
+{
+ static const png_color_16 my_background = {0, 0, 0, 0, 0};
+
+ png_uint_32 width, height;
+ unsigned int i;
+ int bit_depth, color_type, interlace_type;
+ png_byte *fbptr;
+ FILE *fh;
+
+ if (!(fh = fopen(file, "rb")))
+ return NULL;
+
+ png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if (png_ptr == NULL)
+ return NULL;
+ png_infop info_ptr = png_create_info_struct(png_ptr);
+ if (info_ptr == NULL)
+ {
+ png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
+ fclose(fh);
+ return NULL;
+ }
+
+ if (setjmp(png_ptr->jmpbuf))
+ {
+ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
+ fclose(fh);
+ return NULL;
+ }
+
+ png_init_io(png_ptr, fh);
+
+ png_read_info(png_ptr, info_ptr);
+ png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL);
+
+ if ((color_type == PNG_COLOR_TYPE_PALETTE)||(color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)||(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)))
+ png_set_expand(png_ptr);
+ if (bit_depth == 16)
+ png_set_strip_16(png_ptr);
+ if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+ png_set_gray_to_rgb(png_ptr);
+
+ int number_passes = png_set_interlace_handling(png_ptr);
+ png_read_update_info(png_ptr, info_ptr);
+
+ if (width * 3 != png_get_rowbytes(png_ptr, info_ptr))
+ {
+ eDebug("[Picload] Error processing");
+ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
+ fclose(fh);
+ return NULL;
+ }
+
+ unsigned char *pic_buffer = new unsigned char[height * width * 3];
+ *ox=width;
+ *oy=height;
+
+ for(int pass = 0; pass < number_passes; pass++)
+ {
+ fbptr = (png_byte *)pic_buffer;
+ for (i = 0; i < height; i++, fbptr += width * 3)
+ png_read_row(png_ptr, fbptr, NULL);
+ }
+ png_read_end(png_ptr, info_ptr);
+ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
+ fclose(fh);
+ return(pic_buffer);
+}
+