1 /*******************************************************************************
2 * Copyright (c) 2007, 2017 IBM Corporation and others.
4 * This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License 2.0
6 * which accompanies this distribution, and is available at
7 * https://www.eclipse.org/legal/epl-2.0/
9 * SPDX-License-Identifier: EPL-2.0
12 * IBM Corporation - initial API and implementation
13 *******************************************************************************/
14 package org.eclipse.swt.dnd;
16 import org.eclipse.swt.*;
17 import org.eclipse.swt.graphics.*;
18 import org.eclipse.swt.internal.*;
19 import org.eclipse.swt.internal.ole.win32.*;
20 import org.eclipse.swt.internal.win32.*;
23 * The class <code>ImageTransfer</code> provides a platform specific mechanism
24 * for converting an Image represented as a java <code>ImageData</code> to a
25 * platform specific representation of the data and vice versa.
27 * <p>An example of a java <code>ImageData</code> is shown below:</p>
30 * Image image = new Image(display, "C:\\temp\\img1.gif");
31 * ImageData imgData = image.getImageData();
38 public class ImageTransfer extends ByteArrayTransfer {
40 private static ImageTransfer _instance = new ImageTransfer();
41 private static final String CF_DIB = "CF_DIB"; //$NON-NLS-1$
42 private static final int CF_DIBID = COM.CF_DIB;
44 private ImageTransfer() {}
47 * Returns the singleton instance of the ImageTransfer class.
49 * @return the singleton instance of the ImageTransfer class
51 public static ImageTransfer getInstance () {
56 * This implementation of <code>javaToNative</code> converts an ImageData object represented
57 * by java <code>ImageData</code> to a platform specific representation.
59 * @param object a java <code>ImageData</code> containing the ImageData to be converted
60 * @param transferData an empty <code>TransferData</code> object that will
61 * be filled in on return with the platform specific format of the data
63 * @see Transfer#nativeToJava
66 public void javaToNative(Object object, TransferData transferData) {
67 if (!checkImage(object) || !isSupportedType(transferData)) {
68 DND.error(DND.ERROR_INVALID_DATA);
70 ImageData imgData = (ImageData)object;
71 if (imgData == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
73 int imageSize = imgData.data.length;
74 int imageHeight = imgData.height;
75 int bytesPerLine = imgData.bytesPerLine;
77 BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER();
78 bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
79 bmiHeader.biSizeImage = imageSize;
80 bmiHeader.biWidth = imgData.width;
81 bmiHeader.biHeight = imageHeight;
82 bmiHeader.biPlanes = 1;
83 bmiHeader.biBitCount = (short)imgData.depth;
84 bmiHeader.biCompression = OS.DIB_RGB_COLORS;
87 if (bmiHeader.biBitCount <= 8) {
88 colorSize += (1 << bmiHeader.biBitCount) * 4;
90 byte[] bmi = new byte[BITMAPINFOHEADER.sizeof + colorSize];
91 OS.MoveMemory(bmi, bmiHeader, BITMAPINFOHEADER.sizeof);
93 RGB[] rgbs = imgData.palette.getRGBs();
94 if (rgbs != null && colorSize > 0) {
95 int offset = BITMAPINFOHEADER.sizeof;
96 for (int j = 0; j < rgbs.length; j++) {
97 bmi[offset] = (byte)rgbs[j].blue;
98 bmi[offset + 1] = (byte)rgbs[j].green;
99 bmi[offset + 2] = (byte)rgbs[j].red;
104 long newPtr = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, BITMAPINFOHEADER.sizeof + colorSize + imageSize);
105 OS.MoveMemory(newPtr, bmi, bmi.length);
106 long pBitDest = newPtr + BITMAPINFOHEADER.sizeof + colorSize;
108 if (imageHeight <= 0) {
109 OS.MoveMemory(pBitDest, imgData.data, imageSize);
112 pBitDest += bytesPerLine * (imageHeight - 1);
113 byte[] scanline = new byte[bytesPerLine];
114 for (int i = 0; i < imageHeight; i++) {
115 System.arraycopy(imgData.data, offset, scanline, 0, bytesPerLine);
116 OS.MoveMemory(pBitDest, scanline, bytesPerLine);
117 offset += bytesPerLine;
118 pBitDest -= bytesPerLine;
121 transferData.stgmedium = new STGMEDIUM();
122 transferData.stgmedium.tymed = COM.TYMED_HGLOBAL;
123 transferData.stgmedium.unionField = newPtr;
124 transferData.stgmedium.pUnkForRelease = 0;
125 transferData.result = COM.S_OK;
130 * This implementation of <code>nativeToJava</code> converts a platform specific
131 * representation of an image to java <code>ImageData</code>.
133 * @param transferData the platform specific representation of the data to be converted
134 * @return a java <code>ImageData</code> of the image if the conversion was successful;
137 * @see Transfer#javaToNative
140 public Object nativeToJava(TransferData transferData) {
141 if (!isSupportedType(transferData) || transferData.pIDataObject == 0) return null;
142 IDataObject dataObject = new IDataObject(transferData.pIDataObject);
144 FORMATETC formatetc = new FORMATETC();
145 formatetc.cfFormat = COM.CF_DIB;
147 formatetc.dwAspect = COM.DVASPECT_CONTENT;
148 formatetc.lindex = -1;
149 formatetc.tymed = COM.TYMED_HGLOBAL;
150 STGMEDIUM stgmedium = new STGMEDIUM();
151 stgmedium.tymed = COM.TYMED_HGLOBAL;
152 transferData.result = getData(dataObject, formatetc, stgmedium);
154 if (transferData.result != COM.S_OK) return null;
155 long hMem = stgmedium.unionField;
156 dataObject.Release();
158 long ptr = OS.GlobalLock(hMem);
159 if (ptr == 0) return null;
161 BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER();
162 OS.MoveMemory(bmiHeader, ptr, BITMAPINFOHEADER.sizeof);
163 long[] pBits = new long[1];
164 long memDib = OS.CreateDIBSection(0, ptr, OS.DIB_RGB_COLORS, pBits, 0, 0);
165 if (memDib == 0) SWT.error(SWT.ERROR_NO_HANDLES);
166 long bits = ptr + bmiHeader.biSize;
167 if (bmiHeader.biBitCount <= 8) {
168 bits += (bmiHeader.biClrUsed == 0 ? (1 << bmiHeader.biBitCount) : bmiHeader.biClrUsed) * 4;
169 } else if (bmiHeader.biCompression == OS.BI_BITFIELDS) {
172 if (bmiHeader.biHeight < 0) {
173 OS.MoveMemory(pBits[0], bits, bmiHeader.biSizeImage);
175 DIBSECTION dib = new DIBSECTION();
176 OS.GetObject(memDib, DIBSECTION.sizeof, dib);
177 int biHeight = dib.biHeight;
178 int scanline = dib.biSizeImage / biHeight;
179 long pDestBits = pBits[0];
180 long pSourceBits = bits + scanline * (biHeight - 1);
181 for (int i = 0; i < biHeight; i++) {
182 OS.MoveMemory(pDestBits, pSourceBits, scanline);
183 pDestBits += scanline;
184 pSourceBits -= scanline;
187 Image image = Image.win32_new(null, SWT.BITMAP, memDib);
188 ImageData data = image.getImageData (DPIUtil.getDeviceZoom ());
189 OS.DeleteObject(memDib);
193 OS.GlobalUnlock(hMem);
201 protected int[] getTypeIds(){
202 return new int[] {CF_DIBID};
206 protected String[] getTypeNames(){
207 return new String[] {CF_DIB};
209 boolean checkImage(Object object) {
210 if (object == null || !(object instanceof ImageData)) return false;
215 protected boolean validate(Object object) {
216 return checkImage(object);