mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-14 18:05:27 +07:00
[pycharm] PY-80835 PY-81089 Debugger: move cursor and add data type
Merge-request: IJ-MR-162745 Merged-by: Ekaterina Itsenko <ekaterina.itsenko@jetbrains.com> (cherry picked from commit 4481d3e22b0c597c5d72eff21100feb94182977c) GitOrigin-RevId: cb7a8bfce45fec4525e99a29e74ce342485bdf10
This commit is contained in:
committed by
intellij-monorepo-bot
parent
757a45f40f
commit
a6a827f1df
@@ -103,5 +103,8 @@ image.channels.mode.channel.3=Channel 3
|
||||
image.color.mode.configure.actions=Binarization\u2026
|
||||
action.restore.original.text=Restore Original
|
||||
action.normalize.image.text=Normalize Image
|
||||
scientific.cursor.position=(x = {0}, y = {1});
|
||||
scientific.pixel.value=value = ({0}, {1}, {2})
|
||||
scientific.cursor.position=x={0}, y={1}
|
||||
scientific.pixel.value.grayscale=Value: {0}
|
||||
scientific.pixel.value.rgb=Value: {0},{1},{2}
|
||||
scientific.data.type=Type: {0}
|
||||
scientific.data.dimensions=HxW:{0}x{1}
|
||||
@@ -53,11 +53,11 @@ import org.intellij.images.editor.ImageEditor;
|
||||
import org.intellij.images.editor.ImageZoomModel;
|
||||
import org.intellij.images.editor.actionSystem.ImageEditorActions;
|
||||
import org.intellij.images.options.*;
|
||||
import org.intellij.images.scientific.utils.ScientificUtils;
|
||||
import org.intellij.images.thumbnail.actionSystem.ThumbnailViewActions;
|
||||
import org.intellij.images.thumbnail.actions.ShowBorderAction;
|
||||
import org.intellij.images.ui.ImageComponent;
|
||||
import org.intellij.images.ui.ImageComponentDecorator;
|
||||
import org.intellij.images.scientific.utils.ScientificUtils;
|
||||
import org.intellij.images.vfs.IfsUtil;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
@@ -174,59 +174,19 @@ public final class ImageEditorUI extends JPanel implements UiDataProvider, CopyP
|
||||
contentPanel.add(myScrollPane, IMAGE_PANEL);
|
||||
contentPanel.add(errorPanel, ERROR_PANEL);
|
||||
|
||||
JPanel topPanel = new NonOpaquePanel(new BorderLayout());
|
||||
JPanel bottomPanel = new NonOpaquePanel(new BorderLayout());
|
||||
|
||||
infoLabel = new JLabel((String)null, SwingConstants.RIGHT);
|
||||
infoLabel.setBorder(JBUI.Borders.emptyRight(2));
|
||||
|
||||
boolean isScientificMode = editor != null && editor.getFile().getUserData(ScientificUtils.SCIENTIFIC_MODE_KEY) != null;
|
||||
JPanel topPanel = new NonOpaquePanel(new BorderLayout());
|
||||
if (!isEmbedded) {
|
||||
topPanel.add(toolbarPanel, BorderLayout.WEST);
|
||||
if (isScientificMode) {
|
||||
JPanel scientificInfoPanel = new NonOpaquePanel(new FlowLayout(FlowLayout.LEFT, 2, 0));
|
||||
JLabel positionLabel = new JLabel(ImagesBundle.message("scientific.cursor.position", 0, 0));
|
||||
JLabel valueLabel = new JLabel(ImagesBundle.message("scientific.pixel.value", 0, 0, 0));
|
||||
scientificInfoPanel.add(positionLabel);
|
||||
scientificInfoPanel.add(valueLabel);
|
||||
|
||||
view.addMouseMotionListener(new MouseMotionAdapter() {
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
BufferedImage image = imageComponent.getDocument().getValue();
|
||||
if (image != null) {
|
||||
double zoom = imageComponent.getZoomFactor();
|
||||
|
||||
int x = (int)((e.getX() - ImageComponent.IMAGE_INSETS) / zoom);
|
||||
int y = (int)((e.getY() - ImageComponent.IMAGE_INSETS) / zoom);
|
||||
|
||||
if (x >= 0 && x < image.getWidth() && y >= 0 && y < image.getHeight()) {
|
||||
int pixel = image.getRGB(x, y);
|
||||
int r = (pixel >> 16) & 0xFF;
|
||||
int g = (pixel >> 8) & 0xFF;
|
||||
int b = pixel & 0xFF;
|
||||
positionLabel.setText(ImagesBundle.message("scientific.cursor.position", x, y));
|
||||
valueLabel.setText(ImagesBundle.message("scientific.pixel.value", r, g, b));
|
||||
}
|
||||
else {
|
||||
positionLabel.setText(ImagesBundle.message("scientific.cursor.position", 0, 0));
|
||||
valueLabel.setText(ImagesBundle.message("scientific.pixel.value", 0, 0, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
bottomPanel.add(scientificInfoPanel, BorderLayout.WEST);
|
||||
bottomPanel.add(infoLabel, BorderLayout.EAST);
|
||||
}
|
||||
else {
|
||||
if (!isScientificMode) {
|
||||
infoLabel = new JLabel((String)null, SwingConstants.RIGHT);
|
||||
infoLabel.setBorder(JBUI.Borders.emptyRight(2));
|
||||
topPanel.add(infoLabel, BorderLayout.EAST);
|
||||
}
|
||||
}
|
||||
|
||||
add(topPanel, BorderLayout.NORTH);
|
||||
add(contentPanel, BorderLayout.CENTER);
|
||||
add(bottomPanel, BorderLayout.SOUTH);
|
||||
|
||||
myScrollPane.addComponentListener(new ComponentAdapter() {
|
||||
@Override
|
||||
@@ -250,21 +210,20 @@ public final class ImageEditorUI extends JPanel implements UiDataProvider, CopyP
|
||||
|
||||
private void updateInfo() {
|
||||
if (isEmbedded) return;
|
||||
boolean isScientificMode = editor != null && editor.getFile().getUserData(ScientificUtils.SCIENTIFIC_MODE_KEY) != null;
|
||||
if (isScientificMode) return;
|
||||
ImageDocument document = imageComponent.getDocument();
|
||||
BufferedImage image = document.getValue();
|
||||
VirtualFile file = editor != null ? editor.getFile() : null;
|
||||
boolean isScientificMode = (file != null ? file.getUserData(ScientificUtils.SCIENTIFIC_MODE_KEY) : null) != null;
|
||||
if (image != null) {
|
||||
ColorModel colorModel = image.getColorModel();
|
||||
String format = document.getFormat();
|
||||
if (format == null) {
|
||||
format = editor != null ? ImagesBundle.message("unknown.format") : "";
|
||||
} else if (isScientificMode) {
|
||||
format = "";
|
||||
}
|
||||
else {
|
||||
format = StringUtil.toUpperCase(format);
|
||||
}
|
||||
VirtualFile file = editor != null ? editor.getFile() : null;
|
||||
infoLabel.setText(
|
||||
ImagesBundle.message("image.info",
|
||||
image.getWidth(), image.getHeight(), format,
|
||||
@@ -735,4 +694,4 @@ public final class ImageEditorUI extends JPanel implements UiDataProvider, CopyP
|
||||
imageComponent.setGridLineColor(gridOptions.getLineColor());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ object ScientificUtils {
|
||||
@JvmField
|
||||
var SCIENTIFIC_MODE_KEY: Key<Unit> = Key<Unit>("SCIENTIFIC_MODE")
|
||||
val ORIGINAL_IMAGE_KEY: Key<BufferedImage> = Key("ORIGINAL_IMAGE")
|
||||
val DATA_TYPE_KEY: Key<String> = Key("DATA_TYPE")
|
||||
val ROTATION_ANGLE_KEY: Key<Int> = Key.create("IMAGE_ROTATION_ANGLE")
|
||||
val CURRENT_NOT_NORMALIZED_IMAGE_KEY: Key<BufferedImage> = Key("CURRENT_NOT_NORMALIZED_IMAGE_KEY")
|
||||
val IS_NORMALIZED_KEY: Key<Boolean> = Key<Boolean>("IS_NORMALIZED")
|
||||
|
||||
@@ -142,7 +142,7 @@ def __get_image_provider(output):
|
||||
import _pydevd_bundle.tables.images.pydevd_numpy_based_image as image_provider
|
||||
elif type_qualified_name == 'numpy.ndarray':
|
||||
import _pydevd_bundle.tables.images.pydevd_numpy_image as image_provider
|
||||
elif type_qualified_name == 'PIL.Image.Image':
|
||||
elif type_qualified_name in ['PIL.Image.Image', 'PIL.PngImagePlugin.PngImageFile', 'PIL.JpegImagePlugin.JpegImageFile']:
|
||||
import _pydevd_bundle.tables.images.pydevd_pillow_image as image_provider
|
||||
elif type_qualified_name == 'matplotlib.figure.Figure':
|
||||
import _pydevd_bundle.tables.images.pydevd_matplotlib_image as image_provider
|
||||
|
||||
@@ -32,8 +32,8 @@ def load_image_chunk(offset, image_id):
|
||||
return "Error: {}".format(e)
|
||||
|
||||
|
||||
def save_image_to_storage(image_data, format=DEFAULT_IMAGE_FORMAT, save_func=None):
|
||||
# type: (any, str, callable) -> str
|
||||
def save_image_to_storage(image_data, data_type=None, format=DEFAULT_IMAGE_FORMAT, save_func=None):
|
||||
# type: (any, str, str, callable) -> str
|
||||
try:
|
||||
bytes_buffer = io.BytesIO()
|
||||
try:
|
||||
@@ -45,7 +45,9 @@ def save_image_to_storage(image_data, format=DEFAULT_IMAGE_FORMAT, save_func=Non
|
||||
bytes_data = bytes_buffer.getvalue()
|
||||
image_id = str(uuid.uuid4())
|
||||
IMAGE_DATA_STORAGE[image_id] = bytes_data
|
||||
return "{};{}".format(image_id, len(bytes_data))
|
||||
if data_type is None:
|
||||
data_type = "None"
|
||||
return "{};{};{}".format(image_id, len(bytes_data), data_type)
|
||||
finally:
|
||||
bytes_buffer.close()
|
||||
except Exception as e:
|
||||
|
||||
@@ -16,6 +16,10 @@ def create_image(arr):
|
||||
try:
|
||||
from PIL import Image
|
||||
|
||||
if hasattr(arr.dtype, 'name'):
|
||||
data_type = arr.dtype.name
|
||||
else:
|
||||
data_type = arr.dtype
|
||||
arr_to_convert = arr
|
||||
|
||||
try:
|
||||
@@ -37,14 +41,17 @@ def create_image(arr):
|
||||
elif arr_to_convert.ndim == 3 and arr_to_convert.shape[2] == 1:
|
||||
arr_to_convert = arr_to_convert[:, :, 0]
|
||||
|
||||
arr_min, arr_max = np.min(arr_to_convert), np.max(arr_to_convert)
|
||||
if arr_min == arr_max: # handle constant values
|
||||
arr_to_convert = np.full_like(arr_to_convert, 127, dtype=np.uint8)
|
||||
elif 0 <= arr_min <= 1 and 0 <= arr_max <= 1:
|
||||
arr_min, arr_max = arr_to_convert.min(), arr_to_convert.max()
|
||||
is_float = np.issubdtype(arr_to_convert.dtype, np.floating)
|
||||
is_bool = np.issubdtype(arr_to_convert.dtype, np.bool)
|
||||
|
||||
if (is_float or is_bool) and 0 <= arr_min <= 1 and 0 <= arr_max <= 1: # bool and float in [0; 1]
|
||||
arr_to_convert = (arr_to_convert * 255).astype(np.uint8)
|
||||
elif arr_min < 0 or arr_max > 255:
|
||||
elif arr_min != arr_max and (arr_min < 0 or arr_max > 255): # other values out of [0; 255]
|
||||
arr_to_convert = ((arr_to_convert - arr_min) * 255 / (arr_max - arr_min)).astype(np.uint8)
|
||||
else:
|
||||
elif arr_min == arr_max and (arr_min < 0 or arr_max > 255):
|
||||
arr_to_convert = (np.ones_like(arr_to_convert) * 127).astype(np.uint8)
|
||||
else: # values in [0; 255]
|
||||
arr_to_convert = arr_to_convert.astype(np.uint8)
|
||||
|
||||
arr_to_convert_ndim = arr_to_convert.ndim
|
||||
@@ -54,7 +61,8 @@ def create_image(arr):
|
||||
mode = RGBA_MODE
|
||||
else:
|
||||
mode = RGB_MODE
|
||||
return save_image_to_storage(Image.fromarray(arr_to_convert, mode=mode))
|
||||
|
||||
return save_image_to_storage(Image.fromarray(arr_to_convert, mode=mode), data_type=data_type)
|
||||
|
||||
except ImportError:
|
||||
return "Error: Pillow library is not installed."
|
||||
|
||||
@@ -7,7 +7,9 @@ def create_image(arr):
|
||||
try:
|
||||
from PIL import Image
|
||||
|
||||
data_type = arr.dtype.name
|
||||
arr_to_convert = arr
|
||||
|
||||
arr_to_convert = np.where(arr_to_convert == None, 0, arr_to_convert)
|
||||
arr_to_convert = np.nan_to_num(arr_to_convert, nan=0)
|
||||
|
||||
@@ -19,14 +21,17 @@ def create_image(arr):
|
||||
elif arr_to_convert.ndim == 3 and arr_to_convert.shape[2] == 1:
|
||||
arr_to_convert = arr_to_convert[:, :, 0]
|
||||
|
||||
arr_min, arr_max = np.min(arr_to_convert), np.max(arr_to_convert)
|
||||
if arr_min == arr_max: # handle constant values
|
||||
arr_to_convert = np.full_like(arr_to_convert, 127, dtype=np.uint8)
|
||||
elif 0 <= arr_min <= 1 and 0 <= arr_max <= 1:
|
||||
arr_min, arr_max = arr_to_convert.min(), arr_to_convert.max()
|
||||
is_float = np.issubdtype(arr_to_convert.dtype, np.floating)
|
||||
is_bool = np.issubdtype(arr_to_convert.dtype, np.bool)
|
||||
|
||||
if (is_float or is_bool) and 0 <= arr_min <= 1 and 0 <= arr_max <= 1: # bool and float in [0; 1]
|
||||
arr_to_convert = (arr_to_convert * 255).astype(np.uint8)
|
||||
elif arr_min < 0 or arr_max > 255:
|
||||
arr_to_convert = ((arr_to_convert - arr_min) * 255 / (arr_max - arr_min)).astype(np.uint8)
|
||||
else:
|
||||
elif arr_min != arr_max and (arr_min < 0 or arr_max > 255):
|
||||
arr_to_convert = ((arr_to_convert - arr_min) * 255 / (arr_max - arr_min)).astype(np.uint8) # other values out of [0; 255]
|
||||
elif arr_min == arr_max and (arr_min < 0 or arr_max > 255):
|
||||
arr_to_convert = (np.ones_like(arr_to_convert) * 127).astype(np.uint8)
|
||||
else: # values in [0; 255]
|
||||
arr_to_convert = arr_to_convert.astype(np.uint8)
|
||||
|
||||
arr_to_convert_ndim = arr_to_convert.ndim
|
||||
@@ -37,7 +42,7 @@ def create_image(arr):
|
||||
else:
|
||||
mode = RGB_MODE
|
||||
|
||||
return save_image_to_storage(Image.fromarray(arr_to_convert, mode=mode))
|
||||
return save_image_to_storage(Image.fromarray(arr_to_convert, mode=mode), data_type=data_type)
|
||||
|
||||
except ImportError:
|
||||
return "Error: Pillow library is not installed."
|
||||
|
||||
@@ -35,6 +35,8 @@ object NodeTypes {
|
||||
const val SPARSE_TENSOR_NODE_TYPE: String = "SparseTensor"
|
||||
const val TENSOR_NODE_TYPE: String = "Tensor"
|
||||
const val IMAGE_NODE_TYPE: String = "Image"
|
||||
const val PNG_IMAGE_NODE_TYPE: String = "PngImageFile"
|
||||
const val JPEG_IMAGE_NODE_TYPE: String = "JpegImageFile"
|
||||
const val FIGURE_NODE_TYPE: String = "Figure"
|
||||
const val DATA_FRAME_NODE_TYPE: String = "DataFrame"
|
||||
const val SERIES_NODE_TYPE: String = "Series"
|
||||
|
||||
@@ -539,7 +539,7 @@ public class PyDebugValue extends XNamedValue {
|
||||
int[] shape = extractShape(debugValue);
|
||||
yield isValidArrayShape(shape);
|
||||
}
|
||||
case NodeTypes.IMAGE_NODE_TYPE, NodeTypes.FIGURE_NODE_TYPE -> true;
|
||||
case NodeTypes.IMAGE_NODE_TYPE, NodeTypes.PNG_IMAGE_NODE_TYPE, NodeTypes.JPEG_IMAGE_NODE_TYPE, NodeTypes.FIGURE_NODE_TYPE -> true;
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user