探索Apache Commons Imaging处理图像

第1章:引言

大家好,我是小黑,咱们今天来聊聊图像处理。在这个数字化日益增长的时代,图像处理已经成为了一个不可或缺的技能。不论是社交媒体上的照片编辑,还是专业领域的图像分析,图像处理无处不在。而作为一名Java开发者,小黑自然也对这一领域充满了兴趣。

为什么要选择Apache Commons Imaging(原名Sanselan)来进行图像处理呢?原因很简单:它是一个纯Java的库,不仅功能强大,而且使用起来非常方便。这个库支持广泛的图像格式,从常见的JPEG、PNG到专业的TIFF、PSD等,都能轻松处理。最重要的是,它的开源特性让咱们可以深入了解其内部工作机制,更好地掌握图像处理的精髓。

第2章:Apache Commons Imaging简介

Apache Commons Imaging,之前被称为Sanselan,是一个开源的Java图像库,主要用于读取、写入和操作图像数据。这个库的强大之处在于它对多种格式的图像文件都有很好的支持,比如JPEG、PNG、GIF、BMP,甚至还包括一些不太常见的格式,比如TIFF、PSD等。

为了让咱们更好地理解这个库的使用,小黑会在本篇博客中通过一系列的实际案例来展示它的功能。这样不仅能让咱们更加直观地了解Apache Commons Imaging,还能帮助咱们在实际项目中快速应用这些技巧。

咱们来看看如何在Java项目中添加Apache Commons Imaging。一般来说,如果咱们使用的是Maven来管理项目,只需在pom.xml文件中添加以下依赖:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-imaging</artifactId>
    <version>1.0-alpha2</version>
</dependency>

接下来,小黑会展示一个简单的示例,让咱们看看如何使用Apache Commons Imaging来读取一个图像文件。假设咱们有一个名为“测试图片.jpg”的图像文件,想要读取它并获取一些基本信息,可以使用以下代码:

import org.apache.commons.imaging.Imaging;
import org.apache.commons.imaging.ImageFormats;
import org.apache.commons.imaging.ImagingException;

import java.io.File;
import java.io.IOException;
import java.awt.image.BufferedImage;

public class ImageReaderExample {
    public static void main(String[] args) {
        try {
            File imageFile = new File("测试图片.jpg");
            BufferedImage image = Imaging.getBufferedImage(imageFile);

            // 输出基本信息
            System.out.println("图像格式: " + Imaging.guessFormat(imageFile));
            System.out.println("宽度: " + image.getWidth());
            System.out.println("高度: " + image.getHeight());
        } catch (ImagingException | IOException e) {
            e.printStackTrace();
        }
    }
}

在这段代码中,咱们首先读取了一个名为“测试图片.jpg”的文件,然后使用Imaging.getBufferedImage方法将其转换为BufferedImage对象。之后,咱们打印出了这个图像的格式、宽度和高度等信息。

第3章:依赖配置

对于使用Maven作为项目管理工具的情况,只需要在项目的pom.xml文件中添加相应的依赖。这里的依赖版本可能会随着时间更新,所以建议到Apache Commons Imaging的官方网站查看最新版本。下面是一个示例的依赖配置:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-imaging</artifactId>
    <version>1.0-alpha2</version> <!-- 这里的版本号需要根据最新版本进行调整 -->
</dependency>

加入这段依赖后,Maven会自动处理所需库的下载和管理。接下来,咱们来看看如何使用这个库来进行一些基本的图像操作。比如说,读取一张图像并显示其基本信息,这是图像处理中最基础的一步。

import org.apache.commons.imaging.Imaging;
import org.apache.commons.imaging.common.ImageMetadata;
import org.apache.commons.imaging.common.ImageMetadata.ImageMetadataItem;
import java.io.File;
import java.util.List;

public class BasicImageInfo {
    public static void main(String[] args) {
        try {
            File imageFile = new File("测试图片.jpg"); // 图像文件路径
            List<ImageMetadataItem> metadata = Imaging.getMetadata(imageFile).getItems();

            for (ImageMetadataItem item : metadata) {
                System.out.println(item.toString()); // 打印图像的元数据
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

在这个例子中,小黑使用了Imaging.getMetadata方法来获取图像文件的元数据,并逐个打印出来。这种操作对于理解图像的属性,比如相机设置、拍摄时间等信息非常有用。

图像处理不仅仅是关于读取信息,还包括修改、转换等多种操作。为了进行这些操作,咱们需要确保环境搭建正确无误。在实际开发中,可能会遇到各种问题,比如依赖冲突、版本不兼容等。这时候,查看官方文档、搜索相关问题解决方案或者在社区寻求帮助是非常必要的。

通过以上步骤,咱们就能够在Java项目中成功集成Apache Commons Imaging,并进行基础的图像处理操作了。

第4章:读取和写入图像

读取图像

读取图像是开始任何图像处理任务的第一步。在Apache Commons Imaging中,这个过程非常直观。咱们可以使用Imaging.getBufferedImage方法来读取图像文件。让小黑来展示一下这个过程:

import org.apache.commons.imaging.Imaging;
import org.apache.commons.imaging.ImageFormats;
import org.apache.commons.imaging.ImagingException;

import java.io.File;
import java.awt.image.BufferedImage;

public class ReadImageExample {
    public static void main(String[] args) {
        try {
            File imageFile = new File("测试图片.jpg"); // 图像文件路径
            BufferedImage image = Imaging.getBufferedImage(imageFile);

            System.out.println("图像宽度: " + image.getWidth());
            System.out.println("图像高度: " + image.getHeight());
            // 这里可以添加更多的操作,比如分析图像内容等
        } catch (ImagingException | IOException e) {
            e.printStackTrace();
        }
    }
}

在这个例子中,小黑首先创建了一个指向图像文件的File对象。然后,使用Imaging.getBufferedImage方法读取这个文件,并将其转换为一个BufferedImage对象。这样就可以获取到图像的宽度、高度等基本信息了。

写入图像

读取图像之后,通常咱们可能会对图像进行一系列处理,如调整大小、应用滤镜等。处理完成后,接下来的任务就是将修改后的图像保存回文件。下面是一个简单的示例,展示如何将处理后的图像写入文件:

import org.apache.commons.imaging.Imaging;
import org.apache.commons.imaging.ImageFormats;
import org.apache.commons.imaging.ImagingException;

import java.io.File;
import java.awt.image.BufferedImage;

public class WriteImageExample {
    public static void main(String[] args) {
        try {
            File inputFile = new File("原始图片.jpg");
            BufferedImage image = Imaging.getBufferedImage(inputFile);

            // 在这里可以对image进行各种处理...

            File outputFile = new File("处理后的图片.jpg");
            Imaging.writeImage(image, outputFile, ImageFormats.JPEG, null);
            System.out.println("图像保存成功!");
        } catch (ImagingException | IOException e) {
            e.printStackTrace();
        }
    }
}

在这个例子中,小黑先读取了一个名为“原始图片.jpg”的文件,进行了一些假设的处理(比如调整大小、应用滤镜等),然后将处理后的图像保存为“处理后的图片.jpg”。这里使用了Imaging.writeImage方法,它允许咱们指定图像格式和一些写入参数。

第5章:图像转换和处理

图像格式转换

在日常工作中,咱们经常需要将图像从一种格式转换成另一种格式。比如,可能需要把PNG格式的图片转换成JPEG格式,以便于网络传输或者兼容性更好。小黑这就来展示一个简单的格式转换过程:

import org.apache.commons.imaging.Imaging;
import org.apache.commons.imaging.ImageFormats;
import org.apache.commons.imaging.ImagingException;

import java.io.File;
import java.awt.image.BufferedImage;

public class ImageFormatConversion {
    public static void main(String[] args) {
        try {
            File inputFile = new File("原始图片.png");
            BufferedImage image = Imaging.getBufferedImage(inputFile);

            File outputFile = new File("转换后的图片.jpg");
            Imaging.writeImage(image, outputFile, ImageFormats.JPEG, null);

            System.out.println("格式转换完成!");
        } catch (ImagingException | IOException e) {
            e.printStackTrace();
        }
    }
}

在这个例子中,小黑首先读取了一个PNG格式的图像文件“原始图片.png”,然后使用Imaging.writeImage方法将其保存为JPEG格式的文件“转换后的图片.jpg”。这个过程非常简单,但在实际应用中却非常有用。

基本图像处理

除了格式转换,咱们还可以进行一些基本的图像处理操作,比如调整图像大小、裁剪、旋转等。下面是一个调整图像大小的示例:

import org.apache.commons.imaging.Imaging;
import org.apache.commons.imaging.ImageFormats;
import org.apache.commons.imaging.ImagingException;

import java.io.File;
import java.awt.image.BufferedImage;

public class ResizeImage {
    public static void main(String[] args) {
        try {
            File inputFile = new File("原始图片.jpg");
            BufferedImage image = Imaging.getBufferedImage(inputFile);

            BufferedImage resizedImage = resizeImage(image, 200, 200); // 调整为200x200像素

            File outputFile = new File("调整大小后的图片.jpg");
            Imaging.writeImage(resizedImage, outputFile, ImageFormats.JPEG, null);

            System.out.println("图像大小调整完成!");
        } catch (ImagingException | IOException e) {
            e.printStackTrace();
        }
    }

    private static BufferedImage resizeImage(BufferedImage originalImage, int targetWidth, int targetHeight) throws IOException {
        BufferedImage resizedImage = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics2D = resizedImage.createGraphics();
        graphics2D.drawImage(originalImage, 0, 0, targetWidth, targetHeight, null);
        graphics2D.dispose();
        return resizedImage;
    }
}

在这个例子中,小黑创建了一个名为resizeImage的方法,它接受一个BufferedImage对象和目标宽高,返回一个调整大小后的新图像。这种操作在处理用户上传的图片或者为网页准备缩略图时非常有用。

第6章:元数据处理

读取元数据

在Apache Commons Imaging中,读取图像元数据是一个简单而强大的过程。咱们可以获取到很多有关图像的详细信息。下面是一个读取JPEG图像元数据的示例:

import org.apache.commons.imaging.Imaging;
import org.apache.commons.imaging.common.ImageMetadata;
import org.apache.commons.imaging.common.ImageMetadata.ImageMetadataItem;
import org.apache.commons.imaging.formats.jpeg.JpegImageMetadata;
import org.apache.commons.imaging.formats.tiff.constants.TiffTagConstants;

import java.io.File;
import java.util.List;

public class ReadMetadataExample {
    public static void main(String[] args) {
        try {
            File jpegImageFile = new File("测试图片.jpg");
            final ImageMetadata metadata = Imaging.getMetadata(jpegImageFile);
            final JpegImageMetadata jpegMetadata = (JpegImageMetadata) metadata;

            if (jpegMetadata != null) {
                // 打印所有元数据项
                List<ImageMetadataItem> items = jpegMetadata.getItems();
                for (ImageMetadataItem item : items) {
                    System.out.println(item);
                }

                // 获取特定的元数据项,例如拍摄时间
                String shootingTime = jpegMetadata.findEXIFValueWithExactMatch(TiffTagConstants.TIFF_TAG_DATE_TIME).toString();
                System.out.println("拍摄时间: " + shootingTime);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

在这个示例中,小黑读取了一个JPEG图像文件的元数据,并打印出了所有的元数据项。此外,还特别获取了拍摄时间这一具体的元数据信息。这对于管理大量图像,尤其是对于摄影师来说,是非常有用的。

修改和添加元数据

除了读取元数据,Apache Commons Imaging还允许咱们修改或添加新的元数据信息。这对于个性化图像处理、版权信息添加等场景非常有用。不过,需要注意的是,修改元数据是一个相对复杂的过程,涉及到图像格式和元数据标准的深入理解。

由于修改元数据是一个相对复杂的过程,涉及到直接操作图像的底层数据,所以这个例子将会相对复杂一些。不过别担心,小黑会尽量用清晰的注释来说明每一步的作用。

import org.apache.commons.imaging.ImageReadException;
import org.apache.commons.imaging.ImageWriteException;
import org.apache.commons.imaging.Imaging;
import org.apache.commons.imaging.common.ImageMetadata;
import org.apache.commons.imaging.common.RationalNumber;
import org.apache.commons.imaging.formats.jpeg.JpegImageMetadata;
import org.apache.commons.imaging.formats.jpeg.exif.ExifRewriter;
import org.apache.commons.imaging.formats.tiff.TiffImageMetadata;
import org.apache.commons.imaging.formats.tiff.TiffOutputDirectory;
import org.apache.commons.imaging.formats.tiff.TiffOutputField;
import org.apache.commons.imaging.formats.tiff.TiffOutputSet;
import org.apache.commons.imaging.formats.tiff.constants.ExifTagConstants;
import org.apache.commons.imaging.formats.tiff.constants.TiffTagConstants;
import org.apache.commons.imaging.formats.tiff.write.TiffOutputDirectory;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class ModifyMetadataExample {
    public static void main(String[] args) {
        try {
            File jpegImageFile = new File("测试图片.jpg");
            File outputFile = new File("修改元数据后的图片.jpg");

            OutputStream os = null;
            try {
                TiffOutputSet outputSet = null;

                // 尝试读取图像的元数据
                final ImageMetadata metadata = Imaging.getMetadata(jpegImageFile);
                final JpegImageMetadata jpegMetadata = (JpegImageMetadata) metadata;
                if (jpegMetadata != null) {
                    final TiffImageMetadata exif = jpegMetadata.getExif();

                    if (exif != null) {
                        outputSet = exif.getOutputSet();
                    }
                }

                // 如果JPEG图像没有Exif元数据,则创建一个新的输出集
                if (outputSet == null) {
                    outputSet = new TiffOutputSet();
                }

                // 添加自定义注释
                final TiffOutputDirectory exifDirectory = outputSet.getOrCreateExifDirectory();
                exifDirectory.add(TiffOutputField.create(TiffTagConstants.TIFF_TAG_IMAGE_DESCRIPTION, outputSet.byteOrder, "自定义注释"));

                // 修改现有元数据,例如修改拍摄时间
                exifDirectory.removeField(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL);
                exifDirectory.add(TiffOutputField.create(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL, outputSet.byteOrder, "2023:01:01 00:00:00"));

                os = new FileOutputStream(outputFile);
                new ExifRewriter().updateExifMetadataLossless(jpegImageFile, os, outputSet);
            } finally {
                if (os != null) {
                    try {
                        os.close();
                    } catch (IOException e) {
                        // 忽略关闭异常
                    }
                }
            }

            System.out.println("元数据修改完成!");
        } catch (ImageReadException | ImageWriteException | IOException e) {
            e.printStackTrace();
        }
    }
}

在这个代码中,小黑首先尝试从原始JPEG图像中读取元数据。如果图像包含Exif元数据,小黑将使用这些元数据来创建一个TiffOutputSet对象。接着,小黑在Exif目录中添加了一个自定义的注释字段,并修改了拍摄时间字段。最后,使用ExifRewriter类的updateExifMetadataLossless方法将修改后的元数据写回到一个新的JPEG文件中。

这个过程显示了如何在不损失图像质量的情况下,修改JPEG图像的Exif元数据。这对于添加版权信息、个性化标签或其他重要信息到图像中非常有用。不过,需要注意的是,操作元数据时要格外小心,因为错误的操作可能会损坏图像文件。

第7章:错误处理和性能优化

错误处理

在进行图像处理时,常常会遇到各种错误,比如文件格式不支持、文件损坏、内存不足等。正确地处理这些错误可以提高程序的健壮性和用户体验。小黑来展示一个基本的错误处理示例:

import org.apache.commons.imaging.Imaging;
import org.apache.commons.imaging.ImagingException;

import java.io.File;
import java.awt.image.BufferedImage;

public class ErrorHandlingExample {
    public static void main(String[] args) {
        try {
            File imageFile = new File("可能不存在的图片.jpg");
            BufferedImage image = Imaging.getBufferedImage(imageFile);

            // 进行一些图像处理操作...
        } catch (ImagingException e) {
            System.err.println("图像处理错误: " + e.getMessage());
            // 这里可以记录日志或者通知用户错误信息
        } catch (IOException e) {
            System.err.println("文件读写错误: " + e.getMessage());
            // 处理文件读写异常
        } catch (Exception e) {
            System.err.println("未知错误: " + e.getMessage());
            // 处理其他未预见的异常
        }
    }
}

在这个例子中,小黑尝试读取一个图像文件,并在此过程中捕获可能出现的异常。根据不同类型的异常,程序会输出相应的错误信息。这种做法可以帮助调试程序,并在出现问题时提供更清晰的指示。

性能优化

在图像处理中,性能优化同样至关重要。尤其是处理大量或高分辨率的图像时,效率成为一个不容忽视的问题。下面小黑会介绍一些基本的性能优化技巧。

  1. 合理管理内存: 图像处理通常是内存密集型的操作。对于大图像,尽量使用缩放或分块处理的方式来减少内存占用。

  2. 避免不必要的重复读写: 读取和写入图像是耗时操作。如果需要对同一图像执行多个操作,考虑先将图像读入内存,完成所有处理后再统一写回。

  3. 利用多线程: 当处理多个图像时,可以考虑使用多线程来并行处理,以提高效率。

  4. 调整缓存和IO策略: 根据实际需要调整缓存策略和IO操作,避免频繁的磁盘访问。

这些只是一些基础的性能优化建议。在实际应用中,根据具体的需求和环境,还可以采取更多的优化措施。

第8章:总结

实际应用案例
  1. 社交媒体自动化工具: 假设你在开发一个社交媒体管理工具,需要自动调整上传图片的大小和格式。使用Apache Commons Imaging,你可以轻松实现这一功能,确保每张图片都符合社交媒体平台的要求。

  2. 数字图像存档系统: 在数字图像存档系统中,保留图像的元数据信息非常重要。Apache Commons Imaging可以帮助你读取和编辑这些信息,确保每张图像都有正确的描述、版权信息和拍摄日期。

  3. 个性化图像生成器: 想象一下,你在为一个广告公司工作,需要生成大量包含特定文本和图案的图像。利用Apache Commons Imaging,你可以自动化这一过程,为每个客户快速定制个性化图像。

通过这些实际应用案例,我们可以看到Apache Commons Imaging在不同场景下的灵活性和实用性。无论你是在处理个人项目,还是开发复杂的商业应用,这个库都能提供强大的支持。

小黑希望你已经对Apache Commons Imaging有了全面的了解。通过这系列文章,我们一起深入探索了它的主要功能和应用场景。图像处理是一个既有趣又充满挑战的领域,而Apache Commons Imaging则是一把强大的工具,帮助你在这个领域里游刃有余。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/276131.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JavaSE50题:26. (数组练习题)使奇数位于偶数之前

概述 调整数组顺序使得奇数位于偶数之前&#xff0c;调整之后&#xff0c;不关心大小顺序。 如数组&#xff1a;{1,2,3,4,5,6} 调整后可能是&#xff1a;{1&#xff0c;5&#xff0c;3&#xff0c;4&#xff0c;2&#xff0c;6} 方法 定义 left 和 right&#xff0c;二者分别…

位运算|比特位计数、汉明距离

位运算|比特位计数、汉明距离 338 比特位计数 /** 比特位计数法一&#xff1a;Brian Kernighan 算法的原理是&#xff1a;对于任意整数 x&#xff0c;令 xx & (x−1)&#xff0c;该运算将 x 的二进制表示的最后一个 1 变成 0。因此&#xff0c;对 x 重复该操作&#xff0…

中职网络安全Web2003-2——Web渗透测试

需要环境或换&#xff0c;有问题可以私信我或加Q 1.通过URL访问http://靶机IP/1&#xff0c;对该页面进行渗透测试&#xff0c;将完成后返回的结果内容作为Flag值提交&#xff1b; FLAGflag{htmlcode} 2.通过URL访问http://靶机IP/2&#xff0c;对该页面进行渗透测试&#xff…

数字钥匙进入3.0时代,他们要做智能汽车时代的「微信」

“假设用我们的即时通讯的工具来说&#xff0c;我们想造一个微信&#xff0c;我们希望跟更多的主机厂拥抱融合&#xff0c;而不是造一个飞信。” 11月24日&#xff0c;在银基科技承办的第三届数字钥匙及生态大会期间&#xff0c;银基科技CEO单宏寅尝试向到场的媒体&#xff0c…

Flink Kafka[输入/输出] Connector

本章重点介绍生产环境中最常用到的Flink kafka connector。使用Flink的同学&#xff0c;一定会很熟悉kafka&#xff0c;它是一个分布式的、分区的、多副本的、 支持高吞吐的、发布订阅消息系统。生产环境环境中也经常会跟kafka进行一些数据的交换&#xff0c;比如利用kafka con…

代码随想录刷题题Day24

刷题的第二十四天&#xff0c;希望自己能够不断坚持下去&#xff0c;迎来蜕变。&#x1f600;&#x1f600;&#x1f600; 刷题语言&#xff1a;C Day24 任务 ● 491.递增子序列 ● 46.全排列 ● 47.全排列 II 1 递增子序列 491.递增子序列 思路&#xff1a; 本题求自增子序…

Translation翻译插件

Translation插件是为IntelliJ IDEA开发的&#xff0c;因此只能在IntelliJ IDEA中使用。但是&#xff0c;如果你需要在其他软件中进行翻译&#xff0c;可以考虑使用其他的翻译工具或服务。例如&#xff0c;一些在线翻译网站&#xff08;如Google翻译、百度翻译等&#xff09;提供…

由浅入深走进Python异步编程【协程与yield】(含代码实例讲解 || 迭代器、生成器、协程、yield from)

写在前面 从底层到第三方库&#xff0c;全面讲解python的异步编程。这节讲述的是python异步编程的底层原理第一节&#xff0c;详细了解需要配合下一节观看哦。纯干货&#xff0c;无概念&#xff0c;代码实例讲解。 本系列有6章左右&#xff0c;点击头像或者专栏查看更多内容&…

C++学习实践(一)高频面试问题总结(附详细答案)

文章目录 一、基础常见面试题1、数组和链表区别2、深拷贝和浅拷贝相关问题的区别3、a和a区别4、c内存模型5、四种强制转换和应用场景 二、指针相关1、指针和引用的区别2、函数指针和指针函数3、传指针、引用和值4、常量指针和指针常量5、野指针6、智能指针的用法 三、关键字作用…

YOLOv8可视化:引入多种可视化CAM方法,为科研保驾护航

💡💡💡本文内容:调用pytorch下的CAM可视化库,支持十多种可视化方法,打开“黑盒”,让YOLOv8变得相对可解释性 收录 YOLOv8原创自研 https://blog.csdn.net/m0_63774211/category_12511737.html?spm=1001.2014.3001.5482 💡💡💡全网独家首发创新(原创),适…

桥接模式-举例

概叙&#xff1a;桥接模式用一种巧妙的方式处理多层继承存在的问题&#xff0c; 用抽象关联取代了传统的多层继承&#xff0c; 将类之间的静态继承关系转换为动态的对象组合关系&#xff0c; 使得系统更加灵活&#xff0c;并易于扩展&#xff0c; 同时有效控制了系统中类的个数…

企业如何购买腾讯云服务器?(详细指南)

腾讯云服务器购买流程直接在官方秒杀活动上购买比较划算&#xff0c;在云服务器CVM或轻量应用服务器页面自定义购买价格比较贵&#xff0c;但是自定义购买云服务器CPU内存带宽配置选择范围广&#xff0c;活动上购买只能选择固定的活动机&#xff0c;选择范围窄&#xff0c;但是…

专题四:前缀和

前缀和 一.一维前缀和(模板)&#xff1a;1.思路一&#xff1a;暴力解法2.思路二&#xff1a;前缀和思路 二. 二维前缀和(模板)&#xff1a;1.思路一&#xff1a;构造前缀和数组 三.寻找数组的中心下标&#xff1a;1.思路一&#xff1a;前缀和 四.除自身以外数组的乘积&#xff…

php最常出现的错误

目录 1. E_WARNING&#xff1a;为 foreach &#xff08;&#xff09;提供的参数无效 2. PDOException&#xff1a;拒绝SQLSTATEHY000连接 3.错误使用empty函数 1. E_WARNING&#xff1a;为 foreach &#xff08;&#xff09;提供的参数无效 PHP foreach构造在PHP 4中引入&am…

web3方向产品调研

每次互联网形态的改变&#xff0c;都会对世界产生很大的影响&#xff0c;上一次对社会产生重大影响的互联网形态&#xff08;Web2.0&#xff09;催生了一批改变人类生活和信息交互方式的企业。 目录 概述DAO是什么&#xff1f;为什么我们需要DAO? 金融服务金融桥接及周边服务D…

Unity中Shader 齐次坐标

文章目录 前言一、什么是齐次坐标二、齐次坐标增加分量 w 的意义1、当 w ≠ \neq  0时&#xff1a;2、当 w 0时&#xff1a;3、用方程组&#xff0c;直观的看一下w的意义 前言 在之前的文章中&#xff0c;我们进行了正交相机视图空间转化到裁剪空间的推导。 Unity中Shade…

3DMAX 中的 VR 渲染器如何设置局部区域渲染?

3DMAX 中的 VR 渲染器如何设置局部渲染&#xff1f; 首先我们要得打开渲染设置&#xff0c;在3damx里按F10&#xff0c;调出渲染设置。选定渲染器为Vary渲染器&#xff1a; 设置VR的局部渲染&#xff0c;需要打开帧缓冲&#xff0c;我们在V-ary项下&#xff0c;打开帧缓冲(点击…

腾讯云服务器怎么买划算?最新优惠价格表

2023腾讯云轻量应用服务器优惠价格表&#xff0c;12月最新报价&#xff0c;腾讯云轻量2核2G3M带宽62元一年、2核2G4M轻量服务器118元一年&#xff0c;540元三年、2核4G5M带宽218元一年&#xff0c;756元三年、4核8G12M轻量服务器646元15个月&#xff0c;CVM云服务器S5实例2核2G…

六、Redis 分布式系统

六、Redis 分布式系统 六、Redis 分布式系统6.1 数据分区算法6.1.1 顺序分区6.1.2 哈希分区 6.2 系统搭建与运行6.2.1 系统搭建6.2.2 系统启动与关闭 6.3 集群操作6.3.1 连接集群6.3.2 写入数据6.3.3 集群查询6.3.4 故障转移6.3.5 集群扩容6.3.6 集群收缩 6.4 分布式系统的限制…

vue整理面试题

1. v-if/v-show的区别? v-if"表达式" 当表达式值true&#xff0c;v-if所作用的元素显示 否则隐藏 v-show"表达式" 当表达式值true&#xff0c;v-if所作用的元素显示 否则隐藏 理解&#xff1a; v-if控制元素显示与隐藏&#xff0c;通过js创建dom元素或删除…