HRESULT WINAPI WICCreateImagingFactory_Proxy(UINT, IWICImagingFactory**);
#define PIXELFORMATBPP(x) ((x) ? ((x) >> 8) & 255 : 24)
+#define WMF_PLACEABLE_KEY 0x9ac6cdd7
static const struct
{
srcRect->Height = (REAL) ((GpBitmap*)image)->height;
*srcUnit = UnitPixel;
}
+ else{
+ WARN("GpImage with no image data\n");
+ return InvalidParameter;
+ }
TRACE("returning (%f, %f) (%f, %f) unit type %d\n", srcRect->X, srcRect->Y,
srcRect->Width, srcRect->Height, *srcUnit);
*height = ((GpBitmap*)image)->height;
*width = ((GpBitmap*)image)->width;
}
+ else{
+ WARN("GpImage with no image data\n");
+ return InvalidParameter;
+ }
TRACE("returning (%f, %f)\n", *height, *width);
return Ok;
*height = units_to_pixels(((GpMetafile*)image)->bounds.Height, ((GpMetafile*)image)->unit, image->yres);
else if(image->type == ImageTypeBitmap)
*height = ((GpBitmap*)image)->height;
+ else
+ {
+ WARN("GpImage with no image data\n");
+ return InvalidParameter;
+ }
TRACE("returning %d\n", *height);
*width = units_to_pixels(((GpMetafile*)image)->bounds.Width, ((GpMetafile*)image)->unit, image->xres);
else if(image->type == ImageTypeBitmap)
*width = ((GpBitmap*)image)->width;
+ else
+ {
+ WARN("GpImage with no image data\n");
+ return InvalidParameter;
+ }
TRACE("returning %d\n", *width);
static GpStatus load_wmf(IStream *stream, GpMetafile **metafile)
{
- GpStatus status = GenericError;
- HRESULT hr;
- UINT size;
- LARGE_INTEGER pos;
WmfPlaceableFileHeader pfh;
BOOL is_placeable = FALSE;
+ LARGE_INTEGER seek;
+ GpStatus status;
METAHEADER mh;
HMETAFILE hmf;
+ HRESULT hr;
+ UINT size;
void *buf;
- pos.QuadPart = 0;
- IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL);
-
hr = IStream_Read(stream, &mh, sizeof(mh), &size);
if (hr != S_OK || size != sizeof(mh))
return GenericError;
- if (mh.mtType == 0xcdd7 && mh.mtHeaderSize == 0x9ac6)
+ if (((WmfPlaceableFileHeader *)&mh)->Key == WMF_PLACEABLE_KEY)
{
- is_placeable = TRUE;
-
- pos.QuadPart = 0;
- IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL);
+ seek.QuadPart = 0;
+ hr = IStream_Seek(stream, seek, STREAM_SEEK_SET, NULL);
+ if (FAILED(hr)) return hresult_to_status(hr);
hr = IStream_Read(stream, &pfh, sizeof(pfh), &size);
if (hr != S_OK || size != sizeof(pfh))
hr = IStream_Read(stream, &mh, sizeof(mh), &size);
if (hr != S_OK || size != sizeof(mh))
return GenericError;
+
+ is_placeable = TRUE;
}
- pos.QuadPart = is_placeable ? sizeof(pfh) : 0;
- IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL);
+ seek.QuadPart = is_placeable ? sizeof(pfh) : 0;
+ hr = IStream_Seek(stream, seek, STREAM_SEEK_SET, NULL);
+ if (FAILED(hr)) return hresult_to_status(hr);
buf = heap_alloc(mh.mtSize * 2);
if (!buf) return OutOfMemory;
hr = IStream_Read(stream, buf, mh.mtSize * 2, &size);
- if (hr == S_OK && size == mh.mtSize * 2)
+ if (hr != S_OK || size != mh.mtSize * 2)
{
- hmf = SetMetaFileBitsEx(mh.mtSize * 2, buf);
- if (hmf)
- {
- status = GdipCreateMetafileFromWmf(hmf, TRUE, is_placeable ? &pfh : NULL, metafile);
- if (status != Ok)
- DeleteMetaFile(hmf);
- }
+ heap_free(buf);
+ return GenericError;
}
+ hmf = SetMetaFileBitsEx(mh.mtSize * 2, buf);
heap_free(buf);
+ if (!hmf)
+ return GenericError;
+
+ status = GdipCreateMetafileFromWmf(hmf, TRUE, is_placeable ? &pfh : NULL, metafile);
+ if (status != Ok)
+ DeleteMetaFile(hmf);
return status;
}
+static GpStatus decode_image_wmf(IStream *stream, GpImage **image)
+{
+ GpMetafile *metafile;
+ GpStatus status;
+
+ TRACE("%p %p\n", stream, image);
+
+ if (!stream || !image)
+ return InvalidParameter;
+
+ status = load_wmf(stream, &metafile);
+ if (status != Ok)
+ {
+ TRACE("Could not load metafile\n");
+ return status;
+ }
+
+ *image = (GpImage *)metafile;
+ TRACE("<-- %p\n", *image);
+
+ return Ok;
+}
+
static GpStatus load_emf(IStream *stream, GpMetafile **metafile)
{
- GpStatus status = GenericError;
- HRESULT hr;
- UINT size;
- LARGE_INTEGER pos;
+ LARGE_INTEGER seek;
ENHMETAHEADER emh;
HENHMETAFILE hemf;
+ GpStatus status;
+ HRESULT hr;
+ UINT size;
void *buf;
- pos.QuadPart = 0;
- IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL);
-
hr = IStream_Read(stream, &emh, sizeof(emh), &size);
if (hr != S_OK || size != sizeof(emh) || emh.dSignature != ENHMETA_SIGNATURE)
return GenericError;
- pos.QuadPart = 0;
- IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL);
+ seek.QuadPart = 0;
+ hr = IStream_Seek(stream, seek, STREAM_SEEK_SET, NULL);
+ if (FAILED(hr)) return hresult_to_status(hr);
buf = heap_alloc(emh.nBytes);
if (!buf) return OutOfMemory;
hr = IStream_Read(stream, buf, emh.nBytes, &size);
- if (hr == S_OK && size == emh.nBytes)
+ if (hr != S_OK || size != emh.nBytes)
{
- hemf = SetEnhMetaFileBits(emh.nBytes, buf);
- if (hemf)
- {
- status = GdipCreateMetafileFromEmf(hemf, FALSE, metafile);
- if (status != Ok)
- DeleteEnhMetaFile(hemf);
- }
+ heap_free(buf);
+ return GenericError;
}
+ hemf = SetEnhMetaFileBits(emh.nBytes, buf);
heap_free(buf);
+ if (!hemf)
+ return GenericError;
+
+ status = GdipCreateMetafileFromEmf(hemf, TRUE, metafile);
+ if (status != Ok)
+ DeleteEnhMetaFile(hemf);
return status;
}
-static GpStatus decode_image_metafile(IStream *stream, GpImage **image)
+static GpStatus decode_image_emf(IStream *stream, GpImage **image)
{
GpMetafile *metafile;
+ GpStatus status;
TRACE("%p %p\n", stream, image);
- if(!stream || !image)
+ if (!stream || !image)
return InvalidParameter;
- if (load_emf(stream, &metafile) != Ok && load_wmf(stream, &metafile) != Ok)
+ status = load_emf(stream, &metafile);
+ if (status != Ok)
{
TRACE("Could not load metafile\n");
- return GenericError;
+ return status;
}
*image = (GpImage *)metafile;
static GpStatus encode_image_gif(GpImage *image, IStream* stream,
GDIPCONST CLSID* clsid, GDIPCONST EncoderParameters* params)
{
- return encode_image_wic(image, stream, &CLSID_WICGifEncoder, params);
+ return encode_image_wic(image, stream, &GUID_ContainerFormatGif, params);
}
/*****************************************************************************
encode_image_func encode_image;
int i;
- TRACE("%p %p %p %p\n", image, stream, clsid, params);
+ TRACE("%p %p %s %p\n", image, stream, wine_dbgstr_guid(clsid), params);
if(!image || !stream)
return InvalidParameter;
/* SigMask */ emf_sig_mask,
},
NULL,
- decode_image_metafile,
+ decode_image_emf,
NULL
},
{
/* SigMask */ wmf_sig_mask,
},
NULL,
- decode_image_metafile,
+ decode_image_wmf,
NULL
},
{
*/
GpStatus WINGDIPAPI GdipImageSetAbort(GpImage *image, GdiplusAbort *pabort)
{
- FIXME("(%p, %p): stub\n", image, pabort);
- return NotImplemented;
+ TRACE("(%p, %p)\n", image, pabort);
+
+ if (!image)
+ return InvalidParameter;
+
+ if (pabort)
+ FIXME("Abort callback is not supported.\n");
+
+ return Ok;
}
/*****************************************************************************
FIXME("(%p, 0x%08x, %d, %d, %p, %f): stub\n", bitmap, format, dithertype, palettetype, palette, alphathreshold);
return NotImplemented;
}
+
+static void set_histogram_point_argb(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
+{
+ ch0[ color >> 24 ]++;
+ ch1[(color >> 16) & 0xff]++;
+ ch2[(color >> 8) & 0xff]++;
+ ch3[ color & 0xff]++;
+}
+
+static void set_histogram_point_pargb(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
+{
+ BYTE alpha = color >> 24;
+
+ ch0[alpha]++;
+ ch1[(((color >> 16) & 0xff) * alpha) / 0xff]++;
+ ch2[(((color >> 8) & 0xff) * alpha) / 0xff]++;
+ ch3[(( color & 0xff) * alpha) / 0xff]++;
+}
+
+static void set_histogram_point_rgb(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
+{
+ ch0[(color >> 16) & 0xff]++;
+ ch1[(color >> 8) & 0xff]++;
+ ch2[ color & 0xff]++;
+}
+
+static void set_histogram_point_gray(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
+{
+ ch0[(76 * ((color >> 16) & 0xff) + 150 * ((color >> 8) & 0xff) + 29 * (color & 0xff)) / 0xff]++;
+}
+
+static void set_histogram_point_b(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
+{
+ ch0[color & 0xff]++;
+}
+
+static void set_histogram_point_g(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
+{
+ ch0[(color >> 8) & 0xff]++;
+}
+
+static void set_histogram_point_r(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
+{
+ ch0[(color >> 16) & 0xff]++;
+}
+
+static void set_histogram_point_a(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
+{
+ ch0[(color >> 24) & 0xff]++;
+}
+
+/*****************************************************************************
+ * GdipBitmapGetHistogram [GDIPLUS.@]
+ */
+GpStatus WINGDIPAPI GdipBitmapGetHistogram(GpBitmap *bitmap, HistogramFormat format, UINT num_of_entries,
+ UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
+{
+ static void (* const set_histogram_point[])(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3) =
+ {
+ set_histogram_point_argb,
+ set_histogram_point_pargb,
+ set_histogram_point_rgb,
+ set_histogram_point_gray,
+ set_histogram_point_b,
+ set_histogram_point_g,
+ set_histogram_point_r,
+ set_histogram_point_a,
+ };
+ UINT width, height, x, y;
+
+ TRACE("(%p, %d, %u, %p, %p, %p, %p)\n", bitmap, format, num_of_entries,
+ ch0, ch1, ch2, ch3);
+
+ if (!bitmap || num_of_entries != 256)
+ return InvalidParameter;
+
+ /* Make sure passed channel pointers match requested format */
+ switch (format)
+ {
+ case HistogramFormatARGB:
+ case HistogramFormatPARGB:
+ if (!ch0 || !ch1 || !ch2 || !ch3)
+ return InvalidParameter;
+ memset(ch0, 0, num_of_entries * sizeof(UINT));
+ memset(ch1, 0, num_of_entries * sizeof(UINT));
+ memset(ch2, 0, num_of_entries * sizeof(UINT));
+ memset(ch3, 0, num_of_entries * sizeof(UINT));
+ break;
+ case HistogramFormatRGB:
+ if (!ch0 || !ch1 || !ch2 || ch3)
+ return InvalidParameter;
+ memset(ch0, 0, num_of_entries * sizeof(UINT));
+ memset(ch1, 0, num_of_entries * sizeof(UINT));
+ memset(ch2, 0, num_of_entries * sizeof(UINT));
+ break;
+ case HistogramFormatGray:
+ case HistogramFormatB:
+ case HistogramFormatG:
+ case HistogramFormatR:
+ case HistogramFormatA:
+ if (!ch0 || ch1 || ch2 || ch3)
+ return InvalidParameter;
+ memset(ch0, 0, num_of_entries * sizeof(UINT));
+ break;
+ default:
+ WARN("Invalid histogram format requested, %d\n", format);
+ return InvalidParameter;
+ }
+
+ GdipGetImageWidth(&bitmap->image, &width);
+ GdipGetImageHeight(&bitmap->image, &height);
+
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++)
+ {
+ ARGB color;
+
+ GdipBitmapGetPixel(bitmap, x, y, &color);
+ set_histogram_point[format](color, ch0, ch1, ch2, ch3);
+ }
+
+ return Ok;
+}
+
+/*****************************************************************************
+ * GdipBitmapGetHistogramSize [GDIPLUS.@]
+ */
+GpStatus WINGDIPAPI GdipBitmapGetHistogramSize(HistogramFormat format, UINT *num_of_entries)
+{
+ TRACE("(%d, %p)\n", format, num_of_entries);
+
+ if (!num_of_entries)
+ return InvalidParameter;
+
+ *num_of_entries = 256;
+ return Ok;
+}
+
+static GpStatus create_optimal_palette(ColorPalette *palette, INT desired,
+ BOOL transparent, GpBitmap *bitmap)
+{
+ GpStatus status;
+ BitmapData data;
+ HRESULT hr;
+ IWICImagingFactory *factory;
+ IWICPalette *wic_palette;
+
+ if (!bitmap) return InvalidParameter;
+ if (palette->Count < desired) return GenericError;
+
+ status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat24bppRGB, &data);
+ if (status != Ok) return status;
+
+ hr = WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &factory);
+ if (hr != S_OK)
+ {
+ GdipBitmapUnlockBits(bitmap, &data);
+ return hresult_to_status(hr);
+ }
+
+ hr = IWICImagingFactory_CreatePalette(factory, &wic_palette);
+ if (hr == S_OK)
+ {
+ IWICBitmap *bitmap;
+
+ /* PixelFormat24bppRGB actually stores the bitmap bits as BGR. */
+ hr = IWICImagingFactory_CreateBitmapFromMemory(factory, data.Width, data.Height,
+ &GUID_WICPixelFormat24bppBGR, data.Stride, data.Stride * data.Width, data.Scan0, &bitmap);
+ if (hr == S_OK)
+ {
+ hr = IWICPalette_InitializeFromBitmap(wic_palette, (IWICBitmapSource *)bitmap, desired, transparent);
+ if (hr == S_OK)
+ {
+ palette->Flags = 0;
+ IWICPalette_GetColorCount(wic_palette, &palette->Count);
+ IWICPalette_GetColors(wic_palette, palette->Count, palette->Entries, &palette->Count);
+ }
+
+ IWICBitmap_Release(bitmap);
+ }
+
+ IWICPalette_Release(wic_palette);
+ }
+
+ IWICImagingFactory_Release(factory);
+ GdipBitmapUnlockBits(bitmap, &data);
+
+ return hresult_to_status(hr);
+}
+
+/*****************************************************************************
+ * GdipInitializePalette [GDIPLUS.@]
+ */
+GpStatus WINGDIPAPI GdipInitializePalette(ColorPalette *palette,
+ PaletteType type, INT desired, BOOL transparent, GpBitmap *bitmap)
+{
+ TRACE("(%p,%d,%d,%d,%p)\n", palette, type, desired, transparent, bitmap);
+
+ if (!palette) return InvalidParameter;
+
+ switch (type)
+ {
+ case PaletteTypeCustom:
+ return Ok;
+
+ case PaletteTypeOptimal:
+ return create_optimal_palette(palette, desired, transparent, bitmap);
+
+ /* WIC palette type enumeration matches these gdiplus enums */
+ case PaletteTypeFixedBW:
+ case PaletteTypeFixedHalftone8:
+ case PaletteTypeFixedHalftone27:
+ case PaletteTypeFixedHalftone64:
+ case PaletteTypeFixedHalftone125:
+ case PaletteTypeFixedHalftone216:
+ case PaletteTypeFixedHalftone252:
+ case PaletteTypeFixedHalftone256:
+ {
+ ColorPalette *wic_palette;
+ GpStatus status = Ok;
+
+ wic_palette = get_palette(NULL, type);
+ if (!wic_palette) return OutOfMemory;
+
+ if (palette->Count >= wic_palette->Count)
+ {
+ palette->Flags = wic_palette->Flags;
+ palette->Count = wic_palette->Count;
+ memcpy(palette->Entries, wic_palette->Entries, wic_palette->Count * sizeof(wic_palette->Entries[0]));
+ }
+ else
+ status = GenericError;
+
+ heap_free(wic_palette);
+
+ return status;
+ }
+
+ default:
+ FIXME("unknown palette type %d\n", type);
+ break;
+ }
+
+ return InvalidParameter;
+}