|
- /*
- * libpipi Pathetic image processing interface library
- * Copyright (c) 2004-2008 Sam Hocevar <sam@zoy.org>
- * All Rights Reserved
- *
- * $Id$
- *
- * This library is free software. It comes without any warranty, to
- * the extent permitted by applicable law. You can redistribute it
- * and/or modify it under the terms of the Do What The Fuck You Want
- * To Public License, Version 2, as published by Sam Hocevar. See
- * http://sam.zoy.org/wtfpl/COPYING for more details.
- */
-
- /*
- * gdi.c: Windows GDI I/O functions (BMP only)
- */
-
- #include "config.h"
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- #include <windows.h>
-
- #include "pipi.h"
- #include "pipi_internals.h"
-
- pipi_image_t *pipi_load_gdi(const char *name)
- {
- BITMAPINFO binfo;
- pipi_image_t *img;
- pipi_pixels_t *p;
- uint8_t *data;
- HBITMAP hbmap;
- HDC hdc;
- int x, y;
-
- hbmap = (HBITMAP)LoadImage(NULL, name, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
- if(!hbmap)
- return NULL;
-
- hdc = CreateCompatibleDC(NULL);
- SelectObject(hdc, hbmap);
-
- memset(&binfo, 0, sizeof(binfo));
- binfo.bmiHeader.biSize = sizeof(binfo.bmiHeader);
- if(!GetDIBits(hdc, hbmap, 0, 0, 0, &binfo, DIB_RGB_COLORS))
- {
- ReleaseDC(0, hdc);
- DeleteObject(hbmap);
- return NULL;
- }
-
- img = pipi_new(binfo.bmiHeader.biWidth, binfo.bmiHeader.biHeight);
- p = pipi_getpixels(img, PIPI_PIXELS_RGBA_C);
- data = p->pixels;
-
- binfo.bmiHeader.biBitCount = 32;
- binfo.bmiHeader.biCompression = BI_RGB;
- binfo.bmiHeader.biHeight = - abs(binfo.bmiHeader.biHeight);
- if(!GetDIBits(hdc, hbmap, 0, abs(binfo.bmiHeader.biHeight), data,
- &binfo, DIB_RGB_COLORS))
- {
- ReleaseDC(0, hdc);
- DeleteObject(hbmap);
- return NULL;
- }
-
- /* FIXME: get rid of this loop, maybe by using BITMAPV4HEADER above
- * so that GDI reorders the pixels for us. */
- for(y = 0; y < img->h; y++)
- for(x = 0; x < img->w; x++)
- {
- /* Swap B and R, don't touch G and A. */
- uint8_t tmp = data[0]; data[0] = data[2]; data[2] = tmp;
- data += 4;
- }
-
- img->codec_priv = NULL;
-
- img->wrap = 0;
- img->u8 = 1;
-
- ReleaseDC(0, hdc);
- DeleteObject(hbmap);
-
- return img;
- }
-
- int pipi_save_gdi(pipi_image_t *img, const char *name)
- {
- BITMAPINFOHEADER binfo;
- BITMAPFILEHEADER bfheader;
- uint8_t dummy[4] = { 0 };
- HANDLE hfile;
- pipi_pixels_t *p;
- DWORD ret = 0;
- uint8_t *data;
- int x, y, padding;
-
- p = pipi_getpixels(img, PIPI_PIXELS_RGBA_C);
- data = p->pixels;
-
- padding = ((img->w * 3) + 3) / 4 * 4 - img->w * 3;
-
- memset(&binfo, 0, sizeof(binfo));
- binfo.biSize = sizeof(binfo);
- binfo.biWidth = img->w;
- binfo.biHeight = img->h;
- binfo.biPlanes = 1;
- binfo.biBitCount = 24;
- binfo.biCompression = BI_RGB;
- binfo.biSizeImage = (img->w * 3 + padding) * img->h;
-
- memset(&bfheader, 0, sizeof(bfheader));
- bfheader.bfType = 0x4D42;
- bfheader.bfOffBits = sizeof(bfheader) + sizeof(binfo);
- bfheader.bfSize = bfheader.bfOffBits + binfo.biSizeImage;
-
- /* We don’t even create the bitmap object, since we know exactly
- * what kind of file we are saving. But later, when we support
- * different depths and BMP options, we'll need to care about it. */
- hfile = CreateFile(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
- FILE_ATTRIBUTE_ARCHIVE, NULL);
- if(!hfile)
- return -1;
- WriteFile(hfile, &bfheader, sizeof(bfheader), &ret, NULL);
- WriteFile(hfile, &binfo, sizeof(binfo), &ret, NULL);
- for(y = 0; y < img->h; y++)
- {
- for(x = 0; x < img->w; x++)
- {
- uint8_t tmp[3];
- tmp[0] = data[4 * (img->w * (img->h - 1 - y) + x) + 2];
- tmp[1] = data[4 * (img->w * (img->h - 1 - y) + x) + 1];
- tmp[2] = data[4 * (img->w * (img->h - 1 - y) + x) + 0];
- WriteFile(hfile, tmp, 3, &ret, NULL);
- }
- if(padding)
- WriteFile(hfile, dummy, padding, &ret, NULL);
- }
- CloseHandle(hfile);
-
- return 0;
- }
-
- /*
- * XXX: The following functions are local.
- */
|